11
11
use back:: bytecode:: { self , RLIB_BYTECODE_EXTENSION } ;
12
12
use back:: lto:: { self , ModuleBuffer , ThinBuffer } ;
13
13
use back:: link:: { self , get_linker, remove} ;
14
+ use back:: command:: Command ;
14
15
use back:: linker:: LinkerInfo ;
15
16
use back:: symbol_export:: ExportedSymbols ;
16
17
use base;
17
18
use consts;
18
19
use rustc_incremental:: { save_trans_partition, in_incr_comp_dir} ;
19
20
use rustc:: dep_graph:: { DepGraph , WorkProductFileKind } ;
20
21
use rustc:: middle:: cstore:: { LinkMeta , EncodedMetadata } ;
21
- use rustc:: session:: config:: { self , OutputFilenames , OutputType , OutputTypes , Passes , SomePasses ,
22
+ use rustc:: session:: config:: { self , OutputFilenames , OutputType , Passes , SomePasses ,
22
23
AllPasses , Sanitizer } ;
23
24
use rustc:: session:: Session ;
24
25
use rustc:: util:: nodemap:: FxHashMap ;
@@ -32,7 +33,7 @@ use CrateInfo;
32
33
use rustc:: hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
33
34
use rustc:: ty:: TyCtxt ;
34
35
use rustc:: util:: common:: { time, time_depth, set_time_depth, path2cstr, print_time_passes_entry} ;
35
- use rustc:: util:: fs:: { link_or_copy, rename_or_copy_remove } ;
36
+ use rustc:: util:: fs:: { link_or_copy} ;
36
37
use errors:: { self , Handler , Level , DiagnosticBuilder , FatalError , DiagnosticId } ;
37
38
use errors:: emitter:: { Emitter } ;
38
39
use syntax:: attr;
@@ -258,6 +259,7 @@ pub struct ModuleConfig {
258
259
// make the object file bitcode. Provides easy compatibility with
259
260
// emscripten's ecc compiler, when used as the linker.
260
261
obj_is_bitcode : bool ,
262
+ no_integrated_as : bool ,
261
263
}
262
264
263
265
impl ModuleConfig {
@@ -275,6 +277,7 @@ impl ModuleConfig {
275
277
emit_asm : false ,
276
278
emit_obj : false ,
277
279
obj_is_bitcode : false ,
280
+ no_integrated_as : false ,
278
281
279
282
no_verify : false ,
280
283
no_prepopulate_passes : false ,
@@ -313,6 +316,12 @@ impl ModuleConfig {
313
316
}
314
317
}
315
318
319
+ /// Assembler name and command used by codegen when no_integrated_as is enabled
320
+ struct AssemblerCommand {
321
+ name : PathBuf ,
322
+ cmd : Command ,
323
+ }
324
+
316
325
/// Additional resources used by optimize_and_codegen (not module specific)
317
326
#[ derive( Clone ) ]
318
327
pub struct CodegenContext {
@@ -356,6 +365,8 @@ pub struct CodegenContext {
356
365
// A reference to the TimeGraph so we can register timings. None means that
357
366
// measuring is disabled.
358
367
time_graph : Option < TimeGraph > ,
368
+ // The assembler command if no_integrated_as option is enabled, None otherwise
369
+ assembler_cmd : Option < Arc < AssemblerCommand > > ,
359
370
}
360
371
361
372
impl CodegenContext {
@@ -639,13 +650,17 @@ unsafe fn codegen(cgcx: &CodegenContext,
639
650
!cgcx. crate_types . contains ( & config:: CrateTypeRlib ) &&
640
651
mtrans. kind == ModuleKind :: Regular ;
641
652
653
+ // If we don't have the integrated assembler, then we need to emit asm
654
+ // from LLVM and use `gcc` to create the object file.
655
+ let asm_to_obj = config. emit_obj && config. no_integrated_as ;
656
+
642
657
// Change what we write and cleanup based on whether obj files are
643
658
// just llvm bitcode. In that case write bitcode, and possibly
644
659
// delete the bitcode if it wasn't requested. Don't generate the
645
660
// machine code, instead copy the .o file from the .bc
646
661
let write_bc = config. emit_bc || ( config. obj_is_bitcode && !asm2wasm) ;
647
662
let rm_bc = !config. emit_bc && config. obj_is_bitcode && !asm2wasm;
648
- let write_obj = config. emit_obj && !config. obj_is_bitcode && !asm2wasm;
663
+ let write_obj = config. emit_obj && !config. obj_is_bitcode && !asm2wasm && !asm_to_obj ;
649
664
let copy_bc_to_obj = config. emit_obj && config. obj_is_bitcode && !asm2wasm;
650
665
651
666
let bc_out = cgcx. output_filenames . temp_path ( OutputType :: Bitcode , module_name) ;
@@ -725,7 +740,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
725
740
timeline. record ( "ir" ) ;
726
741
}
727
742
728
- if config. emit_asm || ( asm2wasm && config. emit_obj ) {
743
+ if config. emit_asm || ( asm2wasm && config. emit_obj ) || asm_to_obj {
729
744
let path = cgcx. output_filenames . temp_path ( OutputType :: Assembly , module_name) ;
730
745
731
746
// We can't use the same module for asm and binary output, because that triggers
@@ -760,6 +775,14 @@ unsafe fn codegen(cgcx: &CodegenContext,
760
775
llvm:: FileType :: ObjectFile )
761
776
} ) ?;
762
777
timeline. record ( "obj" ) ;
778
+ } else if asm_to_obj {
779
+ let assembly = cgcx. output_filenames . temp_path ( OutputType :: Assembly , module_name) ;
780
+ run_assembler ( cgcx, diag_handler, & assembly, & obj_out) ;
781
+ timeline. record ( "asm_to_obj" ) ;
782
+
783
+ if !config. emit_asm && !cgcx. save_temps {
784
+ drop ( fs:: remove_file ( & assembly) ) ;
785
+ }
763
786
}
764
787
765
788
Ok ( ( ) )
@@ -841,7 +864,6 @@ pub fn start_async_translation(tcx: TyCtxt,
841
864
total_cgus : usize )
842
865
-> OngoingCrateTranslation {
843
866
let sess = tcx. sess ;
844
- let crate_output = tcx. output_filenames ( LOCAL_CRATE ) ;
845
867
let crate_name = tcx. crate_name ( LOCAL_CRATE ) ;
846
868
let no_builtins = attr:: contains_name ( & tcx. hir . krate ( ) . attrs , "no_builtins" ) ;
847
869
let subsystem = attr:: first_attr_value_str_by_name ( & tcx. hir . krate ( ) . attrs ,
@@ -855,19 +877,9 @@ pub fn start_async_translation(tcx: TyCtxt,
855
877
subsystem. to_string ( )
856
878
} ) ;
857
879
858
- let no_integrated_as = tcx. sess . opts . cg . no_integrated_as ||
859
- ( tcx. sess . target . target . options . no_integrated_as &&
860
- ( crate_output. outputs . contains_key ( & OutputType :: Object ) ||
861
- crate_output. outputs . contains_key ( & OutputType :: Exe ) ) ) ;
862
880
let linker_info = LinkerInfo :: new ( tcx) ;
863
881
let crate_info = CrateInfo :: new ( tcx) ;
864
882
865
- let output_types_override = if no_integrated_as {
866
- OutputTypes :: new ( & [ ( OutputType :: Assembly , None ) ] )
867
- } else {
868
- sess. opts . output_types . clone ( )
869
- } ;
870
-
871
883
// Figure out what we actually need to build.
872
884
let mut modules_config = ModuleConfig :: new ( sess. opts . cg . passes . clone ( ) ) ;
873
885
let mut metadata_config = ModuleConfig :: new ( vec ! [ ] ) ;
@@ -913,7 +925,10 @@ pub fn start_async_translation(tcx: TyCtxt,
913
925
allocator_config. emit_bc_compressed = true ;
914
926
}
915
927
916
- for output_type in output_types_override. keys ( ) {
928
+ modules_config. no_integrated_as = tcx. sess . opts . cg . no_integrated_as ||
929
+ tcx. sess . target . target . options . no_integrated_as ;
930
+
931
+ for output_type in sess. opts . output_types . keys ( ) {
917
932
match * output_type {
918
933
OutputType :: Bitcode => { modules_config. emit_bc = true ; }
919
934
OutputType :: LlvmAssembly => { modules_config. emit_ir = true ; }
@@ -976,7 +991,6 @@ pub fn start_async_translation(tcx: TyCtxt,
976
991
metadata,
977
992
windows_subsystem,
978
993
linker_info,
979
- no_integrated_as,
980
994
crate_info,
981
995
982
996
time_graph,
@@ -1389,6 +1403,18 @@ fn start_executing_work(tcx: TyCtxt,
1389
1403
let wasm_import_memory =
1390
1404
attr:: contains_name ( & tcx. hir . krate ( ) . attrs , "wasm_import_memory" ) ;
1391
1405
1406
+ let assembler_cmd = if modules_config. no_integrated_as {
1407
+ // HACK: currently we use linker (gcc) as our assembler
1408
+ let ( name, mut cmd, _) = get_linker ( sess) ;
1409
+ cmd. args ( & sess. target . target . options . asm_args ) ;
1410
+ Some ( Arc :: new ( AssemblerCommand {
1411
+ name,
1412
+ cmd,
1413
+ } ) )
1414
+ } else {
1415
+ None
1416
+ } ;
1417
+
1392
1418
let cgcx = CodegenContext {
1393
1419
crate_types : sess. crate_types . borrow ( ) . clone ( ) ,
1394
1420
each_linked_rlib_for_lto,
@@ -1428,6 +1454,7 @@ fn start_executing_work(tcx: TyCtxt,
1428
1454
binaryen_linker : tcx. sess . linker_flavor ( ) == LinkerFlavor :: Binaryen ,
1429
1455
debuginfo : tcx. sess . opts . debuginfo ,
1430
1456
wasm_import_memory : wasm_import_memory,
1457
+ assembler_cmd,
1431
1458
} ;
1432
1459
1433
1460
// This is the "main loop" of parallel work happening for parallel codegen.
@@ -1936,15 +1963,14 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem) {
1936
1963
} ) ;
1937
1964
}
1938
1965
1939
- pub fn run_assembler ( sess : & Session , outputs : & OutputFilenames ) {
1940
- let ( pname, mut cmd, _) = get_linker ( sess) ;
1966
+ pub fn run_assembler ( cgcx : & CodegenContext , handler : & Handler , assembly : & Path , object : & Path ) {
1967
+ let assembler = cgcx. assembler_cmd
1968
+ . as_ref ( )
1969
+ . expect ( "cgcx.assembler_cmd is missing?" ) ;
1941
1970
1942
- for arg in & sess. target . target . options . asm_args {
1943
- cmd. arg ( arg) ;
1944
- }
1945
-
1946
- cmd. arg ( "-c" ) . arg ( "-o" ) . arg ( & outputs. path ( OutputType :: Object ) )
1947
- . arg ( & outputs. temp_path ( OutputType :: Assembly , None ) ) ;
1971
+ let pname = & assembler. name ;
1972
+ let mut cmd = assembler. cmd . clone ( ) ;
1973
+ cmd. arg ( "-c" ) . arg ( "-o" ) . arg ( object) . arg ( assembly) ;
1948
1974
debug ! ( "{:?}" , cmd) ;
1949
1975
1950
1976
match cmd. output ( ) {
@@ -1953,18 +1979,18 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
1953
1979
let mut note = prog. stderr . clone ( ) ;
1954
1980
note. extend_from_slice ( & prog. stdout ) ;
1955
1981
1956
- sess . struct_err ( & format ! ( "linking with `{}` failed: {}" ,
1957
- pname. display( ) ,
1958
- prog. status) )
1982
+ handler . struct_err ( & format ! ( "linking with `{}` failed: {}" ,
1983
+ pname. display( ) ,
1984
+ prog. status) )
1959
1985
. note ( & format ! ( "{:?}" , & cmd) )
1960
1986
. note ( str:: from_utf8 ( & note[ ..] ) . unwrap ( ) )
1961
1987
. emit ( ) ;
1962
- sess . abort_if_errors ( ) ;
1988
+ handler . abort_if_errors ( ) ;
1963
1989
}
1964
1990
} ,
1965
1991
Err ( e) => {
1966
- sess . err ( & format ! ( "could not exec the linker `{}`: {}" , pname. display( ) , e) ) ;
1967
- sess . abort_if_errors ( ) ;
1992
+ handler . err ( & format ! ( "could not exec the linker `{}`: {}" , pname. display( ) , e) ) ;
1993
+ handler . abort_if_errors ( ) ;
1968
1994
}
1969
1995
}
1970
1996
}
@@ -2138,7 +2164,6 @@ pub struct OngoingCrateTranslation {
2138
2164
metadata : EncodedMetadata ,
2139
2165
windows_subsystem : Option < String > ,
2140
2166
linker_info : LinkerInfo ,
2141
- no_integrated_as : bool ,
2142
2167
crate_info : CrateInfo ,
2143
2168
time_graph : Option < TimeGraph > ,
2144
2169
coordinator_send : Sender < Box < Any + Send > > ,
@@ -2194,26 +2219,6 @@ impl OngoingCrateTranslation {
2194
2219
metadata_module : compiled_modules. metadata_module ,
2195
2220
} ;
2196
2221
2197
- if self . no_integrated_as {
2198
- run_assembler ( sess, & self . output_filenames ) ;
2199
-
2200
- // HACK the linker expects the object file to be named foo.0.o but
2201
- // `run_assembler` produces an object named just foo.o. Rename it if we
2202
- // are going to build an executable
2203
- if sess. opts . output_types . contains_key ( & OutputType :: Exe ) {
2204
- let f = self . output_filenames . path ( OutputType :: Object ) ;
2205
- rename_or_copy_remove ( & f,
2206
- f. with_file_name ( format ! ( "{}.0.o" ,
2207
- f. file_stem( ) . unwrap( ) . to_string_lossy( ) ) ) ) . unwrap ( ) ;
2208
- }
2209
-
2210
- // Remove assembly source, unless --save-temps was specified
2211
- if !sess. opts . cg . save_temps {
2212
- fs:: remove_file ( & self . output_filenames
2213
- . temp_path ( OutputType :: Assembly , None ) ) . unwrap ( ) ;
2214
- }
2215
- }
2216
-
2217
2222
trans
2218
2223
}
2219
2224
0 commit comments