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;
@@ -191,10 +192,11 @@ pub mod write {
191
192
use back:: link:: { output_type_assembly, output_type_bitcode} ;
192
193
use back:: link:: { output_type_exe, output_type_llvm_assembly} ;
193
194
use back:: link:: { output_type_object} ;
195
+ use driver:: driver:: CrateTranslation ;
194
196
use driver:: session:: Session ;
195
197
use driver:: session;
196
198
use lib:: llvm:: llvm;
197
- use lib:: llvm:: { ModuleRef , ContextRef } ;
199
+ use lib:: llvm:: ModuleRef ;
198
200
use lib;
199
201
200
202
use std:: c_str:: ToCStr ;
@@ -204,10 +206,11 @@ pub mod write {
204
206
use std:: str;
205
207
206
208
pub fn run_passes ( sess : Session ,
207
- llcx : ContextRef ,
208
- llmod : ModuleRef ,
209
+ trans : & CrateTranslation ,
209
210
output_type : output_type ,
210
211
output : & Path ) {
212
+ let llmod = trans. module ;
213
+ let llcx = trans. context ;
211
214
unsafe {
212
215
llvm:: LLVMInitializePasses ( ) ;
213
216
@@ -313,12 +316,23 @@ pub mod write {
313
316
// context, so don't dispose
314
317
jit:: exec ( sess, llcx, llmod, true ) ;
315
318
} else {
316
- // Create a codegen-specific pass manager to emit the actual
317
- // assembly or object files. This may not end up getting used,
318
- // but we make it anyway for good measure.
319
- let cpm = llvm:: LLVMCreatePassManager ( ) ;
320
- llvm:: LLVMRustAddAnalysisPasses ( tm, cpm, llmod) ;
321
- llvm:: LLVMRustAddLibraryInfo ( cpm, llmod) ;
319
+ // A codegen-specific pass manager is used to generate object
320
+ // files for an LLVM module.
321
+ //
322
+ // Apparently each of these pass managers is a one-shot kind of
323
+ // thing, so we create a new one for each type of output. The
324
+ // pass manager passed to the closure should be ensured to not
325
+ // escape the closure itself, and the manager should only be
326
+ // used once.
327
+ fn with_codegen ( tm : TargetMachineRef , llmod : ModuleRef ,
328
+ f: |PassManagerRef |) {
329
+ let cpm = llvm:: LLVMCreatePassManager ( ) ;
330
+ llvm:: LLVMRustAddAnalysisPasses ( tm, cpm, llmod) ;
331
+ llvm:: LLVMRustAddLibraryInfo ( cpm, llmod) ;
332
+ f ( cpm) ;
333
+ llvm:: LLVMDisposePassManager ( cpm) ;
334
+
335
+ }
322
336
323
337
match output_type {
324
338
output_type_none => { }
@@ -329,21 +343,48 @@ pub mod write {
329
343
}
330
344
output_type_llvm_assembly => {
331
345
output. with_c_str ( |output| {
332
- llvm:: LLVMRustPrintModule ( cpm, llmod, output)
346
+ with_codegen ( tm, llmod, |cpm| {
347
+ llvm:: LLVMRustPrintModule ( cpm, llmod, output) ;
348
+ } )
333
349
} )
334
350
}
335
351
output_type_assembly => {
336
- WriteOutputFile ( sess, tm, cpm, llmod, output, lib:: llvm:: AssemblyFile ) ;
352
+ with_codegen ( tm, llmod, |cpm| {
353
+ WriteOutputFile ( sess, tm, cpm, llmod, output,
354
+ lib:: llvm:: AssemblyFile ) ;
355
+ } ) ;
356
+
357
+ // windows will invoke this function with an assembly
358
+ // output type when it's actually generating an object
359
+ // file. This is because g++ is used to compile the
360
+ // assembly instead of having LLVM directly output an
361
+ // object file. Regardless, in this case, we're going to
362
+ // possibly need a metadata file.
363
+ if sess. opts . output_type != output_type_assembly {
364
+ with_codegen ( tm, trans. metadata_module , |cpm| {
365
+ let out = output. with_extension ( "metadata.o" ) ;
366
+ WriteOutputFile ( sess, tm, cpm,
367
+ trans. metadata_module , & out,
368
+ lib:: llvm:: ObjectFile ) ;
369
+ } )
370
+ }
337
371
}
338
372
output_type_exe | output_type_object => {
339
- WriteOutputFile ( sess, tm, cpm, llmod, output, lib:: llvm:: ObjectFile ) ;
373
+ with_codegen ( tm, llmod, |cpm| {
374
+ WriteOutputFile ( sess, tm, cpm, llmod, output,
375
+ lib:: llvm:: ObjectFile ) ;
376
+ } ) ;
377
+ with_codegen ( tm, trans. metadata_module , |cpm| {
378
+ WriteOutputFile ( sess, tm, cpm, trans. metadata_module ,
379
+ & output. with_extension ( "metadata.o" ) ,
380
+ lib:: llvm:: ObjectFile ) ;
381
+ } )
340
382
}
341
383
}
342
-
343
- llvm:: LLVMDisposePassManager ( cpm) ;
344
384
}
345
385
346
386
llvm:: LLVMRustDisposeTargetMachine ( tm) ;
387
+ llvm:: LLVMDisposeModule ( trans. metadata_module ) ;
347
388
// the jit takes ownership of these two items
348
389
if !sess. opts . jit {
349
390
llvm:: LLVMDisposeModule ( llmod) ;
@@ -895,10 +936,9 @@ pub fn get_cc_prog(sess: Session) -> ~str {
895
936
/// Perform the linkage portion of the compilation phase. This will generate all
896
937
/// of the requested outputs for this compilation session.
897
938
pub fn link_binary ( sess : Session ,
898
- crate_types : & [ ~ str ] ,
939
+ trans : & CrateTranslation ,
899
940
obj_filename : & Path ,
900
- out_filename : & Path ,
901
- lm : LinkMeta ) {
941
+ out_filename : & Path ) {
902
942
let outputs = if sess. opts . test {
903
943
// If we're generating a test executable, then ignore all other output
904
944
// styles at all other locations
@@ -908,7 +948,7 @@ pub fn link_binary(sess: Session,
908
948
// look at what was in the crate file itself for generating output
909
949
// formats.
910
950
let mut outputs = sess. opts . outputs . clone ( ) ;
911
- for ty in crate_types. iter ( ) {
951
+ for ty in trans . crate_types . iter ( ) {
912
952
if "bin" == * ty {
913
953
outputs. push ( session:: OutputExecutable ) ;
914
954
} else if "dylib" == * ty || "lib" == * ty {
@@ -926,12 +966,13 @@ pub fn link_binary(sess: Session,
926
966
} ;
927
967
928
968
for output in outputs. move_iter ( ) {
929
- link_binary_output ( sess, output, obj_filename, out_filename, lm ) ;
969
+ link_binary_output ( sess, trans , output, obj_filename, out_filename) ;
930
970
}
931
971
932
- // Remove the temporary object file if we aren't saving temps
972
+ // Remove the temporary object file and metadata if we aren't saving temps
933
973
if !sess. opts . save_temps {
934
974
fs:: unlink ( obj_filename) ;
975
+ fs:: unlink ( & obj_filename. with_extension ( "metadata.o" ) ) ;
935
976
}
936
977
}
937
978
@@ -945,11 +986,11 @@ fn is_writeable(p: &Path) -> bool {
945
986
}
946
987
947
988
fn link_binary_output ( sess : Session ,
989
+ trans : & CrateTranslation ,
948
990
output : session:: OutputStyle ,
949
991
obj_filename : & Path ,
950
- out_filename : & Path ,
951
- lm : LinkMeta ) {
952
- let libname = output_lib_filename ( lm) ;
992
+ out_filename : & Path ) {
993
+ let libname = output_lib_filename ( trans. link ) ;
953
994
let out_filename = match output {
954
995
session:: OutputRlib => {
955
996
out_filename. with_filename ( format ! ( "lib{}.rlib" , libname) )
@@ -987,7 +1028,7 @@ fn link_binary_output(sess: Session,
987
1028
988
1029
match output {
989
1030
session:: OutputRlib => {
990
- link_rlib ( sess, obj_filename, & out_filename) ;
1031
+ link_rlib ( sess, Some ( trans ) , obj_filename, & out_filename) ;
991
1032
}
992
1033
session:: OutputStaticlib => {
993
1034
link_staticlib ( sess, obj_filename, & out_filename) ;
@@ -1007,9 +1048,25 @@ fn link_binary_output(sess: Session,
1007
1048
// rlib primarily contains the object file of the crate, but it also contains
1008
1049
// all of the object files from native libraries. This is done by unzipping
1009
1050
// native libraries and inserting all of the contents into this archive.
1010
- fn link_rlib ( sess : Session , obj_filename : & Path ,
1051
+ //
1052
+ // Instead of putting the metadata in an object file section, instead rlibs
1053
+ // contain the metadata in a separate file.
1054
+ fn link_rlib ( sess : Session ,
1055
+ trans : Option < & CrateTranslation > , // None == no metadata
1056
+ obj_filename : & Path ,
1011
1057
out_filename : & Path ) -> Archive {
1012
1058
let mut a = Archive :: create ( sess, out_filename, obj_filename) ;
1059
+
1060
+ match trans {
1061
+ Some ( trans) => {
1062
+ let metadata = obj_filename. with_filename ( METADATA_FILENAME ) ;
1063
+ fs:: File :: create ( & metadata) . write ( trans. metadata ) ;
1064
+ a. add_file ( & metadata) ;
1065
+ fs:: unlink ( & metadata) ;
1066
+ }
1067
+ None => { }
1068
+ }
1069
+
1013
1070
for & ( ref l, kind) in cstore:: get_used_libraries ( sess. cstore ) . iter ( ) {
1014
1071
match kind {
1015
1072
cstore:: NativeStatic => {
@@ -1029,8 +1086,12 @@ fn link_rlib(sess: Session, obj_filename: &Path,
1029
1086
//
1030
1087
// Additionally, there's no way for us to link dynamic libraries, so we warn
1031
1088
// about all dynamic library dependencies that they're not linked in.
1089
+ //
1090
+ // There's no need to include metadata in a static archive, so ensure to not
1091
+ // link in the metadata object file (and also don't prepare the archive with a
1092
+ // metadata file).
1032
1093
fn link_staticlib ( sess : Session , obj_filename : & Path , out_filename : & Path ) {
1033
- let mut a = link_rlib ( sess, obj_filename, out_filename) ;
1094
+ let mut a = link_rlib ( sess, None , obj_filename, out_filename) ;
1034
1095
a. add_native_library ( "morestack" ) ;
1035
1096
1036
1097
let crates = cstore:: get_used_crates ( sess. cstore , cstore:: RequireStatic ) ;
@@ -1111,6 +1172,14 @@ fn link_args(sess: Session,
1111
1172
~"-o", out_filename. as_str ( ) . unwrap ( ) . to_owned ( ) ,
1112
1173
obj_filename. as_str ( ) . unwrap ( ) . to_owned ( ) ] ) ;
1113
1174
1175
+ // When linking a dynamic library, we put the metadata into a section of the
1176
+ // executable. This metadata is in a separate object file from the main
1177
+ // object file, so we link that in here.
1178
+ if dylib {
1179
+ let metadata = obj_filename. with_extension ( "metadata.o" ) ;
1180
+ args. push ( metadata. as_str ( ) . unwrap ( ) . to_owned ( ) ) ;
1181
+ }
1182
+
1114
1183
if sess. targ_cfg . os == abi:: OsLinux {
1115
1184
// GNU-style linkers will use this to omit linking to libraries which
1116
1185
// don't actually fulfill any relocations, but only for libraries which
0 commit comments