1111use back:: bytecode:: { self , RLIB_BYTECODE_EXTENSION } ;
1212use back:: lto:: { self , ModuleBuffer , ThinBuffer } ;
1313use back:: link:: { self , get_linker, remove} ;
14+ use back:: command:: Command ;
1415use back:: linker:: LinkerInfo ;
1516use back:: symbol_export:: ExportedSymbols ;
1617use base;
1718use consts;
1819use rustc_incremental:: { save_trans_partition, in_incr_comp_dir} ;
1920use rustc:: dep_graph:: { DepGraph , WorkProductFileKind } ;
2021use 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 ,
2223 AllPasses , Sanitizer } ;
2324use rustc:: session:: Session ;
2425use rustc:: util:: nodemap:: FxHashMap ;
@@ -32,7 +33,7 @@ use CrateInfo;
3233use rustc:: hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
3334use rustc:: ty:: TyCtxt ;
3435use 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} ;
3637use errors:: { self , Handler , Level , DiagnosticBuilder , FatalError , DiagnosticId } ;
3738use errors:: emitter:: { Emitter } ;
3839use syntax:: attr;
@@ -258,6 +259,7 @@ pub struct ModuleConfig {
258259 // make the object file bitcode. Provides easy compatibility with
259260 // emscripten's ecc compiler, when used as the linker.
260261 obj_is_bitcode : bool ,
262+ no_integrated_as : bool ,
261263}
262264
263265impl ModuleConfig {
@@ -275,6 +277,7 @@ impl ModuleConfig {
275277 emit_asm : false ,
276278 emit_obj : false ,
277279 obj_is_bitcode : false ,
280+ no_integrated_as : false ,
278281
279282 no_verify : false ,
280283 no_prepopulate_passes : false ,
@@ -313,6 +316,12 @@ impl ModuleConfig {
313316 }
314317}
315318
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+
316325/// Additional resources used by optimize_and_codegen (not module specific)
317326#[ derive( Clone ) ]
318327pub struct CodegenContext {
@@ -356,6 +365,8 @@ pub struct CodegenContext {
356365 // A reference to the TimeGraph so we can register timings. None means that
357366 // measuring is disabled.
358367 time_graph : Option < TimeGraph > ,
368+ // The assembler command if no_integrated_as option is enabled, None otherwise
369+ assembler_cmd : Option < Arc < AssemblerCommand > > ,
359370}
360371
361372impl CodegenContext {
@@ -639,13 +650,17 @@ unsafe fn codegen(cgcx: &CodegenContext,
639650 !cgcx. crate_types . contains ( & config:: CrateTypeRlib ) &&
640651 mtrans. kind == ModuleKind :: Regular ;
641652
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+
642657 // Change what we write and cleanup based on whether obj files are
643658 // just llvm bitcode. In that case write bitcode, and possibly
644659 // delete the bitcode if it wasn't requested. Don't generate the
645660 // machine code, instead copy the .o file from the .bc
646661 let write_bc = config. emit_bc || ( config. obj_is_bitcode && !asm2wasm) ;
647662 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 ;
649664 let copy_bc_to_obj = config. emit_obj && config. obj_is_bitcode && !asm2wasm;
650665
651666 let bc_out = cgcx. output_filenames . temp_path ( OutputType :: Bitcode , module_name) ;
@@ -725,7 +740,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
725740 timeline. record ( "ir" ) ;
726741 }
727742
728- if config. emit_asm || ( asm2wasm && config. emit_obj ) {
743+ if config. emit_asm || ( asm2wasm && config. emit_obj ) || asm_to_obj {
729744 let path = cgcx. output_filenames . temp_path ( OutputType :: Assembly , module_name) ;
730745
731746 // We can't use the same module for asm and binary output, because that triggers
@@ -760,6 +775,14 @@ unsafe fn codegen(cgcx: &CodegenContext,
760775 llvm:: FileType :: ObjectFile )
761776 } ) ?;
762777 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+ }
763786 }
764787
765788 Ok ( ( ) )
@@ -841,7 +864,6 @@ pub fn start_async_translation(tcx: TyCtxt,
841864 total_cgus : usize )
842865 -> OngoingCrateTranslation {
843866 let sess = tcx. sess ;
844- let crate_output = tcx. output_filenames ( LOCAL_CRATE ) ;
845867 let crate_name = tcx. crate_name ( LOCAL_CRATE ) ;
846868 let no_builtins = attr:: contains_name ( & tcx. hir . krate ( ) . attrs , "no_builtins" ) ;
847869 let subsystem = attr:: first_attr_value_str_by_name ( & tcx. hir . krate ( ) . attrs ,
@@ -855,19 +877,9 @@ pub fn start_async_translation(tcx: TyCtxt,
855877 subsystem. to_string ( )
856878 } ) ;
857879
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 ) ) ) ;
862880 let linker_info = LinkerInfo :: new ( tcx) ;
863881 let crate_info = CrateInfo :: new ( tcx) ;
864882
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-
871883 // Figure out what we actually need to build.
872884 let mut modules_config = ModuleConfig :: new ( sess. opts . cg . passes . clone ( ) ) ;
873885 let mut metadata_config = ModuleConfig :: new ( vec ! [ ] ) ;
@@ -913,7 +925,10 @@ pub fn start_async_translation(tcx: TyCtxt,
913925 allocator_config. emit_bc_compressed = true ;
914926 }
915927
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 ( ) {
917932 match * output_type {
918933 OutputType :: Bitcode => { modules_config. emit_bc = true ; }
919934 OutputType :: LlvmAssembly => { modules_config. emit_ir = true ; }
@@ -976,7 +991,6 @@ pub fn start_async_translation(tcx: TyCtxt,
976991 metadata,
977992 windows_subsystem,
978993 linker_info,
979- no_integrated_as,
980994 crate_info,
981995
982996 time_graph,
@@ -1384,6 +1398,18 @@ fn start_executing_work(tcx: TyCtxt,
13841398 let wasm_import_memory =
13851399 attr:: contains_name ( & tcx. hir . krate ( ) . attrs , "wasm_import_memory" ) ;
13861400
1401+ let assembler_cmd = if modules_config. no_integrated_as {
1402+ // HACK: currently we use linker (gcc) as our assembler
1403+ let ( name, mut cmd, _) = get_linker ( sess) ;
1404+ cmd. args ( & sess. target . target . options . asm_args ) ;
1405+ Some ( Arc :: new ( AssemblerCommand {
1406+ name,
1407+ cmd,
1408+ } ) )
1409+ } else {
1410+ None
1411+ } ;
1412+
13871413 let cgcx = CodegenContext {
13881414 crate_types : sess. crate_types . borrow ( ) . clone ( ) ,
13891415 each_linked_rlib_for_lto,
@@ -1423,6 +1449,7 @@ fn start_executing_work(tcx: TyCtxt,
14231449 binaryen_linker : tcx. sess . linker_flavor ( ) == LinkerFlavor :: Binaryen ,
14241450 debuginfo : tcx. sess . opts . debuginfo ,
14251451 wasm_import_memory : wasm_import_memory,
1452+ assembler_cmd,
14261453 } ;
14271454
14281455 // This is the "main loop" of parallel work happening for parallel codegen.
@@ -1931,15 +1958,14 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem) {
19311958 } ) ;
19321959}
19331960
1934- pub fn run_assembler ( sess : & Session , outputs : & OutputFilenames ) {
1935- let ( pname, mut cmd, _) = get_linker ( sess) ;
1961+ pub fn run_assembler ( cgcx : & CodegenContext , handler : & Handler , assembly : & Path , object : & Path ) {
1962+ let assembler = cgcx. assembler_cmd
1963+ . as_ref ( )
1964+ . expect ( "cgcx.assembler_cmd is missing?" ) ;
19361965
1937- for arg in & sess. target . target . options . asm_args {
1938- cmd. arg ( arg) ;
1939- }
1940-
1941- cmd. arg ( "-c" ) . arg ( "-o" ) . arg ( & outputs. path ( OutputType :: Object ) )
1942- . arg ( & outputs. temp_path ( OutputType :: Assembly , None ) ) ;
1966+ let pname = & assembler. name ;
1967+ let mut cmd = assembler. cmd . clone ( ) ;
1968+ cmd. arg ( "-c" ) . arg ( "-o" ) . arg ( object) . arg ( assembly) ;
19431969 debug ! ( "{:?}" , cmd) ;
19441970
19451971 match cmd. output ( ) {
@@ -1948,18 +1974,18 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
19481974 let mut note = prog. stderr . clone ( ) ;
19491975 note. extend_from_slice ( & prog. stdout ) ;
19501976
1951- sess . struct_err ( & format ! ( "linking with `{}` failed: {}" ,
1952- pname. display( ) ,
1953- prog. status) )
1977+ handler . struct_err ( & format ! ( "linking with `{}` failed: {}" ,
1978+ pname. display( ) ,
1979+ prog. status) )
19541980 . note ( & format ! ( "{:?}" , & cmd) )
19551981 . note ( str:: from_utf8 ( & note[ ..] ) . unwrap ( ) )
19561982 . emit ( ) ;
1957- sess . abort_if_errors ( ) ;
1983+ handler . abort_if_errors ( ) ;
19581984 }
19591985 } ,
19601986 Err ( e) => {
1961- sess . err ( & format ! ( "could not exec the linker `{}`: {}" , pname. display( ) , e) ) ;
1962- sess . abort_if_errors ( ) ;
1987+ handler . err ( & format ! ( "could not exec the linker `{}`: {}" , pname. display( ) , e) ) ;
1988+ handler . abort_if_errors ( ) ;
19631989 }
19641990 }
19651991}
@@ -2133,7 +2159,6 @@ pub struct OngoingCrateTranslation {
21332159 metadata : EncodedMetadata ,
21342160 windows_subsystem : Option < String > ,
21352161 linker_info : LinkerInfo ,
2136- no_integrated_as : bool ,
21372162 crate_info : CrateInfo ,
21382163 time_graph : Option < TimeGraph > ,
21392164 coordinator_send : Sender < Box < Any + Send > > ,
@@ -2189,26 +2214,6 @@ impl OngoingCrateTranslation {
21892214 metadata_module : compiled_modules. metadata_module ,
21902215 } ;
21912216
2192- if self . no_integrated_as {
2193- run_assembler ( sess, & self . output_filenames ) ;
2194-
2195- // HACK the linker expects the object file to be named foo.0.o but
2196- // `run_assembler` produces an object named just foo.o. Rename it if we
2197- // are going to build an executable
2198- if sess. opts . output_types . contains_key ( & OutputType :: Exe ) {
2199- let f = self . output_filenames . path ( OutputType :: Object ) ;
2200- rename_or_copy_remove ( & f,
2201- f. with_file_name ( format ! ( "{}.0.o" ,
2202- f. file_stem( ) . unwrap( ) . to_string_lossy( ) ) ) ) . unwrap ( ) ;
2203- }
2204-
2205- // Remove assembly source, unless --save-temps was specified
2206- if !sess. opts . cg . save_temps {
2207- fs:: remove_file ( & self . output_filenames
2208- . temp_path ( OutputType :: Assembly , None ) ) . unwrap ( ) ;
2209- }
2210- }
2211-
22122217 trans
22132218 }
22142219
0 commit comments