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,
@@ -1389,6 +1403,18 @@ fn start_executing_work(tcx: TyCtxt,
13891403 let wasm_import_memory =
13901404 attr:: contains_name ( & tcx. hir . krate ( ) . attrs , "wasm_import_memory" ) ;
13911405
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+
13921418 let cgcx = CodegenContext {
13931419 crate_types : sess. crate_types . borrow ( ) . clone ( ) ,
13941420 each_linked_rlib_for_lto,
@@ -1428,6 +1454,7 @@ fn start_executing_work(tcx: TyCtxt,
14281454 binaryen_linker : tcx. sess . linker_flavor ( ) == LinkerFlavor :: Binaryen ,
14291455 debuginfo : tcx. sess . opts . debuginfo ,
14301456 wasm_import_memory : wasm_import_memory,
1457+ assembler_cmd,
14311458 } ;
14321459
14331460 // This is the "main loop" of parallel work happening for parallel codegen.
@@ -1936,15 +1963,14 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem) {
19361963 } ) ;
19371964}
19381965
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?" ) ;
19411970
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) ;
19481974 debug ! ( "{:?}" , cmd) ;
19491975
19501976 match cmd. output ( ) {
@@ -1953,18 +1979,18 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
19531979 let mut note = prog. stderr . clone ( ) ;
19541980 note. extend_from_slice ( & prog. stdout ) ;
19551981
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) )
19591985 . note ( & format ! ( "{:?}" , & cmd) )
19601986 . note ( str:: from_utf8 ( & note[ ..] ) . unwrap ( ) )
19611987 . emit ( ) ;
1962- sess . abort_if_errors ( ) ;
1988+ handler . abort_if_errors ( ) ;
19631989 }
19641990 } ,
19651991 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 ( ) ;
19681994 }
19691995 }
19701996}
@@ -2138,7 +2164,6 @@ pub struct OngoingCrateTranslation {
21382164 metadata : EncodedMetadata ,
21392165 windows_subsystem : Option < String > ,
21402166 linker_info : LinkerInfo ,
2141- no_integrated_as : bool ,
21422167 crate_info : CrateInfo ,
21432168 time_graph : Option < TimeGraph > ,
21442169 coordinator_send : Sender < Box < Any + Send > > ,
@@ -2194,26 +2219,6 @@ impl OngoingCrateTranslation {
21942219 metadata_module : compiled_modules. metadata_module ,
21952220 } ;
21962221
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-
22172222 trans
22182223 }
22192224
0 commit comments