@@ -29,6 +29,7 @@ use rustc_hir::LangItem;
29
29
use rustc_middle:: dep_graph:: WorkProduct ;
30
30
use rustc_middle:: middle:: dependency_format:: Dependencies ;
31
31
use rustc_middle:: ty:: query:: { ExternProviders , Providers } ;
32
+ use rustc_serialize:: { opaque, Decodable , Decoder , Encoder } ;
32
33
use rustc_session:: config:: { CrateType , OutputFilenames , OutputType , RUST_CGU_EXT } ;
33
34
use rustc_session:: cstore:: { self , CrateSource } ;
34
35
use rustc_session:: utils:: NativeLibKind ;
@@ -190,3 +191,53 @@ pub fn looks_like_rust_object_file(filename: &str) -> bool {
190
191
// Check if the "inner" extension
191
192
ext2 == Some ( RUST_CGU_EXT )
192
193
}
194
+
195
+ const RLINK_VERSION : u32 = 1 ;
196
+ const RLINK_MAGIC : & [ u8 ] = b"rustlink" ;
197
+
198
+ const RUSTC_VERSION : Option < & str > = option_env ! ( "CFG_VERSION" ) ;
199
+
200
+ impl CodegenResults {
201
+ pub fn serialize_rlink ( codegen_results : & CodegenResults ) -> Vec < u8 > {
202
+ let mut encoder = opaque:: Encoder :: new ( vec ! [ ] ) ;
203
+ encoder. emit_raw_bytes ( RLINK_MAGIC ) . unwrap ( ) ;
204
+ // `emit_raw_bytes` is used to make sure that the version representation does not depend on
205
+ // Encoder's inner representation of `u32`.
206
+ encoder. emit_raw_bytes ( & RLINK_VERSION . to_be_bytes ( ) ) . unwrap ( ) ;
207
+ encoder. emit_str ( RUSTC_VERSION . unwrap ( ) ) . unwrap ( ) ;
208
+
209
+ let mut encoder = rustc_serialize:: opaque:: Encoder :: new ( encoder. into_inner ( ) ) ;
210
+ rustc_serialize:: Encodable :: encode ( codegen_results, & mut encoder) . unwrap ( ) ;
211
+ encoder. into_inner ( )
212
+ }
213
+
214
+ pub fn deserialize_rlink ( data : Vec < u8 > ) -> Result < Self , String > {
215
+ // The Decodable machinery is not used here because it panics if the input data is invalid
216
+ // and because its internal representation may change.
217
+ if !data. starts_with ( RLINK_MAGIC ) {
218
+ return Err ( "The input does not look like a .rlink file" . to_string ( ) ) ;
219
+ }
220
+ let data = & data[ RLINK_MAGIC . len ( ) ..] ;
221
+ if data. len ( ) < 4 {
222
+ return Err ( "The input does not contain version number" . to_string ( ) ) ;
223
+ }
224
+
225
+ let mut version_array: [ u8 ; 4 ] = Default :: default ( ) ;
226
+ version_array. copy_from_slice ( & data[ ..4 ] ) ;
227
+ if u32:: from_be_bytes ( version_array) != RLINK_VERSION {
228
+ return Err ( ".rlink file was produced with encoding version {version_array}, but the current version is {RLINK_VERSION}" . to_string ( ) ) ;
229
+ }
230
+
231
+ let mut decoder = opaque:: Decoder :: new ( & data[ 4 ..] , 0 ) ;
232
+ let rustc_version = decoder. read_str ( ) ;
233
+ let current_version = RUSTC_VERSION . unwrap ( ) ;
234
+ if rustc_version != current_version {
235
+ return Err ( format ! (
236
+ ".rlink file was produced by rustc version {rustc_version}, but the current version is {current_version}."
237
+ ) ) ;
238
+ }
239
+
240
+ let codegen_results = CodegenResults :: decode ( & mut decoder) ;
241
+ Ok ( codegen_results)
242
+ }
243
+ }
0 commit comments