@@ -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( ) ,
@@ -2206,42 +2207,61 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
2206
2207
// generated regardless of trailing bytes that end up in it.
2207
2208
2208
2209
pub struct EncodedMetadata {
2209
- // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2210
- mmap : Option < Mmap > ,
2210
+ // The declaration order matters because `full_mmap` should be dropped
2211
+ // before `_temp_dir`.
2212
+ full_mmap : Option < Mmap > ,
2213
+ reference : Option < Vec < u8 > > ,
2211
2214
// We need to carry MaybeTempDir to avoid deleting the temporary
2212
2215
// directory while accessing the Mmap.
2213
2216
_temp_dir : Option < MaybeTempDir > ,
2214
2217
}
2215
2218
2216
2219
impl EncodedMetadata {
2217
2220
#[ inline]
2218
- pub fn from_path ( path : PathBuf , temp_dir : Option < MaybeTempDir > ) -> std:: io:: Result < Self > {
2221
+ pub fn from_path (
2222
+ path : PathBuf ,
2223
+ reference_path : PathBuf ,
2224
+ temp_dir : Option < MaybeTempDir > ,
2225
+ ) -> std:: io:: Result < Self > {
2219
2226
let file = std:: fs:: File :: open ( & path) ?;
2220
2227
let file_metadata = file. metadata ( ) ?;
2221
2228
if file_metadata. len ( ) == 0 {
2222
- return Ok ( Self { mmap : None , _temp_dir : None } ) ;
2229
+ return Ok ( Self { full_mmap : None , reference : None , _temp_dir : None } ) ;
2223
2230
}
2224
- let mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2225
- Ok ( Self { mmap, _temp_dir : temp_dir } )
2231
+ let full_mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2232
+
2233
+ let reference = std:: fs:: read ( reference_path) ?;
2234
+ let reference = if reference. is_empty ( ) { None } else { Some ( reference) } ;
2235
+
2236
+ Ok ( Self { full_mmap, reference, _temp_dir : temp_dir } )
2237
+ }
2238
+
2239
+ #[ inline]
2240
+ pub fn full ( & self ) -> & [ u8 ] {
2241
+ & self . full_mmap . as_deref ( ) . unwrap_or_default ( )
2226
2242
}
2227
2243
2228
2244
#[ inline]
2229
- pub fn raw_data ( & self ) -> & [ u8 ] {
2230
- self . mmap . as_deref ( ) . unwrap_or_default ( )
2245
+ pub fn maybe_reference ( & self ) -> & [ u8 ] {
2246
+ self . reference . as_deref ( ) . unwrap_or ( self . full ( ) )
2231
2247
}
2232
2248
}
2233
2249
2234
2250
impl < S : Encoder > Encodable < S > for EncodedMetadata {
2235
2251
fn encode ( & self , s : & mut S ) {
2236
- let slice = self . raw_data ( ) ;
2252
+ self . reference . encode ( s) ;
2253
+
2254
+ let slice = self . full ( ) ;
2237
2255
slice. encode ( s)
2238
2256
}
2239
2257
}
2240
2258
2241
2259
impl < D : Decoder > Decodable < D > for EncodedMetadata {
2242
2260
fn decode ( d : & mut D ) -> Self {
2261
+ let reference = <Option < Vec < u8 > > >:: decode ( d) ;
2262
+
2243
2263
let len = d. read_usize ( ) ;
2244
- let mmap = if len > 0 {
2264
+ let full_mmap = if len > 0 {
2245
2265
let mut mmap = MmapMut :: map_anon ( len) . unwrap ( ) ;
2246
2266
for _ in 0 ..len {
2247
2267
( & mut mmap[ ..] ) . write_all ( & [ d. read_u8 ( ) ] ) . unwrap ( ) ;
@@ -2252,11 +2272,11 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
2252
2272
None
2253
2273
} ;
2254
2274
2255
- Self { mmap , _temp_dir : None }
2275
+ Self { full_mmap , reference , _temp_dir : None }
2256
2276
}
2257
2277
}
2258
2278
2259
- pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path ) {
2279
+ pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path , ref_path : & Path ) {
2260
2280
let _prof_timer = tcx. prof . verbose_generic_activity ( "generate_crate_metadata" ) ;
2261
2281
2262
2282
// Since encoding metadata is not in a query, and nothing is cached,
@@ -2270,6 +2290,44 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2270
2290
join ( || prefetch_mir ( tcx) , || tcx. exported_symbols ( LOCAL_CRATE ) ) ;
2271
2291
}
2272
2292
2293
+ with_encode_metadata_header ( tcx, path, |ecx| {
2294
+ // Encode all the entries and extra information in the crate,
2295
+ // culminating in the `CrateRoot` which points to all of it.
2296
+ let root = ecx. encode_crate_root ( ) ;
2297
+
2298
+ // Flush buffer to ensure backing file has the correct size.
2299
+ ecx. opaque . flush ( ) ;
2300
+ // Record metadata size for self-profiling
2301
+ tcx. prof . artifact_size (
2302
+ "crate_metadata" ,
2303
+ "crate_metadata" ,
2304
+ ecx. opaque . file ( ) . metadata ( ) . unwrap ( ) . len ( ) ,
2305
+ ) ;
2306
+
2307
+ root. position . get ( )
2308
+ } ) ;
2309
+
2310
+ if tcx. sess . opts . unstable_opts . split_metadata
2311
+ && !tcx. crate_types ( ) . contains ( & CrateType :: ProcMacro )
2312
+ {
2313
+ with_encode_metadata_header ( tcx, ref_path, |ecx| {
2314
+ let header: LazyValue < CrateHeader > = ecx. lazy ( CrateHeader {
2315
+ name : tcx. crate_name ( LOCAL_CRATE ) ,
2316
+ triple : tcx. sess . opts . target_triple . clone ( ) ,
2317
+ hash : tcx. crate_hash ( LOCAL_CRATE ) ,
2318
+ is_proc_macro_crate : false ,
2319
+ is_reference : true ,
2320
+ } ) ;
2321
+ header. position . get ( )
2322
+ } ) ;
2323
+ }
2324
+ }
2325
+
2326
+ fn with_encode_metadata_header (
2327
+ tcx : TyCtxt < ' _ > ,
2328
+ path : & Path ,
2329
+ f : impl FnOnce ( & mut EncodeContext < ' _ , ' _ > ) -> usize ,
2330
+ ) {
2273
2331
let mut encoder = opaque:: FileEncoder :: new ( path)
2274
2332
. unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
2275
2333
encoder. emit_raw_bytes ( METADATA_HEADER ) ;
@@ -2304,9 +2362,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2304
2362
// Encode the rustc version string in a predictable location.
2305
2363
rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
2306
2364
2307
- // Encode all the entries and extra information in the crate,
2308
- // culminating in the `CrateRoot` which points to all of it.
2309
- let root = ecx. encode_crate_root ( ) ;
2365
+ let root_position = f ( & mut ecx) ;
2310
2366
2311
2367
// Make sure we report any errors from writing to the file.
2312
2368
// If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2316,12 +2372,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2316
2372
}
2317
2373
2318
2374
let file = ecx. opaque . file ( ) ;
2319
- if let Err ( err) = encode_root_position ( file, root . position . get ( ) ) {
2375
+ if let Err ( err) = encode_root_position ( file, root_position ) {
2320
2376
tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
2321
2377
}
2322
-
2323
- // Record metadata size for self-profiling
2324
- tcx. prof . artifact_size ( "crate_metadata" , "crate_metadata" , file. metadata ( ) . unwrap ( ) . len ( ) ) ;
2325
2378
}
2326
2379
2327
2380
fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
0 commit comments