@@ -701,6 +701,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
701701 triple: tcx. sess. opts. target_triple. clone( ) ,
702702 hash: tcx. crate_hash( LOCAL_CRATE ) ,
703703 is_proc_macro_crate: proc_macro_data. is_some( ) ,
704+ is_reference: false ,
704705 } ,
705706 extra_filename: tcx. sess. opts. cg. extra_filename. clone( ) ,
706707 stable_crate_id: tcx. def_path_hash( LOCAL_CRATE . as_def_id( ) ) . stable_crate_id( ) ,
@@ -2198,42 +2199,61 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
21982199// generated regardless of trailing bytes that end up in it.
21992200
22002201pub 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 > > ,
22032206 // We need to carry MaybeTempDir to avoid deleting the temporary
22042207 // directory while accessing the Mmap.
22052208 _temp_dir : Option < MaybeTempDir > ,
22062209}
22072210
22082211impl EncodedMetadata {
22092212 #[ 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 > {
22112218 let file = std:: fs:: File :: open ( & path) ?;
22122219 let file_metadata = file. metadata ( ) ?;
22132220 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 } ) ;
22152222 }
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 ( )
22182234 }
22192235
22202236 #[ 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 ( ) )
22232239 }
22242240}
22252241
22262242impl < S : Encoder > Encodable < S > for EncodedMetadata {
22272243 fn encode ( & self , s : & mut S ) {
2228- let slice = self . raw_data ( ) ;
2244+ self . reference . encode ( s) ;
2245+
2246+ let slice = self . full ( ) ;
22292247 slice. encode ( s)
22302248 }
22312249}
22322250
22332251impl < D : Decoder > Decodable < D > for EncodedMetadata {
22342252 fn decode ( d : & mut D ) -> Self {
2253+ let reference = <Option < Vec < u8 > > >:: decode ( d) ;
2254+
22352255 let len = d. read_usize ( ) ;
2236- let mmap = if len > 0 {
2256+ let full_mmap = if len > 0 {
22372257 let mut mmap = MmapMut :: map_anon ( len) . unwrap ( ) ;
22382258 for _ in 0 ..len {
22392259 ( & mut mmap[ ..] ) . write_all ( & [ d. read_u8 ( ) ] ) . unwrap ( ) ;
@@ -2244,11 +2264,11 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
22442264 None
22452265 } ;
22462266
2247- Self { mmap , _temp_dir : None }
2267+ Self { full_mmap , reference , _temp_dir : None }
22482268 }
22492269}
22502270
2251- pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path ) {
2271+ pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path , ref_path : & Path ) {
22522272 let _prof_timer = tcx. prof . verbose_generic_activity ( "generate_crate_metadata" ) ;
22532273
22542274 // Since encoding metadata is not in a query, and nothing is cached,
@@ -2262,6 +2282,44 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
22622282 join ( || prefetch_mir ( tcx) , || tcx. exported_symbols ( LOCAL_CRATE ) ) ;
22632283 }
22642284
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+ ) {
22652323 let mut encoder = opaque:: FileEncoder :: new ( path)
22662324 . unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
22672325 encoder. emit_raw_bytes ( METADATA_HEADER ) ;
@@ -2296,9 +2354,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
22962354 // Encode the rustc version string in a predictable location.
22972355 rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
22982356
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) ;
23022358
23032359 // Make sure we report any errors from writing to the file.
23042360 // If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2308,12 +2364,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
23082364 }
23092365
23102366 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 ) {
23122368 tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
23132369 }
2314-
2315- // Record metadata size for self-profiling
2316- tcx. prof . artifact_size ( "crate_metadata" , "crate_metadata" , file. metadata ( ) . unwrap ( ) . len ( ) ) ;
23172370}
23182371
23192372fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
0 commit comments