1- use rustc:: middle:: cstore:: MetadataLoader ;
2- use rustc_data_structures:: owning_ref:: { self , OwningRef } ;
3- use rustc_data_structures:: rustc_erase_owner;
41use std:: fs:: File ;
52use std:: path:: Path ;
63
4+ use rustc:: session:: config;
5+ use rustc:: ty:: TyCtxt ;
6+ use rustc:: middle:: cstore:: { EncodedMetadata , MetadataLoader } ;
7+ use rustc_data_structures:: owning_ref:: { self , OwningRef } ;
8+ use rustc_data_structures:: rustc_erase_owner;
9+ use rustc_target:: spec:: Target ;
10+
711pub const METADATA_FILENAME : & str = "rust.metadata.bin" ;
812
913pub struct CraneliftMetadataLoader ;
1014
1115impl MetadataLoader for CraneliftMetadataLoader {
1216 fn get_rlib_metadata (
1317 & self ,
14- _target : & crate :: rustc_target :: spec :: Target ,
18+ _target : & Target ,
1519 path : & Path ,
1620 ) -> Result < owning_ref:: ErasedBoxRef < [ u8 ] > , String > {
1721 let mut archive = ar:: Archive :: new ( File :: open ( path) . map_err ( |e| format ! ( "{:?}" , e) ) ?) ;
@@ -32,9 +36,62 @@ impl MetadataLoader for CraneliftMetadataLoader {
3236
3337 fn get_dylib_metadata (
3438 & self ,
35- _target : & crate :: rustc_target :: spec :: Target ,
36- _path : & Path ,
39+ _target : & Target ,
40+ path : & Path ,
3741 ) -> Result < owning_ref:: ErasedBoxRef < [ u8 ] > , String > {
38- Err ( "dylib metadata loading is not yet supported" . to_string ( ) )
42+ use object:: Object ;
43+ let file = std:: fs:: read ( path) . map_err ( |e| format ! ( "read:{:?}" , e) ) ?;
44+ let file = object:: File :: parse ( & file) . map_err ( |e| format ! ( "parse: {:?}" , e) ) ?;
45+ let buf = file. section_data_by_name ( ".rustc" ) . ok_or ( "no .rustc section" ) ?. into_owned ( ) ;
46+ let buf: OwningRef < Vec < u8 > , [ u8 ] > = OwningRef :: new ( buf) . into ( ) ;
47+ Ok ( rustc_erase_owner ! ( buf. map_owner_box( ) ) )
3948 }
4049}
50+
51+ // Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
52+ pub fn write_metadata < ' a , ' gcx > (
53+ tcx : TyCtxt < ' a , ' gcx , ' gcx > ,
54+ artifact : & mut faerie:: Artifact
55+ ) -> EncodedMetadata {
56+ use std:: io:: Write ;
57+ use flate2:: Compression ;
58+ use flate2:: write:: DeflateEncoder ;
59+
60+ #[ derive( PartialEq , Eq , PartialOrd , Ord ) ]
61+ enum MetadataKind {
62+ None ,
63+ Uncompressed ,
64+ Compressed
65+ }
66+
67+ let kind = tcx. sess . crate_types . borrow ( ) . iter ( ) . map ( |ty| {
68+ match * ty {
69+ config:: CrateType :: Executable |
70+ config:: CrateType :: Staticlib |
71+ config:: CrateType :: Cdylib => MetadataKind :: None ,
72+
73+ config:: CrateType :: Rlib => MetadataKind :: Uncompressed ,
74+
75+ config:: CrateType :: Dylib |
76+ config:: CrateType :: ProcMacro => MetadataKind :: Compressed ,
77+ }
78+ } ) . max ( ) . unwrap_or ( MetadataKind :: None ) ;
79+
80+ if kind == MetadataKind :: None {
81+ return EncodedMetadata :: new ( ) ;
82+ }
83+
84+ let metadata = tcx. encode_metadata ( ) ;
85+ if kind == MetadataKind :: Uncompressed {
86+ return metadata;
87+ }
88+
89+ assert ! ( kind == MetadataKind :: Compressed ) ;
90+ let mut compressed = tcx. metadata_encoding_version ( ) ;
91+ DeflateEncoder :: new ( & mut compressed, Compression :: fast ( ) )
92+ . write_all ( & metadata. raw_data ) . unwrap ( ) ;
93+
94+ artifact. declare_with ( ".rustc" , faerie:: Decl :: debug_section ( ) , compressed) . unwrap ( ) ;
95+
96+ metadata
97+ }
0 commit comments