@@ -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,64 @@ 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 : Option < 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 = if let Some ( reference_path) = reference_path {
2254
+ Some ( std:: fs:: read ( reference_path) ?)
2255
+ } else {
2256
+ None
2257
+ } ;
2258
+
2259
+ Ok ( Self { full_mmap, reference, _temp_dir : temp_dir } )
2246
2260
}
2247
2261
2248
2262
#[ inline]
2249
- pub fn raw_data ( & self ) -> & [ u8 ] {
2250
- self . mmap . as_deref ( ) . unwrap_or_default ( )
2263
+ pub fn full ( & self ) -> & [ u8 ] {
2264
+ & self . full_mmap . as_deref ( ) . unwrap_or_default ( )
2265
+ }
2266
+
2267
+ #[ inline]
2268
+ pub fn maybe_reference ( & self ) -> & [ u8 ] {
2269
+ self . reference . as_deref ( ) . unwrap_or ( self . full ( ) )
2251
2270
}
2252
2271
}
2253
2272
2254
2273
impl < S : Encoder > Encodable < S > for EncodedMetadata {
2255
2274
fn encode ( & self , s : & mut S ) {
2256
- let slice = self . raw_data ( ) ;
2275
+ self . reference . encode ( s) ;
2276
+
2277
+ let slice = self . full ( ) ;
2257
2278
slice. encode ( s)
2258
2279
}
2259
2280
}
2260
2281
2261
2282
impl < D : Decoder > Decodable < D > for EncodedMetadata {
2262
2283
fn decode ( d : & mut D ) -> Self {
2284
+ let reference = <Option < Vec < u8 > > >:: decode ( d) ;
2285
+
2263
2286
let len = d. read_usize ( ) ;
2264
- let mmap = if len > 0 {
2287
+ let full_mmap = if len > 0 {
2265
2288
let mut mmap = MmapMut :: map_anon ( len) . unwrap ( ) ;
2266
2289
for _ in 0 ..len {
2267
2290
( & mut mmap[ ..] ) . write_all ( & [ d. read_u8 ( ) ] ) . unwrap ( ) ;
@@ -2272,11 +2295,11 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
2272
2295
None
2273
2296
} ;
2274
2297
2275
- Self { mmap , _temp_dir : None }
2298
+ Self { full_mmap , reference , _temp_dir : None }
2276
2299
}
2277
2300
}
2278
2301
2279
- pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path ) {
2302
+ pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path , ref_path : Option < & Path > ) {
2280
2303
let _prof_timer = tcx. prof . verbose_generic_activity ( "generate_crate_metadata" ) ;
2281
2304
2282
2305
// Since encoding metadata is not in a query, and nothing is cached,
@@ -2290,6 +2313,42 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2290
2313
join ( || prefetch_mir ( tcx) , || tcx. exported_symbols ( LOCAL_CRATE ) ) ;
2291
2314
}
2292
2315
2316
+ with_encode_metadata_header ( tcx, path, |ecx| {
2317
+ // Encode all the entries and extra information in the crate,
2318
+ // culminating in the `CrateRoot` which points to all of it.
2319
+ let root = ecx. encode_crate_root ( ) ;
2320
+
2321
+ // Flush buffer to ensure backing file has the correct size.
2322
+ ecx. opaque . flush ( ) ;
2323
+ // Record metadata size for self-profiling
2324
+ tcx. prof . artifact_size (
2325
+ "crate_metadata" ,
2326
+ "crate_metadata" ,
2327
+ ecx. opaque . file ( ) . metadata ( ) . unwrap ( ) . len ( ) ,
2328
+ ) ;
2329
+
2330
+ root. position . get ( )
2331
+ } ) ;
2332
+
2333
+ if let Some ( ref_path) = ref_path {
2334
+ with_encode_metadata_header ( tcx, ref_path, |ecx| {
2335
+ let header: LazyValue < CrateHeader > = ecx. lazy ( CrateHeader {
2336
+ name : tcx. crate_name ( LOCAL_CRATE ) ,
2337
+ triple : tcx. sess . opts . target_triple . clone ( ) ,
2338
+ hash : tcx. crate_hash ( LOCAL_CRATE ) ,
2339
+ is_proc_macro_crate : false ,
2340
+ is_reference : true ,
2341
+ } ) ;
2342
+ header. position . get ( )
2343
+ } ) ;
2344
+ }
2345
+ }
2346
+
2347
+ fn with_encode_metadata_header (
2348
+ tcx : TyCtxt < ' _ > ,
2349
+ path : & Path ,
2350
+ f : impl FnOnce ( & mut EncodeContext < ' _ , ' _ > ) -> usize ,
2351
+ ) {
2293
2352
let mut encoder = opaque:: FileEncoder :: new ( path)
2294
2353
. unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
2295
2354
encoder. emit_raw_bytes ( METADATA_HEADER ) ;
@@ -2324,9 +2383,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2324
2383
// Encode the rustc version string in a predictable location.
2325
2384
rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
2326
2385
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 ( ) ;
2386
+ let root_position = f ( & mut ecx) ;
2330
2387
2331
2388
// Make sure we report any errors from writing to the file.
2332
2389
// If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2336,12 +2393,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2336
2393
}
2337
2394
2338
2395
let file = ecx. opaque . file ( ) ;
2339
- if let Err ( err) = encode_root_position ( file, root . position . get ( ) ) {
2396
+ if let Err ( err) = encode_root_position ( file, root_position ) {
2340
2397
tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
2341
2398
}
2342
-
2343
- // Record metadata size for self-profiling
2344
- tcx. prof . artifact_size ( "crate_metadata" , "crate_metadata" , file. metadata ( ) . unwrap ( ) . len ( ) ) ;
2345
2399
}
2346
2400
2347
2401
fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
0 commit comments