@@ -29,6 +29,7 @@ use rustc_hir::LangItem;
2929use rustc_middle:: dep_graph:: WorkProduct ;
3030use rustc_middle:: middle:: dependency_format:: Dependencies ;
3131use rustc_middle:: ty:: query:: { ExternProviders , Providers } ;
32+ use rustc_serialize:: { opaque, Decodable , Decoder , Encoder } ;
3233use rustc_session:: config:: { CrateType , OutputFilenames , OutputType , RUST_CGU_EXT } ;
3334use rustc_session:: cstore:: { self , CrateSource } ;
3435use rustc_session:: utils:: NativeLibKind ;
@@ -190,3 +191,53 @@ pub fn looks_like_rust_object_file(filename: &str) -> bool {
190191 // Check if the "inner" extension
191192 ext2 == Some ( RUST_CGU_EXT )
192193}
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