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