1 // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use back
::link
::{get_cc_prog, remove}
;
13 use session
::config
::{OutputFilenames, NoDebugInfo, Passes, SomePasses, AllPasses}
;
17 use llvm
::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef}
;
18 use llvm
::SMDiagnosticRef
;
19 use trans
::{CrateTranslation, ModuleTranslation}
;
20 use util
::common
::time
;
22 use syntax
::diagnostic
;
23 use syntax
::diagnostic
::{Emitter, Handler, Level, mk_handler}
;
25 use std
::ffi
::{self, CString}
;
28 use std
::iter
::Unfold
;
32 use std
::sync
::{Arc, Mutex}
;
33 use std
::sync
::mpsc
::channel
;
35 use libc
::{self, c_uint, c_int, c_void}
;
37 #[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
41 OutputTypeLlvmAssembly
,
46 pub fn llvm_err(handler
: &diagnostic
::Handler
, msg
: String
) -> ! {
48 let cstr
= llvm
::LLVMRustGetLastError();
49 if cstr
== ptr
::null() {
50 handler
.fatal(&msg
[]);
52 let err
= ffi
::c_str_to_bytes(&cstr
);
53 let err
= String
::from_utf8_lossy(err
.as_slice()).to_string();
54 libc
::free(cstr
as *mut _
);
55 handler
.fatal(&format
!("{}: {}",
62 pub fn write_output_file(
63 handler
: &diagnostic
::Handler
,
64 target
: llvm
::TargetMachineRef
,
65 pm
: llvm
::PassManagerRef
,
68 file_type
: llvm
::FileType
) {
70 let output
= CString
::from_slice(output
.as_vec());
71 let result
= llvm
::LLVMRustWriteOutputFile(
72 target
, pm
, m
, output
.as_ptr(), file_type
);
74 llvm_err(handler
, "could not write output".to_string());
86 // We use an Arc instead of just returning a list of diagnostics from the
87 // child task because we need to make sure that the messages are seen even
88 // if the child task panics (for example, when `fatal` is called).
90 struct SharedEmitter
{
91 buffer
: Arc
<Mutex
<Vec
<Diagnostic
>>>,
95 fn new() -> SharedEmitter
{
97 buffer
: Arc
::new(Mutex
::new(Vec
::new())),
101 fn dump(&mut self, handler
: &Handler
) {
102 let mut buffer
= self.buffer
.lock().unwrap();
103 for diag
in buffer
.iter() {
106 handler
.emit_with_code(None
,
122 impl Emitter
for SharedEmitter
{
123 fn emit(&mut self, cmsp
: Option
<(&codemap
::CodeMap
, codemap
::Span
)>,
124 msg
: &str, code
: Option
<&str>, lvl
: Level
) {
125 assert
!(cmsp
.is_none(), "SharedEmitter doesn't support spans");
127 self.buffer
.lock().unwrap().push(Diagnostic
{
128 msg
: msg
.to_string(),
129 code
: code
.map(|s
| s
.to_string()),
134 fn custom_emit(&mut self, _cm
: &codemap
::CodeMap
,
135 _sp
: diagnostic
::RenderSpan
, _msg
: &str, _lvl
: Level
) {
136 panic
!("SharedEmitter doesn't support custom_emit");
141 // On android, we by default compile for armv7 processors. This enables
142 // things like double word CAS instructions (rather than emulating them)
143 // which are *far* more efficient. This is obviously undesirable in some
144 // cases, so if any sort of target feature is specified we don't append v7
145 // to the feature list.
147 // On iOS only armv7 and newer are supported. So it is useful to
148 // get all hardware potential via VFP3 (hardware floating point)
149 // and NEON (SIMD) instructions supported by LLVM.
150 // Note that without those flags various linking errors might
151 // arise as some of intrinsics are converted into function calls
152 // and nobody provides implementations those functions
153 fn target_feature(sess
: &Session
) -> String
{
154 format
!("{},{}", sess
.target
.target
.options
.features
, sess
.opts
.cg
.target_feature
)
157 fn get_llvm_opt_level(optimize
: config
::OptLevel
) -> llvm
::CodeGenOptLevel
{
159 config
::No
=> llvm
::CodeGenLevelNone
,
160 config
::Less
=> llvm
::CodeGenLevelLess
,
161 config
::Default
=> llvm
::CodeGenLevelDefault
,
162 config
::Aggressive
=> llvm
::CodeGenLevelAggressive
,
166 fn create_target_machine(sess
: &Session
) -> TargetMachineRef
{
167 let reloc_model_arg
= match sess
.opts
.cg
.relocation_model
{
169 None
=> &sess
.target
.target
.options
.relocation_model
[]
171 let reloc_model
= match reloc_model_arg
{
172 "pic" => llvm
::RelocPIC
,
173 "static" => llvm
::RelocStatic
,
174 "default" => llvm
::RelocDefault
,
175 "dynamic-no-pic" => llvm
::RelocDynamicNoPic
,
177 sess
.err(&format
!("{:?} is not a valid relocation mode",
180 .relocation_model
)[]);
181 sess
.abort_if_errors();
186 let opt_level
= get_llvm_opt_level(sess
.opts
.optimize
);
187 let use_softfp
= sess
.opts
.cg
.soft_float
;
189 // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
190 let no_fp_elim
= (sess
.opts
.debuginfo
!= NoDebugInfo
) ||
191 !sess
.target
.target
.options
.eliminate_frame_pointer
;
193 let any_library
= sess
.crate_types
.borrow().iter().any(|ty
| {
194 *ty
!= config
::CrateTypeExecutable
197 let ffunction_sections
= sess
.target
.target
.options
.function_sections
;
198 let fdata_sections
= ffunction_sections
;
200 let code_model_arg
= match sess
.opts
.cg
.code_model
{
202 None
=> &sess
.target
.target
.options
.code_model
[]
205 let code_model
= match code_model_arg
{
206 "default" => llvm
::CodeModelDefault
,
207 "small" => llvm
::CodeModelSmall
,
208 "kernel" => llvm
::CodeModelKernel
,
209 "medium" => llvm
::CodeModelMedium
,
210 "large" => llvm
::CodeModelLarge
,
212 sess
.err(&format
!("{:?} is not a valid code model",
216 sess
.abort_if_errors();
221 let triple
= &sess
.target
.target
.llvm_target
[];
224 let triple
= CString
::from_slice(triple
.as_bytes());
225 let cpu
= match sess
.opts
.cg
.target_cpu
{
226 Some(ref s
) => s
.as_slice(),
227 None
=> sess
.target
.target
.options
.cpu
.as_slice()
229 let cpu
= CString
::from_slice(cpu
.as_bytes());
230 let features
= CString
::from_slice(target_feature(sess
).as_bytes());
231 llvm
::LLVMRustCreateTargetMachine(
232 triple
.as_ptr(), cpu
.as_ptr(), features
.as_ptr(),
236 true /* EnableSegstk */,
239 !any_library
&& reloc_model
== llvm
::RelocPIC
,
246 llvm_err(sess
.diagnostic().handler(),
247 format
!("Could not create LLVM TargetMachine for triple: {}",
248 triple
).to_string());
255 /// Module-specific configuration for `optimize_and_codegen`.
257 struct ModuleConfig
{
258 /// LLVM TargetMachine to use for codegen.
259 tm
: TargetMachineRef
,
260 /// Names of additional optimization passes to run.
262 /// Some(level) to optimize at a certain level, or None to run
263 /// absolutely no optimizations (used for the metadata module).
264 opt_level
: Option
<llvm
::CodeGenOptLevel
>,
266 // Flags indicating which outputs to produce.
267 emit_no_opt_bc
: bool
,
274 // Miscellaneous flags. These are mostly copied from command-line
277 no_prepopulate_passes
: bool
,
282 unsafe impl Send
for ModuleConfig { }
285 fn new(tm
: TargetMachineRef
, passes
: Vec
<String
>) -> ModuleConfig
{
291 emit_no_opt_bc
: false,
299 no_prepopulate_passes
: false,
305 fn set_flags(&mut self, sess
: &Session
, trans
: &CrateTranslation
) {
306 self.no_verify
= sess
.no_verify();
307 self.no_prepopulate_passes
= sess
.opts
.cg
.no_prepopulate_passes
;
308 self.no_builtins
= trans
.no_builtins
;
309 self.time_passes
= sess
.time_passes();
313 /// Additional resources used by optimize_and_codegen (not module specific)
314 struct CodegenContext
<'a
> {
315 // Extra resources used for LTO: (sess, reachable). This will be `None`
316 // when running in a worker thread.
317 lto_ctxt
: Option
<(&'a Session
, &'a
[String
])>,
318 // Handler to use for diagnostics produced during codegen.
319 handler
: &'a Handler
,
320 // LLVM optimizations for which we want to print remarks.
324 impl<'a
> CodegenContext
<'a
> {
325 fn new_with_session(sess
: &'a Session
, reachable
: &'a
[String
]) -> CodegenContext
<'a
> {
327 lto_ctxt
: Some((sess
, reachable
)),
328 handler
: sess
.diagnostic().handler(),
329 remark
: sess
.opts
.cg
.remark
.clone(),
334 struct HandlerFreeVars
<'a
> {
336 cgcx
: &'a CodegenContext
<'a
>,
339 unsafe extern "C" fn inline_asm_handler(diag
: SMDiagnosticRef
,
342 use syntax
::codemap
::ExpnId
;
344 let HandlerFreeVars { cgcx, .. }
345 = *mem
::transmute
::<_
, *const HandlerFreeVars
>(user
);
347 let msg
= llvm
::build_string(|s
| llvm
::LLVMWriteSMDiagnosticToString(diag
, s
))
348 .expect("non-UTF8 SMDiagnostic");
350 match cgcx
.lto_ctxt
{
352 sess
.codemap().with_expn_info(ExpnId
::from_llvm_cookie(cookie
), |info
| match info
{
353 Some(ei
) => sess
.span_err(ei
.call_site
, &msg
[]),
354 None
=> sess
.err(&msg
[]),
359 cgcx
.handler
.err(&msg
[]);
360 cgcx
.handler
.note("build without -C codegen-units for more exact errors");
365 unsafe extern "C" fn diagnostic_handler(info
: DiagnosticInfoRef
, user
: *mut c_void
) {
366 let HandlerFreeVars { llcx, cgcx }
367 = *mem
::transmute
::<_
, *const HandlerFreeVars
>(user
);
369 match llvm
::diagnostic
::Diagnostic
::unpack(info
) {
370 llvm
::diagnostic
::Optimization(opt
) => {
371 let pass_name
= str::from_utf8(ffi
::c_str_to_bytes(&opt
.pass_name
))
373 .expect("got a non-UTF8 pass name from LLVM");
374 let enabled
= match cgcx
.remark
{
376 SomePasses(ref v
) => v
.iter().any(|s
| *s
== pass_name
),
380 let loc
= llvm
::debug_loc_to_string(llcx
, opt
.debug_loc
);
381 cgcx
.handler
.note(format
!("optimization {} for {} at {}: {}",
384 if loc
.is_empty() { "[unknown]" }
else { loc.as_slice() }
,
385 llvm
::twine_to_string(opt
.message
)).as_slice());
393 // Unsafe due to LLVM calls.
394 unsafe fn optimize_and_codegen(cgcx
: &CodegenContext
,
395 mtrans
: ModuleTranslation
,
396 config
: ModuleConfig
,
398 output_names
: OutputFilenames
) {
399 let ModuleTranslation { llmod, llcx }
= mtrans
;
402 // llcx doesn't outlive this function, so we can put this on the stack.
403 let fv
= HandlerFreeVars
{
407 let fv
= &fv
as *const HandlerFreeVars
as *mut c_void
;
409 llvm
::LLVMSetInlineAsmDiagnosticHandler(llcx
, inline_asm_handler
, fv
);
411 if !cgcx
.remark
.is_empty() {
412 llvm
::LLVMContextSetDiagnosticHandler(llcx
, diagnostic_handler
, fv
);
415 if config
.emit_no_opt_bc
{
416 let ext
= format
!("{}.no-opt.bc", name_extra
);
417 let out
= output_names
.with_extension(ext
.as_slice());
418 let out
= CString
::from_slice(out
.as_vec());
419 llvm
::LLVMWriteBitcodeToFile(llmod
, out
.as_ptr());
422 match config
.opt_level
{
424 // Create the two optimizing pass managers. These mirror what clang
425 // does, and are by populated by LLVM's default PassManagerBuilder.
426 // Each manager has a different set of passes, but they also share
427 // some common passes.
428 let fpm
= llvm
::LLVMCreateFunctionPassManagerForModule(llmod
);
429 let mpm
= llvm
::LLVMCreatePassManager();
431 // If we're verifying or linting, add them to the function pass
433 let addpass
= |&: pass
: &str| {
434 let pass
= CString
::from_slice(pass
.as_bytes());
435 llvm
::LLVMRustAddPass(fpm
, pass
.as_ptr())
437 if !config
.no_verify { assert!(addpass("verify")); }
439 if !config
.no_prepopulate_passes
{
440 llvm
::LLVMRustAddAnalysisPasses(tm
, fpm
, llmod
);
441 llvm
::LLVMRustAddAnalysisPasses(tm
, mpm
, llmod
);
442 populate_llvm_passes(fpm
, mpm
, llmod
, opt_level
,
446 for pass
in config
.passes
.iter() {
447 let pass
= CString
::from_slice(pass
.as_bytes());
448 if !llvm
::LLVMRustAddPass(mpm
, pass
.as_ptr()) {
449 cgcx
.handler
.warn(format
!("unknown pass {:?}, ignoring",
454 // Finally, run the actual optimization passes
455 time(config
.time_passes
, "llvm function passes", (), |()|
456 llvm
::LLVMRustRunFunctionPassManager(fpm
, llmod
));
457 time(config
.time_passes
, "llvm module passes", (), |()|
458 llvm
::LLVMRunPassManager(mpm
, llmod
));
460 // Deallocate managers that we're now done with
461 llvm
::LLVMDisposePassManager(fpm
);
462 llvm
::LLVMDisposePassManager(mpm
);
464 match cgcx
.lto_ctxt
{
465 Some((sess
, reachable
)) if sess
.lto() => {
466 time(sess
.time_passes(), "all lto passes", (), |()|
467 lto
::run(sess
, llmod
, tm
, reachable
));
469 if config
.emit_lto_bc
{
470 let name
= format
!("{}.lto.bc", name_extra
);
471 let out
= output_names
.with_extension(name
.as_slice());
472 let out
= CString
::from_slice(out
.as_vec());
473 llvm
::LLVMWriteBitcodeToFile(llmod
, out
.as_ptr());
482 // A codegen-specific pass manager is used to generate object
483 // files for an LLVM module.
485 // Apparently each of these pass managers is a one-shot kind of
486 // thing, so we create a new one for each type of output. The
487 // pass manager passed to the closure should be ensured to not
488 // escape the closure itself, and the manager should only be
490 unsafe fn with_codegen
<F
>(tm
: TargetMachineRef
,
494 F
: FnOnce(PassManagerRef
),
496 let cpm
= llvm
::LLVMCreatePassManager();
497 llvm
::LLVMRustAddAnalysisPasses(tm
, cpm
, llmod
);
498 llvm
::LLVMRustAddLibraryInfo(cpm
, llmod
, no_builtins
);
500 llvm
::LLVMDisposePassManager(cpm
);
504 let ext
= format
!("{}.bc", name_extra
);
505 let out
= output_names
.with_extension(ext
.as_slice());
506 let out
= CString
::from_slice(out
.as_vec());
507 llvm
::LLVMWriteBitcodeToFile(llmod
, out
.as_ptr());
510 time(config
.time_passes
, "codegen passes", (), |()| {
512 let ext
= format
!("{}.ll", name_extra
);
513 let out
= output_names
.with_extension(ext
.as_slice());
514 let out
= CString
::from_slice(out
.as_vec());
515 with_codegen(tm
, llmod
, config
.no_builtins
, |cpm
| {
516 llvm
::LLVMRustPrintModule(cpm
, llmod
, out
.as_ptr());
521 let path
= output_names
.with_extension(&format
!("{}.s", name_extra
)[]);
522 with_codegen(tm
, llmod
, config
.no_builtins
, |cpm
| {
523 write_output_file(cgcx
.handler
, tm
, cpm
, llmod
, &path
, llvm
::AssemblyFileType
);
528 let path
= output_names
.with_extension(&format
!("{}.o", name_extra
)[]);
529 with_codegen(tm
, llmod
, config
.no_builtins
, |cpm
| {
530 write_output_file(cgcx
.handler
, tm
, cpm
, llmod
, &path
, llvm
::ObjectFileType
);
535 llvm
::LLVMDisposeModule(llmod
);
536 llvm
::LLVMContextDispose(llcx
);
537 llvm
::LLVMRustDisposeTargetMachine(tm
);
540 pub fn run_passes(sess
: &Session
,
541 trans
: &CrateTranslation
,
542 output_types
: &[config
::OutputType
],
543 crate_output
: &OutputFilenames
) {
544 // It's possible that we have `codegen_units > 1` but only one item in
545 // `trans.modules`. We could theoretically proceed and do LTO in that
546 // case, but it would be confusing to have the validity of
547 // `-Z lto -C codegen-units=2` depend on details of the crate being
548 // compiled, so we complain regardless.
549 if sess
.lto() && sess
.opts
.cg
.codegen_units
> 1 {
550 // This case is impossible to handle because LTO expects to be able
551 // to combine the entire crate and all its dependencies into a
552 // single compilation unit, but each codegen unit is in a separate
553 // LLVM context, so they can't easily be combined.
554 sess
.fatal("can't perform LTO when using multiple codegen units");
558 assert
!(trans
.modules
.len() == sess
.opts
.cg
.codegen_units
);
561 configure_llvm(sess
);
564 let tm
= create_target_machine(sess
);
566 // Figure out what we actually need to build.
568 let mut modules_config
= ModuleConfig
::new(tm
, sess
.opts
.cg
.passes
.clone());
569 let mut metadata_config
= ModuleConfig
::new(tm
, vec
!());
571 modules_config
.opt_level
= Some(get_llvm_opt_level(sess
.opts
.optimize
));
573 // Save all versions of the bytecode if we're saving our temporaries.
574 if sess
.opts
.cg
.save_temps
{
575 modules_config
.emit_no_opt_bc
= true;
576 modules_config
.emit_bc
= true;
577 modules_config
.emit_lto_bc
= true;
578 metadata_config
.emit_bc
= true;
581 // Emit bitcode files for the crate if we're emitting an rlib.
582 // Whenever an rlib is created, the bitcode is inserted into the
583 // archive in order to allow LTO against it.
584 let needs_crate_bitcode
=
585 sess
.crate_types
.borrow().contains(&config
::CrateTypeRlib
) &&
586 sess
.opts
.output_types
.contains(&config
::OutputTypeExe
);
587 if needs_crate_bitcode
{
588 modules_config
.emit_bc
= true;
591 for output_type
in output_types
.iter() {
593 config
::OutputTypeBitcode
=> { modules_config.emit_bc = true; }
,
594 config
::OutputTypeLlvmAssembly
=> { modules_config.emit_ir = true; }
,
595 config
::OutputTypeAssembly
=> {
596 modules_config
.emit_asm
= true;
597 // If we're not using the LLVM assembler, this function
598 // could be invoked specially with output_type_assembly, so
599 // in this case we still want the metadata object file.
600 if !sess
.opts
.output_types
.contains(&config
::OutputTypeAssembly
) {
601 metadata_config
.emit_obj
= true;
604 config
::OutputTypeObject
=> { modules_config.emit_obj = true; }
,
605 config
::OutputTypeExe
=> {
606 modules_config
.emit_obj
= true;
607 metadata_config
.emit_obj
= true;
609 config
::OutputTypeDepInfo
=> {}
613 modules_config
.set_flags(sess
, trans
);
614 metadata_config
.set_flags(sess
, trans
);
617 // Populate a buffer with a list of codegen tasks. Items are processed in
618 // LIFO order, just because it's a tiny bit simpler that way. (The order
619 // doesn't actually matter.)
620 let mut work_items
= Vec
::with_capacity(1 + trans
.modules
.len());
623 let work
= build_work_item(sess
,
624 trans
.metadata_module
,
625 metadata_config
.clone(),
626 crate_output
.clone(),
627 "metadata".to_string());
628 work_items
.push(work
);
631 for (index
, mtrans
) in trans
.modules
.iter().enumerate() {
632 let work
= build_work_item(sess
,
634 modules_config
.clone(),
635 crate_output
.clone(),
636 format
!("{}", index
));
637 work_items
.push(work
);
640 // Process the work items, optionally using worker threads.
641 if sess
.opts
.cg
.codegen_units
== 1 {
642 run_work_singlethreaded(sess
, &trans
.reachable
[], work_items
);
644 run_work_multithreaded(sess
, work_items
, sess
.opts
.cg
.codegen_units
);
647 // All codegen is finished.
649 llvm
::LLVMRustDisposeTargetMachine(tm
);
652 // Produce final compile outputs.
654 let copy_if_one_unit
= |&: ext
: &str, output_type
: config
::OutputType
, keep_numbered
: bool
| {
656 if sess
.opts
.cg
.codegen_units
== 1 {
657 // 1) Only one codegen unit. In this case it's no difficulty
658 // to copy `foo.0.x` to `foo.x`.
659 fs
::copy(&crate_output
.with_extension(ext
),
660 &crate_output
.path(output_type
)).unwrap();
661 if !sess
.opts
.cg
.save_temps
&& !keep_numbered
{
662 // The user just wants `foo.x`, not `foo.0.x`.
663 remove(sess
, &crate_output
.with_extension(ext
));
666 if crate_output
.single_output_file
.is_some() {
667 // 2) Multiple codegen units, with `-o some_name`. We have
668 // no good solution for this case, so warn the user.
669 sess
.warn(&format
!("ignoring -o because multiple .{} files were produced",
672 // 3) Multiple codegen units, but no `-o some_name`. We
673 // just leave the `foo.0.x` files in place.
674 // (We don't have to do any work in this case.)
679 let link_obj
= |&: output_path
: &Path
| {
680 // Running `ld -r` on a single input is kind of pointless.
681 if sess
.opts
.cg
.codegen_units
== 1 {
682 fs
::copy(&crate_output
.with_extension("0.o"),
683 output_path
).unwrap();
684 // Leave the .0.o file around, to mimic the behavior of the normal
689 // Some builds of MinGW GCC will pass --force-exe-suffix to ld, which
690 // will automatically add a .exe extension if the extension is not
691 // already .exe or .dll. To ensure consistent behavior on Windows, we
692 // add the .exe suffix explicitly and then rename the output file to
693 // the desired path. This will give the correct behavior whether or
694 // not GCC adds --force-exe-suffix.
695 let windows_output_path
=
696 if sess
.target
.target
.options
.is_like_windows
{
697 Some(output_path
.with_extension("o.exe"))
702 let pname
= get_cc_prog(sess
);
703 let mut cmd
= Command
::new(&pname
[]);
705 cmd
.args(&sess
.target
.target
.options
.pre_link_args
[]);
706 cmd
.arg("-nostdlib");
708 for index
in range(0, trans
.modules
.len()) {
709 cmd
.arg(crate_output
.with_extension(&format
!("{}.o", index
)[]));
714 .arg(windows_output_path
.as_ref().unwrap_or(output_path
));
716 cmd
.args(&sess
.target
.target
.options
.post_link_args
[]);
718 if sess
.opts
.debugging_opts
.print_link_args
{
719 println
!("{}", &cmd
);
722 cmd
.stdin(::std
::io
::process
::Ignored
)
723 .stdout(::std
::io
::process
::InheritFd(1))
724 .stderr(::std
::io
::process
::InheritFd(2));
727 if !status
.success() {
728 sess
.err(&format
!("linking of {} with `{}` failed",
729 output_path
.display(), cmd
)[]);
730 sess
.abort_if_errors();
734 sess
.err(&format
!("could not exec the linker `{}`: {}",
737 sess
.abort_if_errors();
741 match windows_output_path
{
742 Some(ref windows_path
) => {
743 fs
::rename(windows_path
, output_path
).unwrap();
746 // The file is already named according to `output_path`.
751 // Flag to indicate whether the user explicitly requested bitcode.
752 // Otherwise, we produced it only as a temporary output, and will need
754 let mut user_wants_bitcode
= false;
755 for output_type
in output_types
.iter() {
757 config
::OutputTypeBitcode
=> {
758 user_wants_bitcode
= true;
759 // Copy to .bc, but always keep the .0.bc. There is a later
760 // check to figure out if we should delete .0.bc files, or keep
761 // them for making an rlib.
762 copy_if_one_unit("0.bc", config
::OutputTypeBitcode
, true);
764 config
::OutputTypeLlvmAssembly
=> {
765 copy_if_one_unit("0.ll", config
::OutputTypeLlvmAssembly
, false);
767 config
::OutputTypeAssembly
=> {
768 copy_if_one_unit("0.s", config
::OutputTypeAssembly
, false);
770 config
::OutputTypeObject
=> {
771 link_obj(&crate_output
.path(config
::OutputTypeObject
));
773 config
::OutputTypeExe
=> {
774 // If config::OutputTypeObject is already in the list, then
775 // `crate.o` will be handled by the config::OutputTypeObject case.
776 // Otherwise, we need to create the temporary object so we
777 // can run the linker.
778 if !sess
.opts
.output_types
.contains(&config
::OutputTypeObject
) {
779 link_obj(&crate_output
.temp_path(config
::OutputTypeObject
));
782 config
::OutputTypeDepInfo
=> {}
785 let user_wants_bitcode
= user_wants_bitcode
;
787 // Clean up unwanted temporary files.
789 // We create the following files by default:
792 // - crate.metadata.bc
793 // - crate.metadata.o
794 // - crate.o (linked from crate.##.o)
795 // - crate.bc (copied from crate.0.bc)
796 // We may create additional files if requested by the user (through
797 // `-C save-temps` or `--emit=` flags).
799 if !sess
.opts
.cg
.save_temps
{
800 // Remove the temporary .0.o objects. If the user didn't
801 // explicitly request bitcode (with --emit=bc), and the bitcode is not
802 // needed for building an rlib, then we must remove .0.bc as well.
804 // Specific rules for keeping .0.bc:
805 // - If we're building an rlib (`needs_crate_bitcode`), then keep
807 // - If the user requested bitcode (`user_wants_bitcode`), and
808 // codegen_units > 1, then keep it.
809 // - If the user requested bitcode but codegen_units == 1, then we
810 // can toss .0.bc because we copied it to .bc earlier.
811 // - If we're not building an rlib and the user didn't request
812 // bitcode, then delete .0.bc.
813 // If you change how this works, also update back::link::link_rlib,
814 // where .0.bc files are (maybe) deleted after making an rlib.
815 let keep_numbered_bitcode
= needs_crate_bitcode
||
816 (user_wants_bitcode
&& sess
.opts
.cg
.codegen_units
> 1);
818 for i
in range(0, trans
.modules
.len()) {
819 if modules_config
.emit_obj
{
820 let ext
= format
!("{}.o", i
);
821 remove(sess
, &crate_output
.with_extension(&ext
[]));
824 if modules_config
.emit_bc
&& !keep_numbered_bitcode
{
825 let ext
= format
!("{}.bc", i
);
826 remove(sess
, &crate_output
.with_extension(&ext
[]));
830 if metadata_config
.emit_bc
&& !user_wants_bitcode
{
831 remove(sess
, &crate_output
.with_extension("metadata.bc"));
835 // We leave the following files around by default:
837 // - crate.metadata.o
839 // These are used in linking steps and will be cleaned up afterward.
841 // FIXME: time_llvm_passes support - does this use a global context or
843 //if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
847 mtrans
: ModuleTranslation
,
848 config
: ModuleConfig
,
849 output_names
: OutputFilenames
,
853 fn build_work_item(sess
: &Session
,
854 mtrans
: ModuleTranslation
,
855 config
: ModuleConfig
,
856 output_names
: OutputFilenames
,
860 let mut config
= config
;
861 config
.tm
= create_target_machine(sess
);
862 WorkItem
{ mtrans
: mtrans
, config
: config
, output_names
: output_names
,
863 name_extra
: name_extra
}
866 fn execute_work_item(cgcx
: &CodegenContext
,
867 work_item
: WorkItem
) {
869 optimize_and_codegen(cgcx
, work_item
.mtrans
, work_item
.config
,
870 work_item
.name_extra
, work_item
.output_names
);
874 fn run_work_singlethreaded(sess
: &Session
,
875 reachable
: &[String
],
876 work_items
: Vec
<WorkItem
>) {
877 let cgcx
= CodegenContext
::new_with_session(sess
, reachable
);
878 let mut work_items
= work_items
;
880 // Since we're running single-threaded, we can pass the session to
881 // the proc, allowing `optimize_and_codegen` to perform LTO.
882 for work
in Unfold
::new((), |_
| work_items
.pop()) {
883 execute_work_item(&cgcx
, work
);
887 fn run_work_multithreaded(sess
: &Session
,
888 work_items
: Vec
<WorkItem
>,
890 // Run some workers to process the work items.
891 let work_items_arc
= Arc
::new(Mutex
::new(work_items
));
892 let mut diag_emitter
= SharedEmitter
::new();
893 let mut futures
= Vec
::with_capacity(num_workers
);
895 for i
in range(0, num_workers
) {
896 let work_items_arc
= work_items_arc
.clone();
897 let diag_emitter
= diag_emitter
.clone();
898 let remark
= sess
.opts
.cg
.remark
.clone();
900 let (tx
, rx
) = channel();
901 let mut tx
= Some(tx
);
904 thread
::Builder
::new().name(format
!("codegen-{}", i
)).spawn(move |:| {
905 let diag_handler
= mk_handler(box diag_emitter
);
907 // Must construct cgcx inside the proc because it has non-Send
909 let cgcx
= CodegenContext
{
911 handler
: &diag_handler
,
916 // Avoid holding the lock for the entire duration of the match.
917 let maybe_work
= work_items_arc
.lock().unwrap().pop();
920 execute_work_item(&cgcx
, work
);
922 // Make sure to fail the worker so the main thread can
923 // tell that there were errors.
924 cgcx
.handler
.abort_if_errors();
930 tx
.take().unwrap().send(()).unwrap();
934 let mut panicked
= false;
935 for rx
in futures
.into_iter() {
942 // Display any new diagnostics.
943 diag_emitter
.dump(sess
.diagnostic().handler());
946 sess
.fatal("aborting due to worker thread panic");
950 pub fn run_assembler(sess
: &Session
, outputs
: &OutputFilenames
) {
951 let pname
= get_cc_prog(sess
);
952 let mut cmd
= Command
::new(&pname
[]);
954 cmd
.arg("-c").arg("-o").arg(outputs
.path(config
::OutputTypeObject
))
955 .arg(outputs
.temp_path(config
::OutputTypeAssembly
));
960 if !prog
.status
.success() {
961 sess
.err(&format
!("linking with `{}` failed: {}",
964 sess
.note(&format
!("{}", &cmd
)[]);
965 let mut note
= prog
.error
.clone();
966 note
.push_all(&prog
.output
[]);
967 sess
.note(str::from_utf8(¬e
[]).unwrap());
968 sess
.abort_if_errors();
972 sess
.err(&format
!("could not exec the linker `{}`: {}",
975 sess
.abort_if_errors();
980 unsafe fn configure_llvm(sess
: &Session
) {
981 use std
::sync
::{Once, ONCE_INIT}
;
982 static INIT
: Once
= ONCE_INIT
;
984 // Copy what clang does by turning on loop vectorization at O2 and
985 // slp vectorization at O3
986 let vectorize_loop
= !sess
.opts
.cg
.no_vectorize_loops
&&
987 (sess
.opts
.optimize
== config
::Default
||
988 sess
.opts
.optimize
== config
::Aggressive
);
989 let vectorize_slp
= !sess
.opts
.cg
.no_vectorize_slp
&&
990 sess
.opts
.optimize
== config
::Aggressive
;
992 let mut llvm_c_strs
= Vec
::new();
993 let mut llvm_args
= Vec
::new();
995 let mut add
= |&mut : arg
: &str| {
996 let s
= CString
::from_slice(arg
.as_bytes());
997 llvm_args
.push(s
.as_ptr());
1000 add("rustc"); // fake program name
1001 if vectorize_loop { add("-vectorize-loops"); }
1002 if vectorize_slp { add("-vectorize-slp"); }
1003 if sess
.time_llvm_passes() { add("-time-passes"); }
1004 if sess
.print_llvm_passes() { add("-debug-pass=Structure"); }
1006 for arg
in sess
.opts
.cg
.llvm_args
.iter() {
1012 llvm
::LLVMInitializePasses();
1014 // Only initialize the platforms supported by Rust here, because
1015 // using --llvm-root will have multiple platforms that rustllvm
1016 // doesn't actually link to and it's pointless to put target info
1017 // into the registry that Rust cannot generate machine code for.
1018 llvm
::LLVMInitializeX86TargetInfo();
1019 llvm
::LLVMInitializeX86Target();
1020 llvm
::LLVMInitializeX86TargetMC();
1021 llvm
::LLVMInitializeX86AsmPrinter();
1022 llvm
::LLVMInitializeX86AsmParser();
1024 llvm
::LLVMInitializeARMTargetInfo();
1025 llvm
::LLVMInitializeARMTarget();
1026 llvm
::LLVMInitializeARMTargetMC();
1027 llvm
::LLVMInitializeARMAsmPrinter();
1028 llvm
::LLVMInitializeARMAsmParser();
1030 llvm
::LLVMInitializeAArch64TargetInfo();
1031 llvm
::LLVMInitializeAArch64Target();
1032 llvm
::LLVMInitializeAArch64TargetMC();
1033 llvm
::LLVMInitializeAArch64AsmPrinter();
1034 llvm
::LLVMInitializeAArch64AsmParser();
1036 llvm
::LLVMInitializeMipsTargetInfo();
1037 llvm
::LLVMInitializeMipsTarget();
1038 llvm
::LLVMInitializeMipsTargetMC();
1039 llvm
::LLVMInitializeMipsAsmPrinter();
1040 llvm
::LLVMInitializeMipsAsmParser();
1042 llvm
::LLVMRustSetLLVMOptions(llvm_args
.len() as c_int
,
1043 llvm_args
.as_ptr());
1047 unsafe fn populate_llvm_passes(fpm
: llvm
::PassManagerRef
,
1048 mpm
: llvm
::PassManagerRef
,
1050 opt
: llvm
::CodeGenOptLevel
,
1051 no_builtins
: bool
) {
1052 // Create the PassManagerBuilder for LLVM. We configure it with
1053 // reasonable defaults and prepare it to actually populate the pass
1055 let builder
= llvm
::LLVMPassManagerBuilderCreate();
1057 llvm
::CodeGenLevelNone
=> {
1058 // Don't add lifetime intrinsics at O0
1059 llvm
::LLVMRustAddAlwaysInlinePass(builder
, false);
1061 llvm
::CodeGenLevelLess
=> {
1062 llvm
::LLVMRustAddAlwaysInlinePass(builder
, true);
1064 // numeric values copied from clang
1065 llvm
::CodeGenLevelDefault
=> {
1066 llvm
::LLVMPassManagerBuilderUseInlinerWithThreshold(builder
,
1069 llvm
::CodeGenLevelAggressive
=> {
1070 llvm
::LLVMPassManagerBuilderUseInlinerWithThreshold(builder
,
1074 llvm
::LLVMPassManagerBuilderSetOptLevel(builder
, opt
as c_uint
);
1075 llvm
::LLVMRustAddBuilderLibraryInfo(builder
, llmod
, no_builtins
);
1077 // Use the builder to populate the function/module pass managers.
1078 llvm
::LLVMPassManagerBuilderPopulateFunctionPassManager(builder
, fpm
);
1079 llvm
::LLVMPassManagerBuilderPopulateModulePassManager(builder
, mpm
);
1080 llvm
::LLVMPassManagerBuilderDispose(builder
);
1083 llvm
::CodeGenLevelDefault
| llvm
::CodeGenLevelAggressive
=> {
1084 llvm
::LLVMRustAddPass(mpm
, "mergefunc\0".as_ptr() as *const _
);