@@ -700,6 +700,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
700
700
triple: tcx. sess. opts. target_triple. clone( ) ,
701
701
hash: tcx. crate_hash( LOCAL_CRATE ) ,
702
702
is_proc_macro_crate: proc_macro_data. is_some( ) ,
703
+ is_reference: false ,
703
704
} ,
704
705
extra_filename: tcx. sess. opts. cg. extra_filename. clone( ) ,
705
706
stable_crate_id: tcx. def_path_hash( LOCAL_CRATE . as_def_id( ) ) . stable_crate_id( ) ,
@@ -2162,42 +2163,61 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
2162
2163
// generated regardless of trailing bytes that end up in it.
2163
2164
2164
2165
pub struct EncodedMetadata {
2165
- // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2166
- mmap : Option < Mmap > ,
2166
+ // The declaration order matters because `full_mmap` should be dropped
2167
+ // before `_temp_dir`.
2168
+ full_mmap : Option < Mmap > ,
2169
+ reference : Option < Vec < u8 > > ,
2167
2170
// We need to carry MaybeTempDir to avoid deleting the temporary
2168
2171
// directory while accessing the Mmap.
2169
2172
_temp_dir : Option < MaybeTempDir > ,
2170
2173
}
2171
2174
2172
2175
impl EncodedMetadata {
2173
2176
#[ inline]
2174
- pub fn from_path ( path : PathBuf , temp_dir : Option < MaybeTempDir > ) -> std:: io:: Result < Self > {
2177
+ pub fn from_path (
2178
+ path : PathBuf ,
2179
+ reference_path : PathBuf ,
2180
+ temp_dir : Option < MaybeTempDir > ,
2181
+ ) -> std:: io:: Result < Self > {
2175
2182
let file = std:: fs:: File :: open ( & path) ?;
2176
2183
let file_metadata = file. metadata ( ) ?;
2177
2184
if file_metadata. len ( ) == 0 {
2178
- return Ok ( Self { mmap : None , _temp_dir : None } ) ;
2185
+ return Ok ( Self { full_mmap : None , reference : None , _temp_dir : None } ) ;
2179
2186
}
2180
- let mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2181
- Ok ( Self { mmap, _temp_dir : temp_dir } )
2187
+ let full_mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2188
+
2189
+ let reference = std:: fs:: read ( reference_path) ?;
2190
+ let reference = if reference. is_empty ( ) { None } else { Some ( reference) } ;
2191
+
2192
+ Ok ( Self { full_mmap, reference, _temp_dir : temp_dir } )
2193
+ }
2194
+
2195
+ #[ inline]
2196
+ pub fn full ( & self ) -> & [ u8 ] {
2197
+ & self . full_mmap . as_deref ( ) . unwrap_or_default ( )
2182
2198
}
2183
2199
2184
2200
#[ inline]
2185
- pub fn raw_data ( & self ) -> & [ u8 ] {
2186
- self . mmap . as_deref ( ) . unwrap_or_default ( )
2201
+ pub fn maybe_reference ( & self ) -> & [ u8 ] {
2202
+ self . reference . as_deref ( ) . unwrap_or ( self . full ( ) )
2187
2203
}
2188
2204
}
2189
2205
2190
2206
impl < S : Encoder > Encodable < S > for EncodedMetadata {
2191
2207
fn encode ( & self , s : & mut S ) {
2192
- let slice = self . raw_data ( ) ;
2208
+ self . reference . encode ( s) ;
2209
+
2210
+ let slice = self . full ( ) ;
2193
2211
slice. encode ( s)
2194
2212
}
2195
2213
}
2196
2214
2197
2215
impl < D : Decoder > Decodable < D > for EncodedMetadata {
2198
2216
fn decode ( d : & mut D ) -> Self {
2217
+ let reference = <Option < Vec < u8 > > >:: decode ( d) ;
2218
+
2199
2219
let len = d. read_usize ( ) ;
2200
- let mmap = if len > 0 {
2220
+ let full_mmap = if len > 0 {
2201
2221
let mut mmap = MmapMut :: map_anon ( len) . unwrap ( ) ;
2202
2222
for _ in 0 ..len {
2203
2223
( & mut mmap[ ..] ) . write_all ( & [ d. read_u8 ( ) ] ) . unwrap ( ) ;
@@ -2208,11 +2228,11 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
2208
2228
None
2209
2229
} ;
2210
2230
2211
- Self { mmap , _temp_dir : None }
2231
+ Self { full_mmap , reference , _temp_dir : None }
2212
2232
}
2213
2233
}
2214
2234
2215
- pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path ) {
2235
+ pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path , ref_path : & Path ) {
2216
2236
let _prof_timer = tcx. prof . verbose_generic_activity ( "generate_crate_metadata" ) ;
2217
2237
2218
2238
// Since encoding metadata is not in a query, and nothing is cached,
@@ -2226,6 +2246,44 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2226
2246
join ( || prefetch_mir ( tcx) , || tcx. exported_symbols ( LOCAL_CRATE ) ) ;
2227
2247
}
2228
2248
2249
+ with_encode_metadata_header ( tcx, path, |ecx| {
2250
+ // Encode all the entries and extra information in the crate,
2251
+ // culminating in the `CrateRoot` which points to all of it.
2252
+ let root = ecx. encode_crate_root ( ) ;
2253
+
2254
+ // Flush buffer to ensure backing file has the correct size.
2255
+ ecx. opaque . flush ( ) ;
2256
+ // Record metadata size for self-profiling
2257
+ tcx. prof . artifact_size (
2258
+ "crate_metadata" ,
2259
+ "crate_metadata" ,
2260
+ ecx. opaque . file ( ) . metadata ( ) . unwrap ( ) . len ( ) ,
2261
+ ) ;
2262
+
2263
+ root. position . get ( )
2264
+ } ) ;
2265
+
2266
+ if tcx. sess . opts . unstable_opts . split_metadata
2267
+ && !tcx. crate_types ( ) . contains ( & CrateType :: ProcMacro )
2268
+ {
2269
+ with_encode_metadata_header ( tcx, ref_path, |ecx| {
2270
+ let header: LazyValue < CrateHeader > = ecx. lazy ( CrateHeader {
2271
+ name : tcx. crate_name ( LOCAL_CRATE ) ,
2272
+ triple : tcx. sess . opts . target_triple . clone ( ) ,
2273
+ hash : tcx. crate_hash ( LOCAL_CRATE ) ,
2274
+ is_proc_macro_crate : false ,
2275
+ is_reference : true ,
2276
+ } ) ;
2277
+ header. position . get ( )
2278
+ } ) ;
2279
+ }
2280
+ }
2281
+
2282
+ pub fn with_encode_metadata_header (
2283
+ tcx : TyCtxt < ' _ > ,
2284
+ path : & Path ,
2285
+ f : impl FnOnce ( & mut EncodeContext < ' _ , ' _ > ) -> usize ,
2286
+ ) {
2229
2287
let mut encoder = opaque:: FileEncoder :: new ( path)
2230
2288
. unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
2231
2289
encoder. emit_raw_bytes ( METADATA_HEADER ) ;
@@ -2260,9 +2318,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2260
2318
// Encode the rustc version string in a predictable location.
2261
2319
rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
2262
2320
2263
- // Encode all the entries and extra information in the crate,
2264
- // culminating in the `CrateRoot` which points to all of it.
2265
- let root = ecx. encode_crate_root ( ) ;
2321
+ let root_position = f ( & mut ecx) ;
2266
2322
2267
2323
// Make sure we report any errors from writing to the file.
2268
2324
// If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2272,12 +2328,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2272
2328
}
2273
2329
2274
2330
let file = ecx. opaque . file ( ) ;
2275
- if let Err ( err) = encode_root_position ( file, root . position . get ( ) ) {
2331
+ if let Err ( err) = encode_root_position ( file, root_position ) {
2276
2332
tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
2277
2333
}
2278
-
2279
- // Record metadata size for self-profiling
2280
- tcx. prof . artifact_size ( "crate_metadata" , "crate_metadata" , file. metadata ( ) . unwrap ( ) . len ( ) ) ;
2281
2334
}
2282
2335
2283
2336
fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
0 commit comments