1 // Copyright 2013-2014 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 driver::driver::{CrateTranslation, ModuleTranslation, OutputFilenames};
14 use session::config::{NoDebugInfo, Passes, SomePasses, AllPasses};
18 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
19 use llvm::SMDiagnosticRef;
20 use util::common::time;
22 use syntax::diagnostic;
23 use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
25 use std::c_str::{ToCStr, CString};
28 use std::iter::Unfold;
32 use std::sync::{Arc, Mutex};
33 use std::task::TaskBuilder;
34 use libc::{c_uint, c_int, c_void};
36 pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
38 let cstr = llvm::LLVMRustGetLastError();
39 if cstr == ptr::null() {
40 handler.fatal(msg.as_slice());
42 let err = CString::new(cstr, true);
43 let err = String::from_utf8_lossy(err.as_bytes());
44 handler.fatal(format!("{}: {}",
46 err.as_slice()).as_slice());
51 pub fn write_output_file(
52 handler: &diagnostic::Handler,
53 target: llvm::TargetMachineRef,
54 pm: llvm::PassManagerRef,
57 file_type: llvm::FileType) {
59 output.with_c_str(|output| {
60 let result = llvm::LLVMRustWriteOutputFile(
61 target, pm, m, output, file_type);
63 llvm_err(handler, "could not write output".to_string());
76 // We use an Arc instead of just returning a list of diagnostics from the
77 // child task because we need to make sure that the messages are seen even
78 // if the child task panics (for example, when `fatal` is called).
80 struct SharedEmitter {
81 buffer: Arc<Mutex<Vec<Diagnostic>>>,
85 fn new() -> SharedEmitter {
87 buffer: Arc::new(Mutex::new(Vec::new())),
91 fn dump(&mut self, handler: &Handler) {
92 let mut buffer = self.buffer.lock();
93 for diag in buffer.iter() {
96 handler.emit_with_code(None,
112 impl Emitter for SharedEmitter {
113 fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, codemap::Span)>,
114 msg: &str, code: Option<&str>, lvl: Level) {
115 assert!(cmsp.is_none(), "SharedEmitter doesn't support spans");
117 self.buffer.lock().push(Diagnostic {
118 msg: msg.to_string(),
119 code: code.map(|s| s.to_string()),
124 fn custom_emit(&mut self, _cm: &codemap::CodeMap,
125 _sp: diagnostic::RenderSpan, _msg: &str, _lvl: Level) {
126 panic!("SharedEmitter doesn't support custom_emit");
131 // On android, we by default compile for armv7 processors. This enables
132 // things like double word CAS instructions (rather than emulating them)
133 // which are *far* more efficient. This is obviously undesirable in some
134 // cases, so if any sort of target feature is specified we don't append v7
135 // to the feature list.
137 // On iOS only armv7 and newer are supported. So it is useful to
138 // get all hardware potential via VFP3 (hardware floating point)
139 // and NEON (SIMD) instructions supported by LLVM.
140 // Note that without those flags various linking errors might
141 // arise as some of intrinsics are converted into function calls
142 // and nobody provides implementations those functions
143 fn target_feature(sess: &Session) -> String {
144 format!("{},{}", sess.target.target.options.features, sess.opts.cg.target_feature)
147 fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
149 config::No => llvm::CodeGenLevelNone,
150 config::Less => llvm::CodeGenLevelLess,
151 config::Default => llvm::CodeGenLevelDefault,
152 config::Aggressive => llvm::CodeGenLevelAggressive,
156 fn create_target_machine(sess: &Session) -> TargetMachineRef {
157 let reloc_model_arg = match sess.opts.cg.relocation_model {
158 Some(ref s) => s.as_slice(),
159 None => sess.target.target.options.relocation_model.as_slice()
161 let reloc_model = match reloc_model_arg {
162 "pic" => llvm::RelocPIC,
163 "static" => llvm::RelocStatic,
164 "default" => llvm::RelocDefault,
165 "dynamic-no-pic" => llvm::RelocDynamicNoPic,
167 sess.err(format!("{} is not a valid relocation mode",
170 .relocation_model).as_slice());
171 sess.abort_if_errors();
176 let opt_level = get_llvm_opt_level(sess.opts.optimize);
177 let use_softfp = sess.opts.cg.soft_float;
179 // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
180 let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
181 !sess.target.target.options.eliminate_frame_pointer;
183 let any_library = sess.crate_types.borrow().iter().any(|ty| {
184 *ty != config::CrateTypeExecutable
187 let ffunction_sections = sess.target.target.options.function_sections;
188 let fdata_sections = ffunction_sections;
190 let code_model_arg = match sess.opts.cg.code_model {
191 Some(ref s) => s.as_slice(),
192 None => sess.target.target.options.code_model.as_slice()
195 let code_model = match code_model_arg {
196 "default" => llvm::CodeModelDefault,
197 "small" => llvm::CodeModelSmall,
198 "kernel" => llvm::CodeModelKernel,
199 "medium" => llvm::CodeModelMedium,
200 "large" => llvm::CodeModelLarge,
202 sess.err(format!("{} is not a valid code model",
205 .code_model).as_slice());
206 sess.abort_if_errors();
211 let triple = sess.target.target.llvm_target.as_slice();
214 triple.with_c_str(|t| {
215 let cpu = match sess.opts.cg.target_cpu {
216 Some(ref s) => s.as_slice(),
217 None => sess.target.target.options.cpu.as_slice()
219 cpu.with_c_str(|cpu| {
220 target_feature(sess).with_c_str(|features| {
221 llvm::LLVMRustCreateTargetMachine(
226 true /* EnableSegstk */,
229 !any_library && reloc_model == llvm::RelocPIC,
239 llvm_err(sess.diagnostic().handler(),
240 format!("Could not create LLVM TargetMachine for triple: {}",
241 triple).to_string());
248 /// Module-specific configuration for `optimize_and_codegen`.
250 struct ModuleConfig {
251 /// LLVM TargetMachine to use for codegen.
252 tm: TargetMachineRef,
253 /// Names of additional optimization passes to run.
255 /// Some(level) to optimize at a certain level, or None to run
256 /// absolutely no optimizations (used for the metadata module).
257 opt_level: Option<llvm::CodeGenOptLevel>,
259 // Flags indicating which outputs to produce.
260 emit_no_opt_bc: bool,
267 // Miscellaneous flags. These are mostly copied from command-line
270 no_prepopulate_passes: bool,
276 fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig {
282 emit_no_opt_bc: false,
290 no_prepopulate_passes: false,
296 fn set_flags(&mut self, sess: &Session, trans: &CrateTranslation) {
297 self.no_verify = sess.no_verify();
298 self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
299 self.no_builtins = trans.no_builtins;
300 self.time_passes = sess.time_passes();
304 /// Additional resources used by optimize_and_codegen (not module specific)
305 struct CodegenContext<'a> {
306 // Extra resources used for LTO: (sess, reachable). This will be `None`
307 // when running in a worker thread.
308 lto_ctxt: Option<(&'a Session, &'a [String])>,
309 // Handler to use for diagnostics produced during codegen.
310 handler: &'a Handler,
311 // LLVM optimizations for which we want to print remarks.
315 impl<'a> CodegenContext<'a> {
316 fn new_with_session(sess: &'a Session, reachable: &'a [String]) -> CodegenContext<'a> {
318 lto_ctxt: Some((sess, reachable)),
319 handler: sess.diagnostic().handler(),
320 remark: sess.opts.cg.remark.clone(),
325 struct HandlerFreeVars<'a> {
327 cgcx: &'a CodegenContext<'a>,
330 unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
333 use syntax::codemap::ExpnId;
335 let HandlerFreeVars { cgcx, .. }
336 = *mem::transmute::<_, *const HandlerFreeVars>(user);
338 let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
339 .expect("non-UTF8 SMDiagnostic");
341 match cgcx.lto_ctxt {
343 sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info {
344 Some(ei) => sess.span_err(ei.call_site, msg.as_slice()),
345 None => sess.err(msg.as_slice()),
350 cgcx.handler.err(msg.as_slice());
351 cgcx.handler.note("build without -C codegen-units for more exact errors");
356 unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
357 let HandlerFreeVars { llcx, cgcx }
358 = *mem::transmute::<_, *const HandlerFreeVars>(user);
360 match llvm::diagnostic::Diagnostic::unpack(info) {
361 llvm::diagnostic::Optimization(opt) => {
362 let pass_name = CString::new(opt.pass_name, false);
363 let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
364 let enabled = match cgcx.remark {
366 SomePasses(ref v) => v.iter().any(|s| s.as_slice() == pass_name),
370 let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
371 cgcx.handler.note(format!("optimization {} for {} at {}: {}",
374 if loc.is_empty() { "[unknown]" } else { loc.as_slice() },
375 llvm::twine_to_string(opt.message)).as_slice());
383 // Unsafe due to LLVM calls.
384 unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
385 mtrans: ModuleTranslation,
386 config: ModuleConfig,
388 output_names: OutputFilenames) {
389 let ModuleTranslation { llmod, llcx } = mtrans;
392 // llcx doesn't outlive this function, so we can put this on the stack.
393 let fv = HandlerFreeVars {
397 let fv = &fv as *const HandlerFreeVars as *mut c_void;
399 llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
401 if !cgcx.remark.is_empty() {
402 llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
405 if config.emit_no_opt_bc {
406 let ext = format!("{}.no-opt.bc", name_extra);
407 output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
408 llvm::LLVMWriteBitcodeToFile(llmod, buf);
412 match config.opt_level {
414 // Create the two optimizing pass managers. These mirror what clang
415 // does, and are by populated by LLVM's default PassManagerBuilder.
416 // Each manager has a different set of passes, but they also share
417 // some common passes.
418 let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
419 let mpm = llvm::LLVMCreatePassManager();
421 // If we're verifying or linting, add them to the function pass
423 let addpass = |pass: &str| {
424 pass.as_slice().with_c_str(|s| llvm::LLVMRustAddPass(fpm, s))
426 if !config.no_verify { assert!(addpass("verify")); }
428 if !config.no_prepopulate_passes {
429 llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
430 llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
431 populate_llvm_passes(fpm, mpm, llmod, opt_level,
435 for pass in config.passes.iter() {
436 pass.as_slice().with_c_str(|s| {
437 if !llvm::LLVMRustAddPass(mpm, s) {
438 cgcx.handler.warn(format!("unknown pass {}, ignoring",
444 // Finally, run the actual optimization passes
445 time(config.time_passes, "llvm function passes", (), |()|
446 llvm::LLVMRustRunFunctionPassManager(fpm, llmod));
447 time(config.time_passes, "llvm module passes", (), |()|
448 llvm::LLVMRunPassManager(mpm, llmod));
450 // Deallocate managers that we're now done with
451 llvm::LLVMDisposePassManager(fpm);
452 llvm::LLVMDisposePassManager(mpm);
454 match cgcx.lto_ctxt {
455 Some((sess, reachable)) if sess.lto() => {
456 time(sess.time_passes(), "all lto passes", (), |()|
457 lto::run(sess, llmod, tm, reachable));
459 if config.emit_lto_bc {
460 let name = format!("{}.lto.bc", name_extra);
461 output_names.with_extension(name.as_slice()).with_c_str(|buf| {
462 llvm::LLVMWriteBitcodeToFile(llmod, buf);
472 // A codegen-specific pass manager is used to generate object
473 // files for an LLVM module.
475 // Apparently each of these pass managers is a one-shot kind of
476 // thing, so we create a new one for each type of output. The
477 // pass manager passed to the closure should be ensured to not
478 // escape the closure itself, and the manager should only be
480 unsafe fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
481 no_builtins: bool, f: |PassManagerRef|) {
482 let cpm = llvm::LLVMCreatePassManager();
483 llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
484 llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
486 llvm::LLVMDisposePassManager(cpm);
490 let ext = format!("{}.bc", name_extra);
491 output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
492 llvm::LLVMWriteBitcodeToFile(llmod, buf);
496 time(config.time_passes, "codegen passes", (), |()| {
498 let ext = format!("{}.ll", name_extra);
499 output_names.with_extension(ext.as_slice()).with_c_str(|output| {
500 with_codegen(tm, llmod, config.no_builtins, |cpm| {
501 llvm::LLVMRustPrintModule(cpm, llmod, output);
507 let path = output_names.with_extension(format!("{}.s", name_extra).as_slice());
508 with_codegen(tm, llmod, config.no_builtins, |cpm| {
509 write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
514 let path = output_names.with_extension(format!("{}.o", name_extra).as_slice());
515 with_codegen(tm, llmod, config.no_builtins, |cpm| {
516 write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::ObjectFileType);
521 llvm::LLVMDisposeModule(llmod);
522 llvm::LLVMContextDispose(llcx);
523 llvm::LLVMRustDisposeTargetMachine(tm);
526 pub fn run_passes(sess: &Session,
527 trans: &CrateTranslation,
528 output_types: &[config::OutputType],
529 crate_output: &OutputFilenames) {
530 // It's possible that we have `codegen_units > 1` but only one item in
531 // `trans.modules`. We could theoretically proceed and do LTO in that
532 // case, but it would be confusing to have the validity of
533 // `-Z lto -C codegen-units=2` depend on details of the crate being
534 // compiled, so we complain regardless.
535 if sess.lto() && sess.opts.cg.codegen_units > 1 {
536 // This case is impossible to handle because LTO expects to be able
537 // to combine the entire crate and all its dependencies into a
538 // single compilation unit, but each codegen unit is in a separate
539 // LLVM context, so they can't easily be combined.
540 sess.fatal("can't perform LTO when using multiple codegen units");
544 assert!(trans.modules.len() == sess.opts.cg.codegen_units);
547 configure_llvm(sess);
550 let tm = create_target_machine(sess);
552 // Figure out what we actually need to build.
554 let mut modules_config = ModuleConfig::new(tm, sess.opts.cg.passes.clone());
555 let mut metadata_config = ModuleConfig::new(tm, vec!());
557 modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize));
559 // Save all versions of the bytecode if we're saving our temporaries.
560 if sess.opts.cg.save_temps {
561 modules_config.emit_no_opt_bc = true;
562 modules_config.emit_bc = true;
563 modules_config.emit_lto_bc = true;
564 metadata_config.emit_bc = true;
567 // Emit bitcode files for the crate if we're emitting an rlib.
568 // Whenever an rlib is created, the bitcode is inserted into the
569 // archive in order to allow LTO against it.
570 let needs_crate_bitcode =
571 sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
572 sess.opts.output_types.contains(&config::OutputTypeExe);
573 if needs_crate_bitcode {
574 modules_config.emit_bc = true;
577 for output_type in output_types.iter() {
579 config::OutputTypeBitcode => { modules_config.emit_bc = true; },
580 config::OutputTypeLlvmAssembly => { modules_config.emit_ir = true; },
581 config::OutputTypeAssembly => {
582 modules_config.emit_asm = true;
583 // If we're not using the LLVM assembler, this function
584 // could be invoked specially with output_type_assembly, so
585 // in this case we still want the metadata object file.
586 if !sess.opts.output_types.contains(&config::OutputTypeAssembly) {
587 metadata_config.emit_obj = true;
590 config::OutputTypeObject => { modules_config.emit_obj = true; },
591 config::OutputTypeExe => {
592 modules_config.emit_obj = true;
593 metadata_config.emit_obj = true;
598 modules_config.set_flags(sess, trans);
599 metadata_config.set_flags(sess, trans);
602 // Populate a buffer with a list of codegen tasks. Items are processed in
603 // LIFO order, just because it's a tiny bit simpler that way. (The order
604 // doesn't actually matter.)
605 let mut work_items = Vec::with_capacity(1 + trans.modules.len());
608 let work = build_work_item(sess,
609 trans.metadata_module,
610 metadata_config.clone(),
611 crate_output.clone(),
612 "metadata".to_string());
613 work_items.push(work);
616 for (index, mtrans) in trans.modules.iter().enumerate() {
617 let work = build_work_item(sess,
619 modules_config.clone(),
620 crate_output.clone(),
621 format!("{}", index));
622 work_items.push(work);
625 // Process the work items, optionally using worker threads.
626 if sess.opts.cg.codegen_units == 1 {
627 run_work_singlethreaded(sess, trans.reachable.as_slice(), work_items);
629 run_work_multithreaded(sess, work_items, sess.opts.cg.codegen_units);
632 // All codegen is finished.
634 llvm::LLVMRustDisposeTargetMachine(tm);
637 // Produce final compile outputs.
639 let copy_if_one_unit = |ext: &str, output_type: config::OutputType, keep_numbered: bool| {
641 if sess.opts.cg.codegen_units == 1 {
642 // 1) Only one codegen unit. In this case it's no difficulty
643 // to copy `foo.0.x` to `foo.x`.
644 fs::copy(&crate_output.with_extension(ext),
645 &crate_output.path(output_type)).unwrap();
646 if !sess.opts.cg.save_temps && !keep_numbered {
647 // The user just wants `foo.x`, not `foo.0.x`.
648 remove(sess, &crate_output.with_extension(ext));
651 if crate_output.single_output_file.is_some() {
652 // 2) Multiple codegen units, with `-o some_name`. We have
653 // no good solution for this case, so warn the user.
654 sess.warn(format!("ignoring -o because multiple .{} files were produced",
657 // 3) Multiple codegen units, but no `-o some_name`. We
658 // just leave the `foo.0.x` files in place.
659 // (We don't have to do any work in this case.)
664 let link_obj = |output_path: &Path| {
665 // Running `ld -r` on a single input is kind of pointless.
666 if sess.opts.cg.codegen_units == 1 {
667 fs::copy(&crate_output.with_extension("0.o"),
668 output_path).unwrap();
669 // Leave the .0.o file around, to mimic the behavior of the normal
674 // Some builds of MinGW GCC will pass --force-exe-suffix to ld, which
675 // will automatically add a .exe extension if the extension is not
676 // already .exe or .dll. To ensure consistent behavior on Windows, we
677 // add the .exe suffix explicitly and then rename the output file to
678 // the desired path. This will give the correct behavior whether or
679 // not GCC adds --force-exe-suffix.
680 let windows_output_path =
681 if sess.target.target.options.is_like_windows {
682 Some(output_path.with_extension("o.exe"))
687 let pname = get_cc_prog(sess);
688 let mut cmd = Command::new(pname.as_slice());
690 cmd.args(sess.target.target.options.pre_link_args.as_slice());
691 cmd.arg("-nostdlib");
693 for index in range(0, trans.modules.len()) {
694 cmd.arg(crate_output.with_extension(format!("{}.o", index).as_slice()));
699 .arg(windows_output_path.as_ref().unwrap_or(output_path));
701 cmd.args(sess.target.target.options.post_link_args.as_slice());
703 if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
704 println!("{}", &cmd);
707 cmd.stdin(::std::io::process::Ignored)
708 .stdout(::std::io::process::InheritFd(1))
709 .stderr(::std::io::process::InheritFd(2));
712 if !status.success() {
713 sess.err(format!("linking of {} with `{}` failed",
714 output_path.display(), cmd).as_slice());
715 sess.abort_if_errors();
719 sess.err(format!("could not exec the linker `{}`: {}",
722 sess.abort_if_errors();
726 match windows_output_path {
727 Some(ref windows_path) => {
728 fs::rename(windows_path, output_path).unwrap();
731 // The file is already named according to `output_path`.
736 // Flag to indicate whether the user explicitly requested bitcode.
737 // Otherwise, we produced it only as a temporary output, and will need
739 let mut user_wants_bitcode = false;
740 for output_type in output_types.iter() {
742 config::OutputTypeBitcode => {
743 user_wants_bitcode = true;
744 // Copy to .bc, but always keep the .0.bc. There is a later
745 // check to figure out if we should delete .0.bc files, or keep
746 // them for making an rlib.
747 copy_if_one_unit("0.bc", config::OutputTypeBitcode, true);
749 config::OutputTypeLlvmAssembly => {
750 copy_if_one_unit("0.ll", config::OutputTypeLlvmAssembly, false);
752 config::OutputTypeAssembly => {
753 copy_if_one_unit("0.s", config::OutputTypeAssembly, false);
755 config::OutputTypeObject => {
756 link_obj(&crate_output.path(config::OutputTypeObject));
758 config::OutputTypeExe => {
759 // If config::OutputTypeObject is already in the list, then
760 // `crate.o` will be handled by the config::OutputTypeObject case.
761 // Otherwise, we need to create the temporary object so we
762 // can run the linker.
763 if !sess.opts.output_types.contains(&config::OutputTypeObject) {
764 link_obj(&crate_output.temp_path(config::OutputTypeObject));
769 let user_wants_bitcode = user_wants_bitcode;
771 // Clean up unwanted temporary files.
773 // We create the following files by default:
776 // - crate.metadata.bc
777 // - crate.metadata.o
778 // - crate.o (linked from crate.##.o)
779 // - crate.bc (copied from crate.0.bc)
780 // We may create additional files if requested by the user (through
781 // `-C save-temps` or `--emit=` flags).
783 if !sess.opts.cg.save_temps {
784 // Remove the temporary .0.o objects. If the user didn't
785 // explicitly request bitcode (with --emit=bc), and the bitcode is not
786 // needed for building an rlib, then we must remove .0.bc as well.
788 // Specific rules for keeping .0.bc:
789 // - If we're building an rlib (`needs_crate_bitcode`), then keep
791 // - If the user requested bitcode (`user_wants_bitcode`), and
792 // codegen_units > 1, then keep it.
793 // - If the user requested bitcode but codegen_units == 1, then we
794 // can toss .0.bc because we copied it to .bc earlier.
795 // - If we're not building an rlib and the user didn't request
796 // bitcode, then delete .0.bc.
797 // If you change how this works, also update back::link::link_rlib,
798 // where .0.bc files are (maybe) deleted after making an rlib.
799 let keep_numbered_bitcode = needs_crate_bitcode ||
800 (user_wants_bitcode && sess.opts.cg.codegen_units > 1);
802 for i in range(0, trans.modules.len()) {
803 if modules_config.emit_obj {
804 let ext = format!("{}.o", i);
805 remove(sess, &crate_output.with_extension(ext.as_slice()));
808 if modules_config.emit_bc && !keep_numbered_bitcode {
809 let ext = format!("{}.bc", i);
810 remove(sess, &crate_output.with_extension(ext.as_slice()));
814 if metadata_config.emit_bc && !user_wants_bitcode {
815 remove(sess, &crate_output.with_extension("metadata.bc"));
819 // We leave the following files around by default:
821 // - crate.metadata.o
823 // These are used in linking steps and will be cleaned up afterward.
825 // FIXME: time_llvm_passes support - does this use a global context or
827 //if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
830 type WorkItem = proc(&CodegenContext):Send;
832 fn build_work_item(sess: &Session,
833 mtrans: ModuleTranslation,
834 config: ModuleConfig,
835 output_names: OutputFilenames,
836 name_extra: String) -> WorkItem {
837 let mut config = config;
838 config.tm = create_target_machine(sess);
841 optimize_and_codegen(cgcx, mtrans, config, name_extra, output_names);
845 fn run_work_singlethreaded(sess: &Session,
846 reachable: &[String],
847 work_items: Vec<WorkItem>) {
848 let cgcx = CodegenContext::new_with_session(sess, reachable);
849 let mut work_items = work_items;
851 // Since we're running single-threaded, we can pass the session to
852 // the proc, allowing `optimize_and_codegen` to perform LTO.
853 for work in Unfold::new((), |_| work_items.pop()) {
858 fn run_work_multithreaded(sess: &Session,
859 work_items: Vec<WorkItem>,
861 // Run some workers to process the work items.
862 let work_items_arc = Arc::new(Mutex::new(work_items));
863 let mut diag_emitter = SharedEmitter::new();
864 let mut futures = Vec::with_capacity(num_workers);
866 for i in range(0, num_workers) {
867 let work_items_arc = work_items_arc.clone();
868 let diag_emitter = diag_emitter.clone();
869 let remark = sess.opts.cg.remark.clone();
871 let future = TaskBuilder::new().named(format!("codegen-{}", i)).try_future(proc() {
872 let diag_handler = mk_handler(box diag_emitter);
874 // Must construct cgcx inside the proc because it has non-Send
876 let cgcx = CodegenContext {
878 handler: &diag_handler,
883 // Avoid holding the lock for the entire duration of the match.
884 let maybe_work = work_items_arc.lock().pop();
889 // Make sure to fail the worker so the main thread can
890 // tell that there were errors.
891 cgcx.handler.abort_if_errors();
897 futures.push(future);
900 let mut panicked = false;
901 for future in futures.into_iter() {
902 match future.into_inner() {
908 // Display any new diagnostics.
909 diag_emitter.dump(sess.diagnostic().handler());
912 sess.fatal("aborting due to worker thread panic");
916 pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
917 let pname = get_cc_prog(sess);
918 let mut cmd = Command::new(pname.as_slice());
920 cmd.arg("-c").arg("-o").arg(outputs.path(config::OutputTypeObject))
921 .arg(outputs.temp_path(config::OutputTypeAssembly));
926 if !prog.status.success() {
927 sess.err(format!("linking with `{}` failed: {}",
929 prog.status).as_slice());
930 sess.note(format!("{}", &cmd).as_slice());
931 let mut note = prog.error.clone();
932 note.push_all(prog.output.as_slice());
933 sess.note(str::from_utf8(note.as_slice()).unwrap());
934 sess.abort_if_errors();
938 sess.err(format!("could not exec the linker `{}`: {}",
941 sess.abort_if_errors();
946 unsafe fn configure_llvm(sess: &Session) {
947 use std::sync::{Once, ONCE_INIT};
948 static INIT: Once = ONCE_INIT;
950 // Copy what clang does by turning on loop vectorization at O2 and
951 // slp vectorization at O3
952 let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
953 (sess.opts.optimize == config::Default ||
954 sess.opts.optimize == config::Aggressive);
955 let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
956 sess.opts.optimize == config::Aggressive;
958 let mut llvm_c_strs = Vec::new();
959 let mut llvm_args = Vec::new();
961 let add = |arg: &str| {
962 let s = arg.to_c_str();
963 llvm_args.push(s.as_ptr());
966 add("rustc"); // fake program name
967 if vectorize_loop { add("-vectorize-loops"); }
968 if vectorize_slp { add("-vectorize-slp"); }
969 if sess.time_llvm_passes() { add("-time-passes"); }
970 if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
972 for arg in sess.opts.cg.llvm_args.iter() {
973 add((*arg).as_slice());
978 llvm::LLVMInitializePasses();
980 // Only initialize the platforms supported by Rust here, because
981 // using --llvm-root will have multiple platforms that rustllvm
982 // doesn't actually link to and it's pointless to put target info
983 // into the registry that Rust cannot generate machine code for.
984 llvm::LLVMInitializeX86TargetInfo();
985 llvm::LLVMInitializeX86Target();
986 llvm::LLVMInitializeX86TargetMC();
987 llvm::LLVMInitializeX86AsmPrinter();
988 llvm::LLVMInitializeX86AsmParser();
990 llvm::LLVMInitializeARMTargetInfo();
991 llvm::LLVMInitializeARMTarget();
992 llvm::LLVMInitializeARMTargetMC();
993 llvm::LLVMInitializeARMAsmPrinter();
994 llvm::LLVMInitializeARMAsmParser();
996 llvm::LLVMInitializeMipsTargetInfo();
997 llvm::LLVMInitializeMipsTarget();
998 llvm::LLVMInitializeMipsTargetMC();
999 llvm::LLVMInitializeMipsAsmPrinter();
1000 llvm::LLVMInitializeMipsAsmParser();
1002 llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
1003 llvm_args.as_ptr());
1007 unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
1008 mpm: llvm::PassManagerRef,
1010 opt: llvm::CodeGenOptLevel,
1011 no_builtins: bool) {
1012 // Create the PassManagerBuilder for LLVM. We configure it with
1013 // reasonable defaults and prepare it to actually populate the pass
1015 let builder = llvm::LLVMPassManagerBuilderCreate();
1017 llvm::CodeGenLevelNone => {
1018 // Don't add lifetime intrinsics at O0
1019 llvm::LLVMRustAddAlwaysInlinePass(builder, false);
1021 llvm::CodeGenLevelLess => {
1022 llvm::LLVMRustAddAlwaysInlinePass(builder, true);
1024 // numeric values copied from clang
1025 llvm::CodeGenLevelDefault => {
1026 llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
1029 llvm::CodeGenLevelAggressive => {
1030 llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
1034 llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
1035 llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
1037 // Use the builder to populate the function/module pass managers.
1038 llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
1039 llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
1040 llvm::LLVMPassManagerBuilderDispose(builder);
1043 llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
1044 "mergefunc".with_c_str(|s| llvm::LLVMRustAddPass(mpm, s));