]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/back/write.rs
auto merge of #19648 : mquandalle/rust/patch-1, r=alexcrichton
[rust.git] / src / librustc_trans / back / write.rs
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.
4 //
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.
10
11 use back::lto;
12 use back::link::{get_cc_prog, remove};
13 use session::config::{OutputFilenames, NoDebugInfo, Passes, SomePasses, AllPasses};
14 use session::Session;
15 use session::config;
16 use llvm;
17 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
18 use llvm::SMDiagnosticRef;
19 use trans::{CrateTranslation, ModuleTranslation};
20 use util::common::time;
21 use syntax::codemap;
22 use syntax::diagnostic;
23 use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
24
25 use std::c_str::{ToCStr, CString};
26 use std::io::Command;
27 use std::io::fs;
28 use std::iter::Unfold;
29 use std::ptr;
30 use std::str;
31 use std::mem;
32 use std::sync::{Arc, Mutex};
33 use std::task::TaskBuilder;
34 use libc::{c_uint, c_int, c_void};
35
36 #[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
37 pub enum OutputType {
38     OutputTypeBitcode,
39     OutputTypeAssembly,
40     OutputTypeLlvmAssembly,
41     OutputTypeObject,
42     OutputTypeExe,
43 }
44
45 impl Copy for OutputType {}
46
47 pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
48     unsafe {
49         let cstr = llvm::LLVMRustGetLastError();
50         if cstr == ptr::null() {
51             handler.fatal(msg.as_slice());
52         } else {
53             let err = CString::new(cstr, true);
54             let err = String::from_utf8_lossy(err.as_bytes());
55             handler.fatal(format!("{}: {}",
56                                   msg.as_slice(),
57                                   err.as_slice()).as_slice());
58         }
59     }
60 }
61
62 pub fn write_output_file(
63         handler: &diagnostic::Handler,
64         target: llvm::TargetMachineRef,
65         pm: llvm::PassManagerRef,
66         m: ModuleRef,
67         output: &Path,
68         file_type: llvm::FileType) {
69     unsafe {
70         output.with_c_str(|output| {
71             let result = llvm::LLVMRustWriteOutputFile(
72                     target, pm, m, output, file_type);
73             if !result {
74                 llvm_err(handler, "could not write output".to_string());
75             }
76         })
77     }
78 }
79
80
81 struct Diagnostic {
82     msg: String,
83     code: Option<String>,
84     lvl: Level,
85 }
86
87 // We use an Arc instead of just returning a list of diagnostics from the
88 // child task because we need to make sure that the messages are seen even
89 // if the child task panics (for example, when `fatal` is called).
90 #[deriving(Clone)]
91 struct SharedEmitter {
92     buffer: Arc<Mutex<Vec<Diagnostic>>>,
93 }
94
95 impl SharedEmitter {
96     fn new() -> SharedEmitter {
97         SharedEmitter {
98             buffer: Arc::new(Mutex::new(Vec::new())),
99         }
100     }
101
102     fn dump(&mut self, handler: &Handler) {
103         let mut buffer = self.buffer.lock();
104         for diag in buffer.iter() {
105             match diag.code {
106                 Some(ref code) => {
107                     handler.emit_with_code(None,
108                                            diag.msg.as_slice(),
109                                            code.as_slice(),
110                                            diag.lvl);
111                 },
112                 None => {
113                     handler.emit(None,
114                                  diag.msg.as_slice(),
115                                  diag.lvl);
116                 },
117             }
118         }
119         buffer.clear();
120     }
121 }
122
123 impl Emitter for SharedEmitter {
124     fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, codemap::Span)>,
125             msg: &str, code: Option<&str>, lvl: Level) {
126         assert!(cmsp.is_none(), "SharedEmitter doesn't support spans");
127
128         self.buffer.lock().push(Diagnostic {
129             msg: msg.to_string(),
130             code: code.map(|s| s.to_string()),
131             lvl: lvl,
132         });
133     }
134
135     fn custom_emit(&mut self, _cm: &codemap::CodeMap,
136                    _sp: diagnostic::RenderSpan, _msg: &str, _lvl: Level) {
137         panic!("SharedEmitter doesn't support custom_emit");
138     }
139 }
140
141
142 // On android, we by default compile for armv7 processors. This enables
143 // things like double word CAS instructions (rather than emulating them)
144 // which are *far* more efficient. This is obviously undesirable in some
145 // cases, so if any sort of target feature is specified we don't append v7
146 // to the feature list.
147 //
148 // On iOS only armv7 and newer are supported. So it is useful to
149 // get all hardware potential via VFP3 (hardware floating point)
150 // and NEON (SIMD) instructions supported by LLVM.
151 // Note that without those flags various linking errors might
152 // arise as some of intrinsics are converted into function calls
153 // and nobody provides implementations those functions
154 fn target_feature(sess: &Session) -> String {
155     format!("{},{}", sess.target.target.options.features, sess.opts.cg.target_feature)
156 }
157
158 fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
159     match optimize {
160       config::No => llvm::CodeGenLevelNone,
161       config::Less => llvm::CodeGenLevelLess,
162       config::Default => llvm::CodeGenLevelDefault,
163       config::Aggressive => llvm::CodeGenLevelAggressive,
164     }
165 }
166
167 fn create_target_machine(sess: &Session) -> TargetMachineRef {
168     let reloc_model_arg = match sess.opts.cg.relocation_model {
169         Some(ref s) => s.as_slice(),
170         None => sess.target.target.options.relocation_model.as_slice()
171     };
172     let reloc_model = match reloc_model_arg {
173         "pic" => llvm::RelocPIC,
174         "static" => llvm::RelocStatic,
175         "default" => llvm::RelocDefault,
176         "dynamic-no-pic" => llvm::RelocDynamicNoPic,
177         _ => {
178             sess.err(format!("{} is not a valid relocation mode",
179                              sess.opts
180                                  .cg
181                                  .relocation_model).as_slice());
182             sess.abort_if_errors();
183             unreachable!();
184         }
185     };
186
187     let opt_level = get_llvm_opt_level(sess.opts.optimize);
188     let use_softfp = sess.opts.cg.soft_float;
189
190     // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
191     let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
192                      !sess.target.target.options.eliminate_frame_pointer;
193
194     let any_library = sess.crate_types.borrow().iter().any(|ty| {
195         *ty != config::CrateTypeExecutable
196     });
197
198     let ffunction_sections = sess.target.target.options.function_sections;
199     let fdata_sections = ffunction_sections;
200
201     let code_model_arg = match sess.opts.cg.code_model {
202         Some(ref s) => s.as_slice(),
203         None => sess.target.target.options.code_model.as_slice()
204     };
205
206     let code_model = match code_model_arg {
207         "default" => llvm::CodeModelDefault,
208         "small" => llvm::CodeModelSmall,
209         "kernel" => llvm::CodeModelKernel,
210         "medium" => llvm::CodeModelMedium,
211         "large" => llvm::CodeModelLarge,
212         _ => {
213             sess.err(format!("{} is not a valid code model",
214                              sess.opts
215                                  .cg
216                                  .code_model).as_slice());
217             sess.abort_if_errors();
218             unreachable!();
219         }
220     };
221
222     let triple = sess.target.target.llvm_target.as_slice();
223
224     let tm = unsafe {
225         triple.with_c_str(|t| {
226             let cpu = match sess.opts.cg.target_cpu {
227                 Some(ref s) => s.as_slice(),
228                 None => sess.target.target.options.cpu.as_slice()
229             };
230             cpu.with_c_str(|cpu| {
231                 target_feature(sess).with_c_str(|features| {
232                     llvm::LLVMRustCreateTargetMachine(
233                         t, cpu, features,
234                         code_model,
235                         reloc_model,
236                         opt_level,
237                         true /* EnableSegstk */,
238                         use_softfp,
239                         no_fp_elim,
240                         !any_library && reloc_model == llvm::RelocPIC,
241                         ffunction_sections,
242                         fdata_sections,
243                     )
244                 })
245             })
246         })
247     };
248
249     if tm.is_null() {
250         llvm_err(sess.diagnostic().handler(),
251                  format!("Could not create LLVM TargetMachine for triple: {}",
252                          triple).to_string());
253     } else {
254         return tm;
255     };
256 }
257
258
259 /// Module-specific configuration for `optimize_and_codegen`.
260 #[deriving(Clone)]
261 struct ModuleConfig {
262     /// LLVM TargetMachine to use for codegen.
263     tm: TargetMachineRef,
264     /// Names of additional optimization passes to run.
265     passes: Vec<String>,
266     /// Some(level) to optimize at a certain level, or None to run
267     /// absolutely no optimizations (used for the metadata module).
268     opt_level: Option<llvm::CodeGenOptLevel>,
269
270     // Flags indicating which outputs to produce.
271     emit_no_opt_bc: bool,
272     emit_bc: bool,
273     emit_lto_bc: bool,
274     emit_ir: bool,
275     emit_asm: bool,
276     emit_obj: bool,
277
278     // Miscellaneous flags.  These are mostly copied from command-line
279     // options.
280     no_verify: bool,
281     no_prepopulate_passes: bool,
282     no_builtins: bool,
283     time_passes: bool,
284 }
285
286 impl ModuleConfig {
287     fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig {
288         ModuleConfig {
289             tm: tm,
290             passes: passes,
291             opt_level: None,
292
293             emit_no_opt_bc: false,
294             emit_bc: false,
295             emit_lto_bc: false,
296             emit_ir: false,
297             emit_asm: false,
298             emit_obj: false,
299
300             no_verify: false,
301             no_prepopulate_passes: false,
302             no_builtins: false,
303             time_passes: false,
304         }
305     }
306
307     fn set_flags(&mut self, sess: &Session, trans: &CrateTranslation) {
308         self.no_verify = sess.no_verify();
309         self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
310         self.no_builtins = trans.no_builtins;
311         self.time_passes = sess.time_passes();
312     }
313 }
314
315 /// Additional resources used by optimize_and_codegen (not module specific)
316 struct CodegenContext<'a> {
317     // Extra resources used for LTO: (sess, reachable).  This will be `None`
318     // when running in a worker thread.
319     lto_ctxt: Option<(&'a Session, &'a [String])>,
320     // Handler to use for diagnostics produced during codegen.
321     handler: &'a Handler,
322     // LLVM optimizations for which we want to print remarks.
323     remark: Passes,
324 }
325
326 impl<'a> CodegenContext<'a> {
327     fn new_with_session(sess: &'a Session, reachable: &'a [String]) -> CodegenContext<'a> {
328         CodegenContext {
329             lto_ctxt: Some((sess, reachable)),
330             handler: sess.diagnostic().handler(),
331             remark: sess.opts.cg.remark.clone(),
332         }
333     }
334 }
335
336 struct HandlerFreeVars<'a> {
337     llcx: ContextRef,
338     cgcx: &'a CodegenContext<'a>,
339 }
340
341 unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
342                                         user: *const c_void,
343                                         cookie: c_uint) {
344     use syntax::codemap::ExpnId;
345
346     let HandlerFreeVars { cgcx, .. }
347         = *mem::transmute::<_, *const HandlerFreeVars>(user);
348
349     let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
350         .expect("non-UTF8 SMDiagnostic");
351
352     match cgcx.lto_ctxt {
353         Some((sess, _)) => {
354             sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info {
355                 Some(ei) => sess.span_err(ei.call_site, msg.as_slice()),
356                 None     => sess.err(msg.as_slice()),
357             });
358         }
359
360         None => {
361             cgcx.handler.err(msg.as_slice());
362             cgcx.handler.note("build without -C codegen-units for more exact errors");
363         }
364     }
365 }
366
367 unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
368     let HandlerFreeVars { llcx, cgcx }
369         = *mem::transmute::<_, *const HandlerFreeVars>(user);
370
371     match llvm::diagnostic::Diagnostic::unpack(info) {
372         llvm::diagnostic::Optimization(opt) => {
373             let pass_name = CString::new(opt.pass_name, false);
374             let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
375             let enabled = match cgcx.remark {
376                 AllPasses => true,
377                 SomePasses(ref v) => v.iter().any(|s| *s == pass_name),
378             };
379
380             if enabled {
381                 let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
382                 cgcx.handler.note(format!("optimization {} for {} at {}: {}",
383                                           opt.kind.describe(),
384                                           pass_name,
385                                           if loc.is_empty() { "[unknown]" } else { loc.as_slice() },
386                                           llvm::twine_to_string(opt.message)).as_slice());
387             }
388         }
389
390         _ => (),
391     }
392 }
393
394 // Unsafe due to LLVM calls.
395 unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
396                                mtrans: ModuleTranslation,
397                                config: ModuleConfig,
398                                name_extra: String,
399                                output_names: OutputFilenames) {
400     let ModuleTranslation { llmod, llcx } = mtrans;
401     let tm = config.tm;
402
403     // llcx doesn't outlive this function, so we can put this on the stack.
404     let fv = HandlerFreeVars {
405         llcx: llcx,
406         cgcx: cgcx,
407     };
408     let fv = &fv as *const HandlerFreeVars as *mut c_void;
409
410     llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
411
412     if !cgcx.remark.is_empty() {
413         llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
414     }
415
416     if config.emit_no_opt_bc {
417         let ext = format!("{}.no-opt.bc", name_extra);
418         output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
419             llvm::LLVMWriteBitcodeToFile(llmod, buf);
420         })
421     }
422
423     match config.opt_level {
424         Some(opt_level) => {
425             // Create the two optimizing pass managers. These mirror what clang
426             // does, and are by populated by LLVM's default PassManagerBuilder.
427             // Each manager has a different set of passes, but they also share
428             // some common passes.
429             let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
430             let mpm = llvm::LLVMCreatePassManager();
431
432             // If we're verifying or linting, add them to the function pass
433             // manager.
434             let addpass = |pass: &str| {
435                 pass.with_c_str(|s| llvm::LLVMRustAddPass(fpm, s))
436             };
437             if !config.no_verify { assert!(addpass("verify")); }
438
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,
443                                      config.no_builtins);
444             }
445
446             for pass in config.passes.iter() {
447                 pass.with_c_str(|s| {
448                     if !llvm::LLVMRustAddPass(mpm, s) {
449                         cgcx.handler.warn(format!("unknown pass {}, ignoring",
450                                                   *pass).as_slice());
451                     }
452                 })
453             }
454
455             // Finally, run the actual optimization passes
456             time(config.time_passes, "llvm function passes", (), |()|
457                  llvm::LLVMRustRunFunctionPassManager(fpm, llmod));
458             time(config.time_passes, "llvm module passes", (), |()|
459                  llvm::LLVMRunPassManager(mpm, llmod));
460
461             // Deallocate managers that we're now done with
462             llvm::LLVMDisposePassManager(fpm);
463             llvm::LLVMDisposePassManager(mpm);
464
465             match cgcx.lto_ctxt {
466                 Some((sess, reachable)) if sess.lto() =>  {
467                     time(sess.time_passes(), "all lto passes", (), |()|
468                          lto::run(sess, llmod, tm, reachable));
469
470                     if config.emit_lto_bc {
471                         let name = format!("{}.lto.bc", name_extra);
472                         output_names.with_extension(name.as_slice()).with_c_str(|buf| {
473                             llvm::LLVMWriteBitcodeToFile(llmod, buf);
474                         })
475                     }
476                 },
477                 _ => {},
478             }
479         },
480         None => {},
481     }
482
483     // A codegen-specific pass manager is used to generate object
484     // files for an LLVM module.
485     //
486     // Apparently each of these pass managers is a one-shot kind of
487     // thing, so we create a new one for each type of output. The
488     // pass manager passed to the closure should be ensured to not
489     // escape the closure itself, and the manager should only be
490     // used once.
491     unsafe fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
492                     no_builtins: bool, f: |PassManagerRef|) {
493         let cpm = llvm::LLVMCreatePassManager();
494         llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
495         llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
496         f(cpm);
497         llvm::LLVMDisposePassManager(cpm);
498     }
499
500     if config.emit_bc {
501         let ext = format!("{}.bc", name_extra);
502         output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
503             llvm::LLVMWriteBitcodeToFile(llmod, buf);
504         })
505     }
506
507     time(config.time_passes, "codegen passes", (), |()| {
508         if config.emit_ir {
509             let ext = format!("{}.ll", name_extra);
510             output_names.with_extension(ext.as_slice()).with_c_str(|output| {
511                 with_codegen(tm, llmod, config.no_builtins, |cpm| {
512                     llvm::LLVMRustPrintModule(cpm, llmod, output);
513                 })
514             })
515         }
516
517         if config.emit_asm {
518             let path = output_names.with_extension(format!("{}.s", name_extra).as_slice());
519             with_codegen(tm, llmod, config.no_builtins, |cpm| {
520                 write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
521             });
522         }
523
524         if config.emit_obj {
525             let path = output_names.with_extension(format!("{}.o", name_extra).as_slice());
526             with_codegen(tm, llmod, config.no_builtins, |cpm| {
527                 write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::ObjectFileType);
528             });
529         }
530     });
531
532     llvm::LLVMDisposeModule(llmod);
533     llvm::LLVMContextDispose(llcx);
534     llvm::LLVMRustDisposeTargetMachine(tm);
535 }
536
537 pub fn run_passes(sess: &Session,
538                   trans: &CrateTranslation,
539                   output_types: &[config::OutputType],
540                   crate_output: &OutputFilenames) {
541     // It's possible that we have `codegen_units > 1` but only one item in
542     // `trans.modules`.  We could theoretically proceed and do LTO in that
543     // case, but it would be confusing to have the validity of
544     // `-Z lto -C codegen-units=2` depend on details of the crate being
545     // compiled, so we complain regardless.
546     if sess.lto() && sess.opts.cg.codegen_units > 1 {
547         // This case is impossible to handle because LTO expects to be able
548         // to combine the entire crate and all its dependencies into a
549         // single compilation unit, but each codegen unit is in a separate
550         // LLVM context, so they can't easily be combined.
551         sess.fatal("can't perform LTO when using multiple codegen units");
552     }
553
554     // Sanity check
555     assert!(trans.modules.len() == sess.opts.cg.codegen_units);
556
557     unsafe {
558         configure_llvm(sess);
559     }
560
561     let tm = create_target_machine(sess);
562
563     // Figure out what we actually need to build.
564
565     let mut modules_config = ModuleConfig::new(tm, sess.opts.cg.passes.clone());
566     let mut metadata_config = ModuleConfig::new(tm, vec!());
567
568     modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize));
569
570     // Save all versions of the bytecode if we're saving our temporaries.
571     if sess.opts.cg.save_temps {
572         modules_config.emit_no_opt_bc = true;
573         modules_config.emit_bc = true;
574         modules_config.emit_lto_bc = true;
575         metadata_config.emit_bc = true;
576     }
577
578     // Emit bitcode files for the crate if we're emitting an rlib.
579     // Whenever an rlib is created, the bitcode is inserted into the
580     // archive in order to allow LTO against it.
581     let needs_crate_bitcode =
582             sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
583             sess.opts.output_types.contains(&config::OutputTypeExe);
584     if needs_crate_bitcode {
585         modules_config.emit_bc = true;
586     }
587
588     for output_type in output_types.iter() {
589         match *output_type {
590             config::OutputTypeBitcode => { modules_config.emit_bc = true; },
591             config::OutputTypeLlvmAssembly => { modules_config.emit_ir = true; },
592             config::OutputTypeAssembly => {
593                 modules_config.emit_asm = true;
594                 // If we're not using the LLVM assembler, this function
595                 // could be invoked specially with output_type_assembly, so
596                 // in this case we still want the metadata object file.
597                 if !sess.opts.output_types.contains(&config::OutputTypeAssembly) {
598                     metadata_config.emit_obj = true;
599                 }
600             },
601             config::OutputTypeObject => { modules_config.emit_obj = true; },
602             config::OutputTypeExe => {
603                 modules_config.emit_obj = true;
604                 metadata_config.emit_obj = true;
605             },
606         }
607     }
608
609     modules_config.set_flags(sess, trans);
610     metadata_config.set_flags(sess, trans);
611
612
613     // Populate a buffer with a list of codegen tasks.  Items are processed in
614     // LIFO order, just because it's a tiny bit simpler that way.  (The order
615     // doesn't actually matter.)
616     let mut work_items = Vec::with_capacity(1 + trans.modules.len());
617
618     {
619         let work = build_work_item(sess,
620                                    trans.metadata_module,
621                                    metadata_config.clone(),
622                                    crate_output.clone(),
623                                    "metadata".to_string());
624         work_items.push(work);
625     }
626
627     for (index, mtrans) in trans.modules.iter().enumerate() {
628         let work = build_work_item(sess,
629                                    *mtrans,
630                                    modules_config.clone(),
631                                    crate_output.clone(),
632                                    format!("{}", index));
633         work_items.push(work);
634     }
635
636     // Process the work items, optionally using worker threads.
637     if sess.opts.cg.codegen_units == 1 {
638         run_work_singlethreaded(sess, trans.reachable.as_slice(), work_items);
639     } else {
640         run_work_multithreaded(sess, work_items, sess.opts.cg.codegen_units);
641     }
642
643     // All codegen is finished.
644     unsafe {
645         llvm::LLVMRustDisposeTargetMachine(tm);
646     }
647
648     // Produce final compile outputs.
649
650     let copy_if_one_unit = |ext: &str, output_type: config::OutputType, keep_numbered: bool| {
651         // Three cases:
652         if sess.opts.cg.codegen_units == 1 {
653             // 1) Only one codegen unit.  In this case it's no difficulty
654             //    to copy `foo.0.x` to `foo.x`.
655             fs::copy(&crate_output.with_extension(ext),
656                      &crate_output.path(output_type)).unwrap();
657             if !sess.opts.cg.save_temps && !keep_numbered {
658                 // The user just wants `foo.x`, not `foo.0.x`.
659                 remove(sess, &crate_output.with_extension(ext));
660             }
661         } else {
662             if crate_output.single_output_file.is_some() {
663                 // 2) Multiple codegen units, with `-o some_name`.  We have
664                 //    no good solution for this case, so warn the user.
665                 sess.warn(format!("ignoring -o because multiple .{} files were produced",
666                                   ext).as_slice());
667             } else {
668                 // 3) Multiple codegen units, but no `-o some_name`.  We
669                 //    just leave the `foo.0.x` files in place.
670                 // (We don't have to do any work in this case.)
671             }
672         }
673     };
674
675     let link_obj = |output_path: &Path| {
676         // Running `ld -r` on a single input is kind of pointless.
677         if sess.opts.cg.codegen_units == 1 {
678             fs::copy(&crate_output.with_extension("0.o"),
679                      output_path).unwrap();
680             // Leave the .0.o file around, to mimic the behavior of the normal
681             // code path.
682             return;
683         }
684
685         // Some builds of MinGW GCC will pass --force-exe-suffix to ld, which
686         // will automatically add a .exe extension if the extension is not
687         // already .exe or .dll.  To ensure consistent behavior on Windows, we
688         // add the .exe suffix explicitly and then rename the output file to
689         // the desired path.  This will give the correct behavior whether or
690         // not GCC adds --force-exe-suffix.
691         let windows_output_path =
692             if sess.target.target.options.is_like_windows {
693                 Some(output_path.with_extension("o.exe"))
694             } else {
695                 None
696             };
697
698         let pname = get_cc_prog(sess);
699         let mut cmd = Command::new(pname.as_slice());
700
701         cmd.args(sess.target.target.options.pre_link_args.as_slice());
702         cmd.arg("-nostdlib");
703
704         for index in range(0, trans.modules.len()) {
705             cmd.arg(crate_output.with_extension(format!("{}.o", index).as_slice()));
706         }
707
708         cmd.arg("-r")
709            .arg("-o")
710            .arg(windows_output_path.as_ref().unwrap_or(output_path));
711
712         cmd.args(sess.target.target.options.post_link_args.as_slice());
713
714         if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
715             println!("{}", &cmd);
716         }
717
718         cmd.stdin(::std::io::process::Ignored)
719            .stdout(::std::io::process::InheritFd(1))
720            .stderr(::std::io::process::InheritFd(2));
721         match cmd.status() {
722             Ok(status) => {
723                 if !status.success() {
724                     sess.err(format!("linking of {} with `{}` failed",
725                                      output_path.display(), cmd).as_slice());
726                     sess.abort_if_errors();
727                 }
728             },
729             Err(e) => {
730                 sess.err(format!("could not exec the linker `{}`: {}",
731                                  pname,
732                                  e).as_slice());
733                 sess.abort_if_errors();
734             },
735         }
736
737         match windows_output_path {
738             Some(ref windows_path) => {
739                 fs::rename(windows_path, output_path).unwrap();
740             },
741             None => {
742                 // The file is already named according to `output_path`.
743             }
744         }
745     };
746
747     // Flag to indicate whether the user explicitly requested bitcode.
748     // Otherwise, we produced it only as a temporary output, and will need
749     // to get rid of it.
750     let mut user_wants_bitcode = false;
751     for output_type in output_types.iter() {
752         match *output_type {
753             config::OutputTypeBitcode => {
754                 user_wants_bitcode = true;
755                 // Copy to .bc, but always keep the .0.bc.  There is a later
756                 // check to figure out if we should delete .0.bc files, or keep
757                 // them for making an rlib.
758                 copy_if_one_unit("0.bc", config::OutputTypeBitcode, true);
759             }
760             config::OutputTypeLlvmAssembly => {
761                 copy_if_one_unit("0.ll", config::OutputTypeLlvmAssembly, false);
762             }
763             config::OutputTypeAssembly => {
764                 copy_if_one_unit("0.s", config::OutputTypeAssembly, false);
765             }
766             config::OutputTypeObject => {
767                 link_obj(&crate_output.path(config::OutputTypeObject));
768             }
769             config::OutputTypeExe => {
770                 // If config::OutputTypeObject is already in the list, then
771                 // `crate.o` will be handled by the config::OutputTypeObject case.
772                 // Otherwise, we need to create the temporary object so we
773                 // can run the linker.
774                 if !sess.opts.output_types.contains(&config::OutputTypeObject) {
775                     link_obj(&crate_output.temp_path(config::OutputTypeObject));
776                 }
777             }
778         }
779     }
780     let user_wants_bitcode = user_wants_bitcode;
781
782     // Clean up unwanted temporary files.
783
784     // We create the following files by default:
785     //  - crate.0.bc
786     //  - crate.0.o
787     //  - crate.metadata.bc
788     //  - crate.metadata.o
789     //  - crate.o (linked from crate.##.o)
790     //  - crate.bc (copied from crate.0.bc)
791     // We may create additional files if requested by the user (through
792     // `-C save-temps` or `--emit=` flags).
793
794     if !sess.opts.cg.save_temps {
795         // Remove the temporary .0.o objects.  If the user didn't
796         // explicitly request bitcode (with --emit=bc), and the bitcode is not
797         // needed for building an rlib, then we must remove .0.bc as well.
798
799         // Specific rules for keeping .0.bc:
800         //  - If we're building an rlib (`needs_crate_bitcode`), then keep
801         //    it.
802         //  - If the user requested bitcode (`user_wants_bitcode`), and
803         //    codegen_units > 1, then keep it.
804         //  - If the user requested bitcode but codegen_units == 1, then we
805         //    can toss .0.bc because we copied it to .bc earlier.
806         //  - If we're not building an rlib and the user didn't request
807         //    bitcode, then delete .0.bc.
808         // If you change how this works, also update back::link::link_rlib,
809         // where .0.bc files are (maybe) deleted after making an rlib.
810         let keep_numbered_bitcode = needs_crate_bitcode ||
811                 (user_wants_bitcode && sess.opts.cg.codegen_units > 1);
812
813         for i in range(0, trans.modules.len()) {
814             if modules_config.emit_obj {
815                 let ext = format!("{}.o", i);
816                 remove(sess, &crate_output.with_extension(ext.as_slice()));
817             }
818
819             if modules_config.emit_bc && !keep_numbered_bitcode {
820                 let ext = format!("{}.bc", i);
821                 remove(sess, &crate_output.with_extension(ext.as_slice()));
822             }
823         }
824
825         if metadata_config.emit_bc && !user_wants_bitcode {
826             remove(sess, &crate_output.with_extension("metadata.bc"));
827         }
828     }
829
830     // We leave the following files around by default:
831     //  - crate.o
832     //  - crate.metadata.o
833     //  - crate.bc
834     // These are used in linking steps and will be cleaned up afterward.
835
836     // FIXME: time_llvm_passes support - does this use a global context or
837     // something?
838     //if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
839 }
840
841 type WorkItem = proc(&CodegenContext):Send;
842
843 fn build_work_item(sess: &Session,
844                    mtrans: ModuleTranslation,
845                    config: ModuleConfig,
846                    output_names: OutputFilenames,
847                    name_extra: String) -> WorkItem {
848     let mut config = config;
849     config.tm = create_target_machine(sess);
850
851     proc(cgcx) unsafe {
852         optimize_and_codegen(cgcx, mtrans, config, name_extra, output_names);
853     }
854 }
855
856 fn run_work_singlethreaded(sess: &Session,
857                            reachable: &[String],
858                            work_items: Vec<WorkItem>) {
859     let cgcx = CodegenContext::new_with_session(sess, reachable);
860     let mut work_items = work_items;
861
862     // Since we're running single-threaded, we can pass the session to
863     // the proc, allowing `optimize_and_codegen` to perform LTO.
864     for work in Unfold::new((), |_| work_items.pop()) {
865         work(&cgcx);
866     }
867 }
868
869 fn run_work_multithreaded(sess: &Session,
870                           work_items: Vec<WorkItem>,
871                           num_workers: uint) {
872     // Run some workers to process the work items.
873     let work_items_arc = Arc::new(Mutex::new(work_items));
874     let mut diag_emitter = SharedEmitter::new();
875     let mut futures = Vec::with_capacity(num_workers);
876
877     for i in range(0, num_workers) {
878         let work_items_arc = work_items_arc.clone();
879         let diag_emitter = diag_emitter.clone();
880         let remark = sess.opts.cg.remark.clone();
881
882         let future = TaskBuilder::new().named(format!("codegen-{}", i)).try_future(proc() {
883             let diag_handler = mk_handler(box diag_emitter);
884
885             // Must construct cgcx inside the proc because it has non-Send
886             // fields.
887             let cgcx = CodegenContext {
888                 lto_ctxt: None,
889                 handler: &diag_handler,
890                 remark: remark,
891             };
892
893             loop {
894                 // Avoid holding the lock for the entire duration of the match.
895                 let maybe_work = work_items_arc.lock().pop();
896                 match maybe_work {
897                     Some(work) => {
898                         work(&cgcx);
899
900                         // Make sure to fail the worker so the main thread can
901                         // tell that there were errors.
902                         cgcx.handler.abort_if_errors();
903                     }
904                     None => break,
905                 }
906             }
907         });
908         futures.push(future);
909     }
910
911     let mut panicked = false;
912     for future in futures.into_iter() {
913         match future.into_inner() {
914             Ok(()) => {},
915             Err(_) => {
916                 panicked = true;
917             },
918         }
919         // Display any new diagnostics.
920         diag_emitter.dump(sess.diagnostic().handler());
921     }
922     if panicked {
923         sess.fatal("aborting due to worker thread panic");
924     }
925 }
926
927 pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
928     let pname = get_cc_prog(sess);
929     let mut cmd = Command::new(pname.as_slice());
930
931     cmd.arg("-c").arg("-o").arg(outputs.path(config::OutputTypeObject))
932                            .arg(outputs.temp_path(config::OutputTypeAssembly));
933     debug!("{}", &cmd);
934
935     match cmd.output() {
936         Ok(prog) => {
937             if !prog.status.success() {
938                 sess.err(format!("linking with `{}` failed: {}",
939                                  pname,
940                                  prog.status).as_slice());
941                 sess.note(format!("{}", &cmd).as_slice());
942                 let mut note = prog.error.clone();
943                 note.push_all(prog.output.as_slice());
944                 sess.note(str::from_utf8(note.as_slice()).unwrap());
945                 sess.abort_if_errors();
946             }
947         },
948         Err(e) => {
949             sess.err(format!("could not exec the linker `{}`: {}",
950                              pname,
951                              e).as_slice());
952             sess.abort_if_errors();
953         }
954     }
955 }
956
957 unsafe fn configure_llvm(sess: &Session) {
958     use std::sync::{Once, ONCE_INIT};
959     static INIT: Once = ONCE_INIT;
960
961     // Copy what clang does by turning on loop vectorization at O2 and
962     // slp vectorization at O3
963     let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
964                          (sess.opts.optimize == config::Default ||
965                           sess.opts.optimize == config::Aggressive);
966     let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
967                         sess.opts.optimize == config::Aggressive;
968
969     let mut llvm_c_strs = Vec::new();
970     let mut llvm_args = Vec::new();
971     {
972         let add = |arg: &str| {
973             let s = arg.to_c_str();
974             llvm_args.push(s.as_ptr());
975             llvm_c_strs.push(s);
976         };
977         add("rustc"); // fake program name
978         if vectorize_loop { add("-vectorize-loops"); }
979         if vectorize_slp  { add("-vectorize-slp");   }
980         if sess.time_llvm_passes() { add("-time-passes"); }
981         if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
982
983         for arg in sess.opts.cg.llvm_args.iter() {
984             add((*arg).as_slice());
985         }
986     }
987
988     INIT.doit(|| {
989         llvm::LLVMInitializePasses();
990
991         // Only initialize the platforms supported by Rust here, because
992         // using --llvm-root will have multiple platforms that rustllvm
993         // doesn't actually link to and it's pointless to put target info
994         // into the registry that Rust cannot generate machine code for.
995         llvm::LLVMInitializeX86TargetInfo();
996         llvm::LLVMInitializeX86Target();
997         llvm::LLVMInitializeX86TargetMC();
998         llvm::LLVMInitializeX86AsmPrinter();
999         llvm::LLVMInitializeX86AsmParser();
1000
1001         llvm::LLVMInitializeARMTargetInfo();
1002         llvm::LLVMInitializeARMTarget();
1003         llvm::LLVMInitializeARMTargetMC();
1004         llvm::LLVMInitializeARMAsmPrinter();
1005         llvm::LLVMInitializeARMAsmParser();
1006
1007         llvm::LLVMInitializeMipsTargetInfo();
1008         llvm::LLVMInitializeMipsTarget();
1009         llvm::LLVMInitializeMipsTargetMC();
1010         llvm::LLVMInitializeMipsAsmPrinter();
1011         llvm::LLVMInitializeMipsAsmParser();
1012
1013         llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
1014                                      llvm_args.as_ptr());
1015     });
1016 }
1017
1018 unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
1019                                mpm: llvm::PassManagerRef,
1020                                llmod: ModuleRef,
1021                                opt: llvm::CodeGenOptLevel,
1022                                no_builtins: bool) {
1023     // Create the PassManagerBuilder for LLVM. We configure it with
1024     // reasonable defaults and prepare it to actually populate the pass
1025     // manager.
1026     let builder = llvm::LLVMPassManagerBuilderCreate();
1027     match opt {
1028         llvm::CodeGenLevelNone => {
1029             // Don't add lifetime intrinsics at O0
1030             llvm::LLVMRustAddAlwaysInlinePass(builder, false);
1031         }
1032         llvm::CodeGenLevelLess => {
1033             llvm::LLVMRustAddAlwaysInlinePass(builder, true);
1034         }
1035         // numeric values copied from clang
1036         llvm::CodeGenLevelDefault => {
1037             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
1038                                                                 225);
1039         }
1040         llvm::CodeGenLevelAggressive => {
1041             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
1042                                                                 275);
1043         }
1044     }
1045     llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
1046     llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
1047
1048     // Use the builder to populate the function/module pass managers.
1049     llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
1050     llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
1051     llvm::LLVMPassManagerBuilderDispose(builder);
1052
1053     match opt {
1054         llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
1055             "mergefunc".with_c_str(|s| llvm::LLVMRustAddPass(mpm, s));
1056         }
1057         _ => {}
1058     };
1059 }