@@ -692,6 +692,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
692
692
triple: tcx. sess. opts. target_triple. clone( ) ,
693
693
hash: tcx. crate_hash( LOCAL_CRATE ) ,
694
694
is_proc_macro_crate: proc_macro_data. is_some( ) ,
695
+ is_reference: false ,
695
696
} ,
696
697
extra_filename: tcx. sess. opts. cg. extra_filename. clone( ) ,
697
698
stable_crate_id: tcx. def_path_hash( LOCAL_CRATE . as_def_id( ) ) . stable_crate_id( ) ,
@@ -2133,42 +2134,61 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
2133
2134
// generated regardless of trailing bytes that end up in it.
2134
2135
2135
2136
pub struct EncodedMetadata {
2136
- // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2137
- mmap : Option < Mmap > ,
2137
+ // The declaration order matters because `full_mmap` should be dropped
2138
+ // before `_temp_dir`.
2139
+ full_mmap : Option < Mmap > ,
2140
+ reference : Option < Vec < u8 > > ,
2138
2141
// We need to carry MaybeTempDir to avoid deleting the temporary
2139
2142
// directory while accessing the Mmap.
2140
2143
_temp_dir : Option < MaybeTempDir > ,
2141
2144
}
2142
2145
2143
2146
impl EncodedMetadata {
2144
2147
#[ inline]
2145
- pub fn from_path ( path : PathBuf , temp_dir : Option < MaybeTempDir > ) -> std:: io:: Result < Self > {
2148
+ pub fn from_path (
2149
+ path : PathBuf ,
2150
+ reference_path : PathBuf ,
2151
+ temp_dir : Option < MaybeTempDir > ,
2152
+ ) -> std:: io:: Result < Self > {
2146
2153
let file = std:: fs:: File :: open ( & path) ?;
2147
2154
let file_metadata = file. metadata ( ) ?;
2148
2155
if file_metadata. len ( ) == 0 {
2149
- return Ok ( Self { mmap : None , _temp_dir : None } ) ;
2156
+ return Ok ( Self { full_mmap : None , reference : None , _temp_dir : None } ) ;
2150
2157
}
2151
- let mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2152
- Ok ( Self { mmap, _temp_dir : temp_dir } )
2158
+ let full_mmap = unsafe { Some ( Mmap :: map ( file) ?) } ;
2159
+
2160
+ let reference = std:: fs:: read ( reference_path) ?;
2161
+ let reference = if reference. is_empty ( ) { None } else { Some ( reference) } ;
2162
+
2163
+ Ok ( Self { full_mmap, reference, _temp_dir : temp_dir } )
2164
+ }
2165
+
2166
+ #[ inline]
2167
+ pub fn full ( & self ) -> & [ u8 ] {
2168
+ & self . full_mmap . as_deref ( ) . unwrap_or_default ( )
2153
2169
}
2154
2170
2155
2171
#[ inline]
2156
- pub fn raw_data ( & self ) -> & [ u8 ] {
2157
- self . mmap . as_deref ( ) . unwrap_or_default ( )
2172
+ pub fn maybe_reference ( & self ) -> & [ u8 ] {
2173
+ self . reference . as_deref ( ) . unwrap_or ( self . full ( ) )
2158
2174
}
2159
2175
}
2160
2176
2161
2177
impl < S : Encoder > Encodable < S > for EncodedMetadata {
2162
2178
fn encode ( & self , s : & mut S ) {
2163
- let slice = self . raw_data ( ) ;
2179
+ self . reference . encode ( s) ;
2180
+
2181
+ let slice = self . full ( ) ;
2164
2182
slice. encode ( s)
2165
2183
}
2166
2184
}
2167
2185
2168
2186
impl < D : Decoder > Decodable < D > for EncodedMetadata {
2169
2187
fn decode ( d : & mut D ) -> Self {
2188
+ let reference = <Option < Vec < u8 > > >:: decode ( d) ;
2189
+
2170
2190
let len = d. read_usize ( ) ;
2171
- let mmap = if len > 0 {
2191
+ let full_mmap = if len > 0 {
2172
2192
let mut mmap = MmapMut :: map_anon ( len) . unwrap ( ) ;
2173
2193
for _ in 0 ..len {
2174
2194
( & mut mmap[ ..] ) . write ( & [ d. read_u8 ( ) ] ) . unwrap ( ) ;
@@ -2179,11 +2199,11 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
2179
2199
None
2180
2200
} ;
2181
2201
2182
- Self { mmap , _temp_dir : None }
2202
+ Self { full_mmap , reference , _temp_dir : None }
2183
2203
}
2184
2204
}
2185
2205
2186
- pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path ) {
2206
+ pub fn encode_metadata ( tcx : TyCtxt < ' _ > , path : & Path , ref_path : & Path ) {
2187
2207
let _prof_timer = tcx. prof . verbose_generic_activity ( "generate_crate_metadata" ) ;
2188
2208
2189
2209
// Since encoding metadata is not in a query, and nothing is cached,
@@ -2197,6 +2217,44 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2197
2217
join ( || prefetch_mir ( tcx) , || tcx. exported_symbols ( LOCAL_CRATE ) ) ;
2198
2218
}
2199
2219
2220
+ with_encode_metadata_header ( tcx, path, |ecx| {
2221
+ // Encode all the entries and extra information in the crate,
2222
+ // culminating in the `CrateRoot` which points to all of it.
2223
+ let root = ecx. encode_crate_root ( ) ;
2224
+
2225
+ // Flush buffer to ensure backing file has the correct size.
2226
+ ecx. opaque . flush ( ) ;
2227
+ // Record metadata size for self-profiling
2228
+ tcx. prof . artifact_size (
2229
+ "crate_metadata" ,
2230
+ "crate_metadata" ,
2231
+ ecx. opaque . file ( ) . metadata ( ) . unwrap ( ) . len ( ) ,
2232
+ ) ;
2233
+
2234
+ root. position . get ( )
2235
+ } ) ;
2236
+
2237
+ if tcx. sess . opts . unstable_opts . split_metadata
2238
+ && !tcx. crate_types ( ) . contains ( & CrateType :: ProcMacro )
2239
+ {
2240
+ with_encode_metadata_header ( tcx, ref_path, |ecx| {
2241
+ let header: LazyValue < CrateHeader > = ecx. lazy ( CrateHeader {
2242
+ name : tcx. crate_name ( LOCAL_CRATE ) ,
2243
+ triple : tcx. sess . opts . target_triple . clone ( ) ,
2244
+ hash : tcx. crate_hash ( LOCAL_CRATE ) ,
2245
+ is_proc_macro_crate : false ,
2246
+ is_reference : true ,
2247
+ } ) ;
2248
+ header. position . get ( )
2249
+ } ) ;
2250
+ }
2251
+ }
2252
+
2253
+ pub fn with_encode_metadata_header (
2254
+ tcx : TyCtxt < ' _ > ,
2255
+ path : & Path ,
2256
+ f : impl FnOnce ( & mut EncodeContext < ' _ , ' _ > ) -> usize ,
2257
+ ) {
2200
2258
let mut encoder = opaque:: FileEncoder :: new ( path)
2201
2259
. unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
2202
2260
encoder. emit_raw_bytes ( METADATA_HEADER ) ;
@@ -2231,9 +2289,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2231
2289
// Encode the rustc version string in a predictable location.
2232
2290
rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
2233
2291
2234
- // Encode all the entries and extra information in the crate,
2235
- // culminating in the `CrateRoot` which points to all of it.
2236
- let root = ecx. encode_crate_root ( ) ;
2292
+ let root_position = f ( & mut ecx) ;
2237
2293
2238
2294
// Make sure we report any errors from writing to the file.
2239
2295
// If we forget this, compilation can succeed with an incomplete rmeta file,
@@ -2243,12 +2299,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2243
2299
}
2244
2300
2245
2301
let file = ecx. opaque . file ( ) ;
2246
- if let Err ( err) = encode_root_position ( file, root . position . get ( ) ) {
2302
+ if let Err ( err) = encode_root_position ( file, root_position ) {
2247
2303
tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
2248
2304
}
2249
-
2250
- // Record metadata size for self-profiling
2251
- tcx. prof . artifact_size ( "crate_metadata" , "crate_metadata" , file. metadata ( ) . unwrap ( ) . len ( ) ) ;
2252
2305
}
2253
2306
2254
2307
fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
0 commit comments