@@ -701,6 +701,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
701
701
triple: tcx. sess. opts. target_triple. clone( ) ,
702
702
hash: tcx. crate_hash( LOCAL_CRATE ) ,
703
703
is_proc_macro_crate: proc_macro_data. is_some( ) ,
704
+ is_reference: false ,
704
705
} ,
705
706
extra_filename: tcx. sess. opts. cg. extra_filename. clone( ) ,
706
707
stable_crate_id: tcx. def_path_hash( LOCAL_CRATE . as_def_id( ) ) . stable_crate_id( ) ,
@@ -2226,42 +2227,61 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
2226
2227
// generated regardless of trailing bytes that end up in it.
2227
2228
2228
2229
pub struct EncodedMetadata {
2229
- // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2230
- mmap : Option < Mmap > ,
2230
+ // The declaration order matters because `full_mmap` should be dropped
2231
+ // before `_temp_dir`.
2232
+ full_mmap : Option < Mmap > ,
2233
+ reference : Option < Vec < u8 > > ,
2231
2234
// We need to carry MaybeTempDir to avoid deleting the temporary
2232
2235
// directory while accessing the Mmap.
2233
2236
_temp_dir : Option < MaybeTempDir > ,
2234
2237
}
2235
2238
2236
2239
impl EncodedMetadata {
2237
2240
#[ inline]
2238
- pub fn from_path ( path : PathBuf , temp_dir : Option < MaybeTempDir > ) -> std:: io:: Result < Self > {
2241
+ pub fn from_path (
2242
+ path : PathBuf ,
2243
+ reference_path : PathBuf ,
2244
+ temp_dir : Option < MaybeTempDir > ,
2245
+ ) -> std:: io:: Result < Self > {
2239
2246
let file = std:: fs:: File :: open ( & path) ?;
2240
2247
let file_metadata = file. metadata ( ) ?;
2241
2248
if file_metadata. len ( ) == 0 {
2242
- return Ok ( Self { mmap : None , _temp_dir : None } ) ;
2249
+ return Ok ( Self { full_mmap : None , reference : None , _temp_dir : None } ) ;
2243
2250
}
2244
- let mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2245
- Ok ( Self { mmap, _temp_dir : temp_dir } )
2251
+ let full_mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2252
+
2253
+ let reference = std:: fs:: read ( reference_path) ?;
2254
+ let reference = if reference. is_empty ( ) { None } else { Some ( reference) } ;
2255
+
2256
+ Ok ( Self { full_mmap, reference, _temp_dir : temp_dir } )
2257
+ }
2258
+
2259
+ #[ inline]
2260
+ pub fn full ( & self ) -> & [ u8 ] {
2261
+ & self . full_mmap . as_deref ( ) . unwrap_or_default ( )
2246
2262
}
2247
2263
2248
2264
#[ inline]
2249
- pub fn raw_data ( & self ) -> & [ u8 ] {
2250
- self . mmap . as_deref ( ) . unwrap_or_default ( )
2265
+ pub fn maybe_reference ( & self ) -> & [ u8 ] {
2266
+ self . reference . as_deref ( ) . unwrap_or ( self . full ( ) )
2251
2267
}
2252
2268
}
2253
2269
2254
2270
impl < S : Encoder > Encodable < S > for EncodedMetadata {
2255
2271
fn encode ( & self , s : & mut S ) {
2256
- let slice = self . raw_data ( ) ;
2272
+ self . reference . encode ( s) ;
2273
+
2274
+ let slice = self . full ( ) ;
2257
2275
slice. encode ( s)
2258
2276
}
2259
2277
}
2260
2278
2261
2279
impl < D : Decoder > Decodable < D > for EncodedMetadata {
2262
2280
fn decode ( d : & mut D ) -> Self {
2281
+ let reference = <Option < Vec < u8 > > >:: decode ( d) ;
2282
+
2263
2283
let len = d. read_usize ( ) ;
2264
- let mmap = if len > 0 {
2284
+ let full_mmap = if len > 0 {
2265
2285
let mut mmap = MmapMut :: map_anon ( len) . unwrap ( ) ;
2266
2286
for _ in 0 ..len {
2267
2287
( & mut mmap[ ..] ) . write_all ( & [ d. read_u8 ( ) ] ) . unwrap ( ) ;
@@ -2272,11 +2292,11 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
2272
2292
None
2273
2293
} ;
2274
2294
2275
- Self { mmap , _temp_dir : None }
2295
+ Self { full_mmap , reference , _temp_dir : None }
2276
2296
}
2277
2297
}
2278
2298
2279
- pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path ) {
2299
+ pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path , ref_path : & Path ) {
2280
2300
let _prof_timer = tcx. prof . verbose_generic_activity ( "generate_crate_metadata" ) ;
2281
2301
2282
2302
// Since encoding metadata is not in a query, and nothing is cached,
@@ -2290,6 +2310,44 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2290
2310
join ( || prefetch_mir ( tcx) , || tcx. exported_symbols ( LOCAL_CRATE ) ) ;
2291
2311
}
2292
2312
2313
+ with_encode_metadata_header ( tcx, path, |ecx| {
2314
+ // Encode all the entries and extra information in the crate,
2315
+ // culminating in the `CrateRoot` which points to all of it.
2316
+ let root = ecx. encode_crate_root ( ) ;
2317
+
2318
+ // Flush buffer to ensure backing file has the correct size.
2319
+ ecx. opaque . flush ( ) ;
2320
+ // Record metadata size for self-profiling
2321
+ tcx. prof . artifact_size (
2322
+ "crate_metadata" ,
2323
+ "crate_metadata" ,
2324
+ ecx. opaque . file ( ) . metadata ( ) . unwrap ( ) . len ( ) ,
2325
+ ) ;
2326
+
2327
+ root. position . get ( )
2328
+ } ) ;
2329
+
2330
+ if tcx. sess . opts . unstable_opts . split_metadata
2331
+ && !tcx. crate_types ( ) . contains ( & CrateType :: ProcMacro )
2332
+ {
2333
+ with_encode_metadata_header ( tcx, ref_path, |ecx| {
2334
+ let header: LazyValue < CrateHeader > = ecx. lazy ( CrateHeader {
2335
+ name : tcx. crate_name ( LOCAL_CRATE ) ,
2336
+ triple : tcx. sess . opts . target_triple . clone ( ) ,
2337
+ hash : tcx. crate_hash ( LOCAL_CRATE ) ,
2338
+ is_proc_macro_crate : false ,
2339
+ is_reference : true ,
2340
+ } ) ;
2341
+ header. position . get ( )
2342
+ } ) ;
2343
+ }
2344
+ }
2345
+
2346
+ fn with_encode_metadata_header (
2347
+ tcx : TyCtxt < ' _ > ,
2348
+ path : & Path ,
2349
+ f : impl FnOnce ( & mut EncodeContext < ' _ , ' _ > ) -> usize ,
2350
+ ) {
2293
2351
let mut encoder = opaque:: FileEncoder :: new ( path)
2294
2352
. unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
2295
2353
encoder. emit_raw_bytes ( METADATA_HEADER ) ;
@@ -2324,9 +2382,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2324
2382
// Encode the rustc version string in a predictable location.
2325
2383
rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
2326
2384
2327
- // Encode all the entries and extra information in the crate,
2328
- // culminating in the `CrateRoot` which points to all of it.
2329
- let root = ecx. encode_crate_root ( ) ;
2385
+ let root_position = f ( & mut ecx) ;
2330
2386
2331
2387
// Make sure we report any errors from writing to the file.
2332
2388
// If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2336,12 +2392,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2336
2392
}
2337
2393
2338
2394
let file = ecx. opaque . file ( ) ;
2339
- if let Err ( err) = encode_root_position ( file, root . position . get ( ) ) {
2395
+ if let Err ( err) = encode_root_position ( file, root_position ) {
2340
2396
tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
2341
2397
}
2342
-
2343
- // Record metadata size for self-profiling
2344
- tcx. prof . artifact_size ( "crate_metadata" , "crate_metadata" , file. metadata ( ) . unwrap ( ) . len ( ) ) ;
2345
2398
}
2346
2399
2347
2400
fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
0 commit comments