9
9
// except according to those terms.
10
10
11
11
12
- use back:: archive:: Archive ;
12
+ use back:: archive:: { Archive , METADATA_FILENAME } ;
13
13
use back:: rpath;
14
+ use driver:: driver:: CrateTranslation ;
14
15
use driver:: session:: Session ;
15
16
use driver:: session;
16
17
use lib:: llvm:: llvm;
@@ -88,10 +89,11 @@ pub mod write {
88
89
use back:: link:: { output_type_assembly, output_type_bitcode} ;
89
90
use back:: link:: { output_type_exe, output_type_llvm_assembly} ;
90
91
use back:: link:: { output_type_object} ;
92
+ use driver:: driver:: CrateTranslation ;
91
93
use driver:: session:: Session ;
92
94
use driver:: session;
93
95
use lib:: llvm:: llvm;
94
- use lib:: llvm:: { ModuleRef , ContextRef } ;
96
+ use lib:: llvm:: ModuleRef ;
95
97
use lib;
96
98
97
99
use std:: c_str:: ToCStr ;
@@ -101,10 +103,11 @@ pub mod write {
101
103
use std:: str;
102
104
103
105
pub fn run_passes ( sess : Session ,
104
- llcx : ContextRef ,
105
- llmod : ModuleRef ,
106
+ trans : & CrateTranslation ,
106
107
output_type : output_type ,
107
108
output : & Path ) {
109
+ let llmod = trans. module ;
110
+ let llcx = trans. context ;
108
111
unsafe {
109
112
llvm:: LLVMInitializePasses ( ) ;
110
113
@@ -204,12 +207,23 @@ pub mod write {
204
207
} )
205
208
}
206
209
207
- // Create a codegen-specific pass manager to emit the actual
208
- // assembly or object files. This may not end up getting used,
209
- // but we make it anyway for good measure.
210
- let cpm = llvm:: LLVMCreatePassManager ( ) ;
211
- llvm:: LLVMRustAddAnalysisPasses ( tm, cpm, llmod) ;
212
- llvm:: LLVMRustAddLibraryInfo ( cpm, llmod) ;
210
+ // A codegen-specific pass manager is used to generate object
211
+ // files for an LLVM module.
212
+ //
213
+ // Apparently each of these pass managers is a one-shot kind of
214
+ // thing, so we create a new one for each type of output. The
215
+ // pass manager passed to the closure should be ensured to not
216
+ // escape the closure itself, and the manager should only be
217
+ // used once.
218
+ fn with_codegen ( tm : TargetMachineRef , llmod : ModuleRef ,
219
+ f: |PassManagerRef |) {
220
+ let cpm = llvm:: LLVMCreatePassManager ( ) ;
221
+ llvm:: LLVMRustAddAnalysisPasses ( tm, cpm, llmod) ;
222
+ llvm:: LLVMRustAddLibraryInfo ( cpm, llmod) ;
223
+ f ( cpm) ;
224
+ llvm:: LLVMDisposePassManager ( cpm) ;
225
+
226
+ }
213
227
214
228
match output_type {
215
229
output_type_none => { }
@@ -220,20 +234,47 @@ pub mod write {
220
234
}
221
235
output_type_llvm_assembly => {
222
236
output. with_c_str ( |output| {
223
- llvm:: LLVMRustPrintModule ( cpm, llmod, output)
237
+ with_codegen ( tm, llmod, |cpm| {
238
+ llvm:: LLVMRustPrintModule ( cpm, llmod, output) ;
239
+ } )
224
240
} )
225
241
}
226
242
output_type_assembly => {
227
- WriteOutputFile ( sess, tm, cpm, llmod, output, lib:: llvm:: AssemblyFile ) ;
243
+ with_codegen ( tm, llmod, |cpm| {
244
+ WriteOutputFile ( sess, tm, cpm, llmod, output,
245
+ lib:: llvm:: AssemblyFile ) ;
246
+ } ) ;
247
+
248
+ // windows will invoke this function with an assembly output
249
+ // type when it's actually generating an object file. This
250
+ // is because g++ is used to compile the assembly instead of
251
+ // having LLVM directly output an object file. Regardless,
252
+ // in this case, we're going to possibly need a metadata
253
+ // file.
254
+ if sess. opts . output_type != output_type_assembly {
255
+ with_codegen ( tm, trans. metadata_module , |cpm| {
256
+ let out = output. with_extension ( "metadata.o" ) ;
257
+ WriteOutputFile ( sess, tm, cpm,
258
+ trans. metadata_module , & out,
259
+ lib:: llvm:: ObjectFile ) ;
260
+ } )
261
+ }
228
262
}
229
263
output_type_exe | output_type_object => {
230
- WriteOutputFile ( sess, tm, cpm, llmod, output, lib:: llvm:: ObjectFile ) ;
264
+ with_codegen ( tm, llmod, |cpm| {
265
+ WriteOutputFile ( sess, tm, cpm, llmod, output,
266
+ lib:: llvm:: ObjectFile ) ;
267
+ } ) ;
268
+ with_codegen ( tm, trans. metadata_module , |cpm| {
269
+ WriteOutputFile ( sess, tm, cpm, trans. metadata_module ,
270
+ & output. with_extension ( "metadata.o" ) ,
271
+ lib:: llvm:: ObjectFile ) ;
272
+ } )
231
273
}
232
274
}
233
275
234
- llvm:: LLVMDisposePassManager ( cpm) ;
235
-
236
276
llvm:: LLVMRustDisposeTargetMachine ( tm) ;
277
+ llvm:: LLVMDisposeModule ( trans. metadata_module ) ;
237
278
llvm:: LLVMDisposeModule ( llmod) ;
238
279
llvm:: LLVMContextDispose ( llcx) ;
239
280
if sess. time_llvm_passes ( ) { llvm:: LLVMRustPrintPassTimings ( ) ; }
@@ -782,10 +823,9 @@ pub fn get_cc_prog(sess: Session) -> ~str {
782
823
/// Perform the linkage portion of the compilation phase. This will generate all
783
824
/// of the requested outputs for this compilation session.
784
825
pub fn link_binary ( sess : Session ,
785
- crate_types : & [ ~ str ] ,
826
+ trans : & CrateTranslation ,
786
827
obj_filename : & Path ,
787
- out_filename : & Path ,
788
- lm : LinkMeta ) {
828
+ out_filename : & Path ) {
789
829
let outputs = if sess. opts . test {
790
830
// If we're generating a test executable, then ignore all other output
791
831
// styles at all other locations
@@ -795,7 +835,7 @@ pub fn link_binary(sess: Session,
795
835
// look at what was in the crate file itself for generating output
796
836
// formats.
797
837
let mut outputs = sess. opts . outputs . clone ( ) ;
798
- for ty in crate_types. iter ( ) {
838
+ for ty in trans . crate_types . iter ( ) {
799
839
if "bin" == * ty {
800
840
outputs. push ( session:: OutputExecutable ) ;
801
841
} else if "dylib" == * ty || "lib" == * ty {
@@ -813,12 +853,13 @@ pub fn link_binary(sess: Session,
813
853
} ;
814
854
815
855
for output in outputs. move_iter ( ) {
816
- link_binary_output ( sess, output, obj_filename, out_filename, lm ) ;
856
+ link_binary_output ( sess, trans , output, obj_filename, out_filename) ;
817
857
}
818
858
819
- // Remove the temporary object file if we aren't saving temps
859
+ // Remove the temporary object file and metadata if we aren't saving temps
820
860
if !sess. opts . save_temps {
821
861
fs:: unlink ( obj_filename) ;
862
+ fs:: unlink ( & obj_filename. with_extension ( "metadata.o" ) ) ;
822
863
}
823
864
}
824
865
@@ -832,11 +873,11 @@ fn is_writeable(p: &Path) -> bool {
832
873
}
833
874
834
875
fn link_binary_output ( sess : Session ,
876
+ trans : & CrateTranslation ,
835
877
output : session:: OutputStyle ,
836
878
obj_filename : & Path ,
837
- out_filename : & Path ,
838
- lm : LinkMeta ) {
839
- let libname = output_lib_filename ( lm) ;
879
+ out_filename : & Path ) {
880
+ let libname = output_lib_filename ( trans. link ) ;
840
881
let out_filename = match output {
841
882
session:: OutputRlib => {
842
883
out_filename. with_filename ( format ! ( "lib{}.rlib" , libname) )
@@ -874,7 +915,7 @@ fn link_binary_output(sess: Session,
874
915
875
916
match output {
876
917
session:: OutputRlib => {
877
- link_rlib ( sess, obj_filename, & out_filename) ;
918
+ link_rlib ( sess, Some ( trans ) , obj_filename, & out_filename) ;
878
919
}
879
920
session:: OutputStaticlib => {
880
921
link_staticlib ( sess, obj_filename, & out_filename) ;
@@ -894,9 +935,25 @@ fn link_binary_output(sess: Session,
894
935
// rlib primarily contains the object file of the crate, but it also contains
895
936
// all of the object files from native libraries. This is done by unzipping
896
937
// native libraries and inserting all of the contents into this archive.
897
- fn link_rlib ( sess : Session , obj_filename : & Path ,
938
+ //
939
+ // Instead of putting the metadata in an object file section, instead rlibs
940
+ // contain the metadata in a separate file.
941
+ fn link_rlib ( sess : Session ,
942
+ trans : Option < & CrateTranslation > , // None == no metadata
943
+ obj_filename : & Path ,
898
944
out_filename : & Path ) -> Archive {
899
945
let mut a = Archive :: create ( sess, out_filename, obj_filename) ;
946
+
947
+ match trans {
948
+ Some ( trans) => {
949
+ let metadata = obj_filename. with_filename ( METADATA_FILENAME ) ;
950
+ fs:: File :: create ( & metadata) . write ( trans. metadata ) ;
951
+ a. add_file ( & metadata) ;
952
+ fs:: unlink ( & metadata) ;
953
+ }
954
+ None => { }
955
+ }
956
+
900
957
for & ( ref l, kind) in cstore:: get_used_libraries ( sess. cstore ) . iter ( ) {
901
958
match kind {
902
959
cstore:: NativeStatic => {
@@ -916,8 +973,12 @@ fn link_rlib(sess: Session, obj_filename: &Path,
916
973
//
917
974
// Additionally, there's no way for us to link dynamic libraries, so we warn
918
975
// about all dynamic library dependencies that they're not linked in.
976
+ //
977
+ // There's no need to include metadata in a static archive, so ensure to not
978
+ // link in the metadata object file (and also don't prepare the archive with a
979
+ // metadata file).
919
980
fn link_staticlib ( sess : Session , obj_filename : & Path , out_filename : & Path ) {
920
- let mut a = link_rlib ( sess, obj_filename, out_filename) ;
981
+ let mut a = link_rlib ( sess, None , obj_filename, out_filename) ;
921
982
a. add_native_library ( "morestack" ) ;
922
983
923
984
let crates = cstore:: get_used_crates ( sess. cstore , cstore:: RequireStatic ) ;
@@ -998,6 +1059,14 @@ fn link_args(sess: Session,
998
1059
~"-o", out_filename. as_str ( ) . unwrap ( ) . to_owned ( ) ,
999
1060
obj_filename. as_str ( ) . unwrap ( ) . to_owned ( ) ] ) ;
1000
1061
1062
+ // When linking a dynamic library, we put the metadata into a section of the
1063
+ // executable. This metadata is in a separate object file from the main
1064
+ // object file, so we link that in here.
1065
+ if dylib {
1066
+ let metadata = obj_filename. with_extension ( "metadata.o" ) ;
1067
+ args. push ( metadata. as_str ( ) . unwrap ( ) . to_owned ( ) ) ;
1068
+ }
1069
+
1001
1070
if sess. targ_cfg . os == abi:: OsLinux {
1002
1071
// GNU-style linkers will use this to omit linking to libraries which
1003
1072
// don't actually fulfill any relocations, but only for libraries which
0 commit comments