]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/back/write.rs
Rollup merge of #39604 - est31:i128_tests, r=alexcrichton
[rust.git] / src / librustc_trans / back / write.rs
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.
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_linker, remove};
13 use back::symbol_export::ExportedSymbols;
14 use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
15 use session::config::{OutputFilenames, OutputTypes, Passes, SomePasses, AllPasses, Sanitizer};
16 use session::Session;
17 use session::config::{self, OutputType};
18 use llvm;
19 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
20 use llvm::SMDiagnosticRef;
21 use {CrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation};
22 use util::common::{time, time_depth, set_time_depth};
23 use util::common::path2cstr;
24 use util::fs::link_or_copy;
25 use errors::{self, Handler, Level, DiagnosticBuilder};
26 use errors::emitter::Emitter;
27 use syntax_pos::MultiSpan;
28 use context::{is_pie_binary, get_reloc_model};
29
30 use std::cmp;
31 use std::ffi::CString;
32 use std::fs;
33 use std::path::{Path, PathBuf};
34 use std::str;
35 use std::sync::{Arc, Mutex};
36 use std::sync::mpsc::channel;
37 use std::thread;
38 use libc::{c_uint, c_void};
39
40 pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 4] = [
41     ("pic", llvm::RelocMode::PIC),
42     ("static", llvm::RelocMode::Static),
43     ("default", llvm::RelocMode::Default),
44     ("dynamic-no-pic", llvm::RelocMode::DynamicNoPic),
45 ];
46
47 pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [
48     ("default", llvm::CodeModel::Default),
49     ("small", llvm::CodeModel::Small),
50     ("kernel", llvm::CodeModel::Kernel),
51     ("medium", llvm::CodeModel::Medium),
52     ("large", llvm::CodeModel::Large),
53 ];
54
55 pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! {
56     match llvm::last_error() {
57         Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))),
58         None => panic!(handler.fatal(&msg)),
59     }
60 }
61
62 pub fn write_output_file(
63         handler: &errors::Handler,
64         target: llvm::TargetMachineRef,
65         pm: llvm::PassManagerRef,
66         m: ModuleRef,
67         output: &Path,
68         file_type: llvm::FileType) {
69     unsafe {
70         let output_c = path2cstr(output);
71         let result = llvm::LLVMRustWriteOutputFile(
72                 target, pm, m, output_c.as_ptr(), file_type);
73         if result.into_result().is_err() {
74             llvm_err(handler, format!("could not write output to {}", output.display()));
75         }
76     }
77 }
78
79
80 struct Diagnostic {
81     msg: String,
82     code: Option<String>,
83     lvl: Level,
84 }
85
86 // We use an Arc instead of just returning a list of diagnostics from the
87 // child thread because we need to make sure that the messages are seen even
88 // if the child thread panics (for example, when `fatal` is called).
89 #[derive(Clone)]
90 struct SharedEmitter {
91     buffer: Arc<Mutex<Vec<Diagnostic>>>,
92 }
93
94 impl SharedEmitter {
95     fn new() -> SharedEmitter {
96         SharedEmitter {
97             buffer: Arc::new(Mutex::new(Vec::new())),
98         }
99     }
100
101     fn dump(&mut self, handler: &Handler) {
102         let mut buffer = self.buffer.lock().unwrap();
103         for diag in &*buffer {
104             match diag.code {
105                 Some(ref code) => {
106                     handler.emit_with_code(&MultiSpan::new(),
107                                            &diag.msg,
108                                            &code[..],
109                                            diag.lvl);
110                 },
111                 None => {
112                     handler.emit(&MultiSpan::new(),
113                                  &diag.msg,
114                                  diag.lvl);
115                 },
116             }
117         }
118         buffer.clear();
119     }
120 }
121
122 impl Emitter for SharedEmitter {
123     fn emit(&mut self, db: &DiagnosticBuilder) {
124         self.buffer.lock().unwrap().push(Diagnostic {
125             msg: db.message(),
126             code: db.code.clone(),
127             lvl: db.level,
128         });
129         for child in &db.children {
130             self.buffer.lock().unwrap().push(Diagnostic {
131                 msg: child.message(),
132                 code: None,
133                 lvl: child.level,
134             });
135         }
136     }
137 }
138
139 // On android, we by default compile for armv7 processors. This enables
140 // things like double word CAS instructions (rather than emulating them)
141 // which are *far* more efficient. This is obviously undesirable in some
142 // cases, so if any sort of target feature is specified we don't append v7
143 // to the feature list.
144 //
145 // On iOS only armv7 and newer are supported. So it is useful to
146 // get all hardware potential via VFP3 (hardware floating point)
147 // and NEON (SIMD) instructions supported by LLVM.
148 // Note that without those flags various linking errors might
149 // arise as some of intrinsics are converted into function calls
150 // and nobody provides implementations those functions
151 fn target_feature(sess: &Session) -> String {
152     let rustc_features = [
153         "crt-static",
154     ];
155     let requested_features = sess.opts.cg.target_feature.split(',');
156     let llvm_features = requested_features.filter(|f| {
157         !rustc_features.iter().any(|s| f.contains(s))
158     });
159     format!("{},{}",
160             sess.target.target.options.features,
161             llvm_features.collect::<Vec<_>>().join(","))
162 }
163
164 fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
165     match optimize {
166       config::OptLevel::No => llvm::CodeGenOptLevel::None,
167       config::OptLevel::Less => llvm::CodeGenOptLevel::Less,
168       config::OptLevel::Default => llvm::CodeGenOptLevel::Default,
169       config::OptLevel::Aggressive => llvm::CodeGenOptLevel::Aggressive,
170       _ => llvm::CodeGenOptLevel::Default,
171     }
172 }
173
174 fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize {
175     match optimize {
176       config::OptLevel::Size => llvm::CodeGenOptSizeDefault,
177       config::OptLevel::SizeMin => llvm::CodeGenOptSizeAggressive,
178       _ => llvm::CodeGenOptSizeNone,
179     }
180 }
181
182 pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
183     let reloc_model = get_reloc_model(sess);
184
185     let opt_level = get_llvm_opt_level(sess.opts.optimize);
186     let use_softfp = sess.opts.cg.soft_float;
187
188     let ffunction_sections = sess.target.target.options.function_sections;
189     let fdata_sections = ffunction_sections;
190
191     let code_model_arg = match sess.opts.cg.code_model {
192         Some(ref s) => &s[..],
193         None => &sess.target.target.options.code_model[..],
194     };
195
196     let code_model = match CODE_GEN_MODEL_ARGS.iter().find(
197         |&&arg| arg.0 == code_model_arg) {
198         Some(x) => x.1,
199         _ => {
200             sess.err(&format!("{:?} is not a valid code model",
201                              sess.opts
202                                  .cg
203                                  .code_model));
204             sess.abort_if_errors();
205             bug!();
206         }
207     };
208
209     let triple = &sess.target.target.llvm_target;
210
211     let tm = unsafe {
212         let triple = CString::new(triple.as_bytes()).unwrap();
213         let cpu = match sess.opts.cg.target_cpu {
214             Some(ref s) => &**s,
215             None => &*sess.target.target.options.cpu
216         };
217         let cpu = CString::new(cpu.as_bytes()).unwrap();
218         let features = CString::new(target_feature(sess).as_bytes()).unwrap();
219         llvm::LLVMRustCreateTargetMachine(
220             triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
221             code_model,
222             reloc_model,
223             opt_level,
224             use_softfp,
225             is_pie_binary(sess),
226             ffunction_sections,
227             fdata_sections,
228         )
229     };
230
231     if tm.is_null() {
232         llvm_err(sess.diagnostic(),
233                  format!("Could not create LLVM TargetMachine for triple: {}",
234                          triple).to_string());
235     } else {
236         return tm;
237     };
238 }
239
240
241 /// Module-specific configuration for `optimize_and_codegen`.
242 #[derive(Clone)]
243 pub struct ModuleConfig {
244     /// LLVM TargetMachine to use for codegen.
245     tm: TargetMachineRef,
246     /// Names of additional optimization passes to run.
247     passes: Vec<String>,
248     /// Some(level) to optimize at a certain level, or None to run
249     /// absolutely no optimizations (used for the metadata module).
250     opt_level: Option<llvm::CodeGenOptLevel>,
251
252     /// Some(level) to optimize binary size, or None to not affect program size.
253     opt_size: Option<llvm::CodeGenOptSize>,
254
255     // Flags indicating which outputs to produce.
256     emit_no_opt_bc: bool,
257     emit_bc: bool,
258     emit_lto_bc: bool,
259     emit_ir: bool,
260     emit_asm: bool,
261     emit_obj: bool,
262     // Miscellaneous flags.  These are mostly copied from command-line
263     // options.
264     no_verify: bool,
265     no_prepopulate_passes: bool,
266     no_builtins: bool,
267     time_passes: bool,
268     vectorize_loop: bool,
269     vectorize_slp: bool,
270     merge_functions: bool,
271     inline_threshold: Option<usize>,
272     // Instead of creating an object file by doing LLVM codegen, just
273     // make the object file bitcode. Provides easy compatibility with
274     // emscripten's ecc compiler, when used as the linker.
275     obj_is_bitcode: bool,
276 }
277
278 unsafe impl Send for ModuleConfig { }
279
280 impl ModuleConfig {
281     fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig {
282         ModuleConfig {
283             tm: tm,
284             passes: passes,
285             opt_level: None,
286             opt_size: None,
287
288             emit_no_opt_bc: false,
289             emit_bc: false,
290             emit_lto_bc: false,
291             emit_ir: false,
292             emit_asm: false,
293             emit_obj: false,
294             obj_is_bitcode: false,
295
296             no_verify: false,
297             no_prepopulate_passes: false,
298             no_builtins: false,
299             time_passes: false,
300             vectorize_loop: false,
301             vectorize_slp: false,
302             merge_functions: false,
303             inline_threshold: None
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         self.inline_threshold = sess.opts.cg.inline_threshold;
313         self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode;
314
315         // Copy what clang does by turning on loop vectorization at O2 and
316         // slp vectorization at O3. Otherwise configure other optimization aspects
317         // of this pass manager builder.
318         self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
319                              (sess.opts.optimize == config::OptLevel::Default ||
320                               sess.opts.optimize == config::OptLevel::Aggressive);
321         self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
322                             sess.opts.optimize == config::OptLevel::Aggressive;
323
324         self.merge_functions = sess.opts.optimize == config::OptLevel::Default ||
325                                sess.opts.optimize == config::OptLevel::Aggressive;
326     }
327 }
328
329 /// Additional resources used by optimize_and_codegen (not module specific)
330 struct CodegenContext<'a> {
331     // Extra resources used for LTO: (sess, reachable).  This will be `None`
332     // when running in a worker thread.
333     lto_ctxt: Option<(&'a Session, &'a ExportedSymbols)>,
334     // Handler to use for diagnostics produced during codegen.
335     handler: &'a Handler,
336     // LLVM passes added by plugins.
337     plugin_passes: Vec<String>,
338     // LLVM optimizations for which we want to print remarks.
339     remark: Passes,
340     // Worker thread number
341     worker: usize,
342     // The incremental compilation session directory, or None if we are not
343     // compiling incrementally
344     incr_comp_session_dir: Option<PathBuf>
345 }
346
347 impl<'a> CodegenContext<'a> {
348     fn new_with_session(sess: &'a Session,
349                         exported_symbols: &'a ExportedSymbols)
350                         -> CodegenContext<'a> {
351         CodegenContext {
352             lto_ctxt: Some((sess, exported_symbols)),
353             handler: sess.diagnostic(),
354             plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
355             remark: sess.opts.cg.remark.clone(),
356             worker: 0,
357             incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone())
358         }
359     }
360 }
361
362 struct HandlerFreeVars<'a> {
363     llcx: ContextRef,
364     cgcx: &'a CodegenContext<'a>,
365 }
366
367 unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>,
368                                                msg: &'b str,
369                                                cookie: c_uint) {
370     use syntax_pos::ExpnId;
371
372     match cgcx.lto_ctxt {
373         Some((sess, _)) => {
374             sess.codemap().with_expn_info(ExpnId::from_u32(cookie), |info| match info {
375                 Some(ei) => sess.span_err(ei.call_site, msg),
376                 None     => sess.err(msg),
377             });
378         }
379
380         None => {
381             cgcx.handler.struct_err(msg)
382                         .note("build without -C codegen-units for more exact errors")
383                         .emit();
384         }
385     }
386 }
387
388 unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
389                                         user: *const c_void,
390                                         cookie: c_uint) {
391     let HandlerFreeVars { cgcx, .. } = *(user as *const HandlerFreeVars);
392
393     let msg = llvm::build_string(|s| llvm::LLVMRustWriteSMDiagnosticToString(diag, s))
394         .expect("non-UTF8 SMDiagnostic");
395
396     report_inline_asm(cgcx, &msg[..], cookie);
397 }
398
399 unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
400     let HandlerFreeVars { llcx, cgcx } = *(user as *const HandlerFreeVars);
401
402     match llvm::diagnostic::Diagnostic::unpack(info) {
403         llvm::diagnostic::InlineAsm(inline) => {
404             report_inline_asm(cgcx,
405                               &llvm::twine_to_string(inline.message),
406                               inline.cookie);
407         }
408
409         llvm::diagnostic::Optimization(opt) => {
410             let enabled = match cgcx.remark {
411                 AllPasses => true,
412                 SomePasses(ref v) => v.iter().any(|s| *s == opt.pass_name),
413             };
414
415             if enabled {
416                 let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
417                 cgcx.handler.note_without_error(&format!("optimization {} for {} at {}: {}",
418                                                 opt.kind.describe(),
419                                                 opt.pass_name,
420                                                 if loc.is_empty() { "[unknown]" } else { &*loc },
421                                                 opt.message));
422             }
423         }
424
425         _ => (),
426     }
427 }
428
429 // Unsafe due to LLVM calls.
430 unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
431                                mtrans: ModuleTranslation,
432                                mllvm: ModuleLlvm,
433                                config: ModuleConfig,
434                                output_names: OutputFilenames) {
435     let llmod = mllvm.llmod;
436     let llcx = mllvm.llcx;
437     let tm = config.tm;
438
439     // llcx doesn't outlive this function, so we can put this on the stack.
440     let fv = HandlerFreeVars {
441         llcx: llcx,
442         cgcx: cgcx,
443     };
444     let fv = &fv as *const HandlerFreeVars as *mut c_void;
445
446     llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
447     llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
448
449     let module_name = Some(&mtrans.name[..]);
450
451     if config.emit_no_opt_bc {
452         let out = output_names.temp_path_ext("no-opt.bc", module_name);
453         let out = path2cstr(&out);
454         llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
455     }
456
457     if config.opt_level.is_some() {
458         // Create the two optimizing pass managers. These mirror what clang
459         // does, and are by populated by LLVM's default PassManagerBuilder.
460         // Each manager has a different set of passes, but they also share
461         // some common passes.
462         let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
463         let mpm = llvm::LLVMCreatePassManager();
464
465         // If we're verifying or linting, add them to the function pass
466         // manager.
467         let addpass = |pass_name: &str| {
468             let pass_name = CString::new(pass_name).unwrap();
469             let pass = llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr());
470             if pass.is_null() {
471                 return false;
472             }
473             let pass_manager = match llvm::LLVMRustPassKind(pass) {
474                 llvm::PassKind::Function => fpm,
475                 llvm::PassKind::Module => mpm,
476                 llvm::PassKind::Other => {
477                     cgcx.handler.err("Encountered LLVM pass kind we can't handle");
478                     return true
479                 },
480             };
481             llvm::LLVMRustAddPass(pass_manager, pass);
482             true
483         };
484
485         if !config.no_verify { assert!(addpass("verify")); }
486         if !config.no_prepopulate_passes {
487             llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
488             llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
489             with_llvm_pmb(llmod, &config, &mut |b| {
490                 llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
491                 llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
492             })
493         }
494
495         for pass in &config.passes {
496             if !addpass(pass) {
497                 cgcx.handler.warn(&format!("unknown pass `{}`, ignoring",
498                                            pass));
499             }
500         }
501
502         for pass in &cgcx.plugin_passes {
503             if !addpass(pass) {
504                 cgcx.handler.err(&format!("a plugin asked for LLVM pass \
505                                            `{}` but LLVM does not \
506                                            recognize it", pass));
507             }
508         }
509
510         cgcx.handler.abort_if_errors();
511
512         // Finally, run the actual optimization passes
513         time(config.time_passes, &format!("llvm function passes [{}]", cgcx.worker), ||
514              llvm::LLVMRustRunFunctionPassManager(fpm, llmod));
515         time(config.time_passes, &format!("llvm module passes [{}]", cgcx.worker), ||
516              llvm::LLVMRunPassManager(mpm, llmod));
517
518         // Deallocate managers that we're now done with
519         llvm::LLVMDisposePassManager(fpm);
520         llvm::LLVMDisposePassManager(mpm);
521
522         match cgcx.lto_ctxt {
523             Some((sess, exported_symbols)) if sess.lto() =>  {
524                 time(sess.time_passes(), "all lto passes", || {
525                     let temp_no_opt_bc_filename =
526                         output_names.temp_path_ext("no-opt.lto.bc", module_name);
527                     lto::run(sess,
528                              llmod,
529                              tm,
530                              exported_symbols,
531                              &config,
532                              &temp_no_opt_bc_filename);
533                 });
534                 if config.emit_lto_bc {
535                     let out = output_names.temp_path_ext("lto.bc", module_name);
536                     let out = path2cstr(&out);
537                     llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
538                 }
539             },
540             _ => {},
541         }
542     }
543
544     // A codegen-specific pass manager is used to generate object
545     // files for an LLVM module.
546     //
547     // Apparently each of these pass managers is a one-shot kind of
548     // thing, so we create a new one for each type of output. The
549     // pass manager passed to the closure should be ensured to not
550     // escape the closure itself, and the manager should only be
551     // used once.
552     unsafe fn with_codegen<F>(tm: TargetMachineRef,
553                               llmod: ModuleRef,
554                               no_builtins: bool,
555                               f: F) where
556         F: FnOnce(PassManagerRef),
557     {
558         let cpm = llvm::LLVMCreatePassManager();
559         llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
560         llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
561         f(cpm);
562     }
563
564     // Change what we write and cleanup based on whether obj files are
565     // just llvm bitcode. In that case write bitcode, and possibly
566     // delete the bitcode if it wasn't requested. Don't generate the
567     // machine code, instead copy the .o file from the .bc
568     let write_bc = config.emit_bc || config.obj_is_bitcode;
569     let rm_bc = !config.emit_bc && config.obj_is_bitcode;
570     let write_obj = config.emit_obj && !config.obj_is_bitcode;
571     let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
572
573     let bc_out = output_names.temp_path(OutputType::Bitcode, module_name);
574     let obj_out = output_names.temp_path(OutputType::Object, module_name);
575
576     if write_bc {
577         let bc_out_c = path2cstr(&bc_out);
578         llvm::LLVMWriteBitcodeToFile(llmod, bc_out_c.as_ptr());
579     }
580
581     time(config.time_passes, &format!("codegen passes [{}]", cgcx.worker), || {
582         if config.emit_ir {
583             let out = output_names.temp_path(OutputType::LlvmAssembly, module_name);
584             let out = path2cstr(&out);
585             with_codegen(tm, llmod, config.no_builtins, |cpm| {
586                 llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
587                 llvm::LLVMDisposePassManager(cpm);
588             })
589         }
590
591         if config.emit_asm {
592             let path = output_names.temp_path(OutputType::Assembly, module_name);
593
594             // We can't use the same module for asm and binary output, because that triggers
595             // various errors like invalid IR or broken binaries, so we might have to clone the
596             // module to produce the asm output
597             let llmod = if config.emit_obj {
598                 llvm::LLVMCloneModule(llmod)
599             } else {
600                 llmod
601             };
602             with_codegen(tm, llmod, config.no_builtins, |cpm| {
603                 write_output_file(cgcx.handler, tm, cpm, llmod, &path,
604                                   llvm::FileType::AssemblyFile);
605             });
606             if config.emit_obj {
607                 llvm::LLVMDisposeModule(llmod);
608             }
609         }
610
611         if write_obj {
612             with_codegen(tm, llmod, config.no_builtins, |cpm| {
613                 write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out,
614                                   llvm::FileType::ObjectFile);
615             });
616         }
617     });
618
619     if copy_bc_to_obj {
620         debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
621         if let Err(e) = link_or_copy(&bc_out, &obj_out) {
622             cgcx.handler.err(&format!("failed to copy bitcode to object file: {}", e));
623         }
624     }
625
626     if rm_bc {
627         debug!("removing_bitcode {:?}", bc_out);
628         if let Err(e) = fs::remove_file(&bc_out) {
629             cgcx.handler.err(&format!("failed to remove bitcode: {}", e));
630         }
631     }
632
633     llvm::LLVMRustDisposeTargetMachine(tm);
634 }
635
636
637 pub fn cleanup_llvm(trans: &CrateTranslation) {
638     for module in trans.modules.iter() {
639         unsafe {
640             match module.source {
641                 ModuleSource::Translated(llvm) => {
642                     llvm::LLVMDisposeModule(llvm.llmod);
643                     llvm::LLVMContextDispose(llvm.llcx);
644                 }
645                 ModuleSource::Preexisting(_) => {
646                 }
647             }
648         }
649     }
650 }
651
652 pub fn run_passes(sess: &Session,
653                   trans: &CrateTranslation,
654                   output_types: &OutputTypes,
655                   crate_output: &OutputFilenames) {
656     // It's possible that we have `codegen_units > 1` but only one item in
657     // `trans.modules`.  We could theoretically proceed and do LTO in that
658     // case, but it would be confusing to have the validity of
659     // `-Z lto -C codegen-units=2` depend on details of the crate being
660     // compiled, so we complain regardless.
661     if sess.lto() && sess.opts.cg.codegen_units > 1 {
662         // This case is impossible to handle because LTO expects to be able
663         // to combine the entire crate and all its dependencies into a
664         // single compilation unit, but each codegen unit is in a separate
665         // LLVM context, so they can't easily be combined.
666         sess.fatal("can't perform LTO when using multiple codegen units");
667     }
668
669     // Sanity check
670     assert!(trans.modules.len() == sess.opts.cg.codegen_units ||
671             sess.opts.debugging_opts.incremental.is_some() ||
672             !sess.opts.output_types.should_trans() ||
673             sess.opts.debugging_opts.no_trans);
674
675     let tm = create_target_machine(sess);
676
677     // Figure out what we actually need to build.
678
679     let mut modules_config = ModuleConfig::new(tm, sess.opts.cg.passes.clone());
680     let mut metadata_config = ModuleConfig::new(tm, vec![]);
681
682     if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer {
683         match *sanitizer {
684             Sanitizer::Address => {
685                 modules_config.passes.push("asan".to_owned());
686                 modules_config.passes.push("asan-module".to_owned());
687             }
688             Sanitizer::Memory => {
689                 modules_config.passes.push("msan".to_owned())
690             }
691             Sanitizer::Thread => {
692                 modules_config.passes.push("tsan".to_owned())
693             }
694             _ => {}
695         }
696     }
697
698     modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize));
699     modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize));
700
701     // Save all versions of the bytecode if we're saving our temporaries.
702     if sess.opts.cg.save_temps {
703         modules_config.emit_no_opt_bc = true;
704         modules_config.emit_bc = true;
705         modules_config.emit_lto_bc = true;
706         metadata_config.emit_bc = true;
707     }
708
709     // Emit bitcode files for the crate if we're emitting an rlib.
710     // Whenever an rlib is created, the bitcode is inserted into the
711     // archive in order to allow LTO against it.
712     let needs_crate_bitcode =
713             sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
714             sess.opts.output_types.contains_key(&OutputType::Exe);
715     let needs_crate_object =
716             sess.opts.output_types.contains_key(&OutputType::Exe);
717     if needs_crate_bitcode {
718         modules_config.emit_bc = true;
719     }
720
721     for output_type in output_types.keys() {
722         match *output_type {
723             OutputType::Bitcode => { modules_config.emit_bc = true; }
724             OutputType::LlvmAssembly => { modules_config.emit_ir = true; }
725             OutputType::Assembly => {
726                 modules_config.emit_asm = true;
727                 // If we're not using the LLVM assembler, this function
728                 // could be invoked specially with output_type_assembly, so
729                 // in this case we still want the metadata object file.
730                 if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
731                     metadata_config.emit_obj = true;
732                 }
733             }
734             OutputType::Object => { modules_config.emit_obj = true; }
735             OutputType::Metadata => { metadata_config.emit_obj = true; }
736             OutputType::Exe => {
737                 modules_config.emit_obj = true;
738                 metadata_config.emit_obj = true;
739             },
740             OutputType::DepInfo => {}
741         }
742     }
743
744     modules_config.set_flags(sess, trans);
745     metadata_config.set_flags(sess, trans);
746
747
748     // Populate a buffer with a list of codegen threads.  Items are processed in
749     // LIFO order, just because it's a tiny bit simpler that way.  (The order
750     // doesn't actually matter.)
751     let mut work_items = Vec::with_capacity(1 + trans.modules.len());
752
753     {
754         let work = build_work_item(sess,
755                                    trans.metadata_module.clone(),
756                                    metadata_config.clone(),
757                                    crate_output.clone());
758         work_items.push(work);
759     }
760
761     for mtrans in trans.modules.iter() {
762         let work = build_work_item(sess,
763                                    mtrans.clone(),
764                                    modules_config.clone(),
765                                    crate_output.clone());
766         work_items.push(work);
767     }
768
769     if sess.opts.debugging_opts.incremental_info {
770         dump_incremental_data(&trans);
771     }
772
773     // Process the work items, optionally using worker threads.
774     // NOTE: We are hardcoding a limit of worker threads for now. With
775     //       incremental compilation we can run into situations where we would
776     //       open hundreds of threads otherwise -- which can make things slower
777     //       if things don't fit into memory anymore, or can cause the compiler
778     //       to crash because of too many open file handles. See #39280 for
779     //       some discussion on how to improve this in the future.
780     let num_workers = cmp::min(work_items.len() - 1, 32);
781     if num_workers <= 1 {
782         run_work_singlethreaded(sess, &trans.exported_symbols, work_items);
783     } else {
784         run_work_multithreaded(sess, work_items, num_workers);
785     }
786
787     // If in incr. comp. mode, preserve the `.o` files for potential re-use
788     for mtrans in trans.modules.iter() {
789         let mut files = vec![];
790
791         if modules_config.emit_obj {
792             let path = crate_output.temp_path(OutputType::Object, Some(&mtrans.name));
793             files.push((OutputType::Object, path));
794         }
795
796         if modules_config.emit_bc {
797             let path = crate_output.temp_path(OutputType::Bitcode, Some(&mtrans.name));
798             files.push((OutputType::Bitcode, path));
799         }
800
801         save_trans_partition(sess, &mtrans.name, mtrans.symbol_name_hash, &files);
802     }
803
804     // All codegen is finished.
805     unsafe {
806         llvm::LLVMRustDisposeTargetMachine(tm);
807     }
808
809     // Produce final compile outputs.
810     let copy_gracefully = |from: &Path, to: &Path| {
811         if let Err(e) = fs::copy(from, to) {
812             sess.err(&format!("could not copy {:?} to {:?}: {}", from, to, e));
813         }
814     };
815
816     let copy_if_one_unit = |output_type: OutputType,
817                             keep_numbered: bool| {
818         if trans.modules.len() == 1 {
819             // 1) Only one codegen unit.  In this case it's no difficulty
820             //    to copy `foo.0.x` to `foo.x`.
821             let module_name = Some(&(trans.modules[0].name)[..]);
822             let path = crate_output.temp_path(output_type, module_name);
823             copy_gracefully(&path,
824                             &crate_output.path(output_type));
825             if !sess.opts.cg.save_temps && !keep_numbered {
826                 // The user just wants `foo.x`, not `foo.#module-name#.x`.
827                 remove(sess, &path);
828             }
829         } else {
830             let ext = crate_output.temp_path(output_type, None)
831                                   .extension()
832                                   .unwrap()
833                                   .to_str()
834                                   .unwrap()
835                                   .to_owned();
836
837             if crate_output.outputs.contains_key(&output_type) {
838                 // 2) Multiple codegen units, with `--emit foo=some_name`.  We have
839                 //    no good solution for this case, so warn the user.
840                 sess.warn(&format!("ignoring emit path because multiple .{} files \
841                                     were produced", ext));
842             } else if crate_output.single_output_file.is_some() {
843                 // 3) Multiple codegen units, with `-o some_name`.  We have
844                 //    no good solution for this case, so warn the user.
845                 sess.warn(&format!("ignoring -o because multiple .{} files \
846                                     were produced", ext));
847             } else {
848                 // 4) Multiple codegen units, but no explicit name.  We
849                 //    just leave the `foo.0.x` files in place.
850                 // (We don't have to do any work in this case.)
851             }
852         }
853     };
854
855     // Flag to indicate whether the user explicitly requested bitcode.
856     // Otherwise, we produced it only as a temporary output, and will need
857     // to get rid of it.
858     let mut user_wants_bitcode = false;
859     let mut user_wants_objects = false;
860     for output_type in output_types.keys() {
861         match *output_type {
862             OutputType::Bitcode => {
863                 user_wants_bitcode = true;
864                 // Copy to .bc, but always keep the .0.bc.  There is a later
865                 // check to figure out if we should delete .0.bc files, or keep
866                 // them for making an rlib.
867                 copy_if_one_unit(OutputType::Bitcode, true);
868             }
869             OutputType::LlvmAssembly => {
870                 copy_if_one_unit(OutputType::LlvmAssembly, false);
871             }
872             OutputType::Assembly => {
873                 copy_if_one_unit(OutputType::Assembly, false);
874             }
875             OutputType::Object => {
876                 user_wants_objects = true;
877                 copy_if_one_unit(OutputType::Object, true);
878             }
879             OutputType::Metadata |
880             OutputType::Exe |
881             OutputType::DepInfo => {}
882         }
883     }
884     let user_wants_bitcode = user_wants_bitcode;
885
886     // Clean up unwanted temporary files.
887
888     // We create the following files by default:
889     //  - crate.#module-name#.bc
890     //  - crate.#module-name#.o
891     //  - crate.metadata.bc
892     //  - crate.metadata.o
893     //  - crate.o (linked from crate.##.o)
894     //  - crate.bc (copied from crate.##.bc)
895     // We may create additional files if requested by the user (through
896     // `-C save-temps` or `--emit=` flags).
897
898     if !sess.opts.cg.save_temps {
899         // Remove the temporary .#module-name#.o objects.  If the user didn't
900         // explicitly request bitcode (with --emit=bc), and the bitcode is not
901         // needed for building an rlib, then we must remove .#module-name#.bc as
902         // well.
903
904         // Specific rules for keeping .#module-name#.bc:
905         //  - If we're building an rlib (`needs_crate_bitcode`), then keep
906         //    it.
907         //  - If the user requested bitcode (`user_wants_bitcode`), and
908         //    codegen_units > 1, then keep it.
909         //  - If the user requested bitcode but codegen_units == 1, then we
910         //    can toss .#module-name#.bc because we copied it to .bc earlier.
911         //  - If we're not building an rlib and the user didn't request
912         //    bitcode, then delete .#module-name#.bc.
913         // If you change how this works, also update back::link::link_rlib,
914         // where .#module-name#.bc files are (maybe) deleted after making an
915         // rlib.
916         let keep_numbered_bitcode = needs_crate_bitcode ||
917                 (user_wants_bitcode && sess.opts.cg.codegen_units > 1);
918
919         let keep_numbered_objects = needs_crate_object ||
920                 (user_wants_objects && sess.opts.cg.codegen_units > 1);
921
922         for module_name in trans.modules.iter().map(|m| Some(&m.name[..])) {
923             if modules_config.emit_obj && !keep_numbered_objects {
924                 let path = crate_output.temp_path(OutputType::Object, module_name);
925                 remove(sess, &path);
926             }
927
928             if modules_config.emit_bc && !keep_numbered_bitcode {
929                 let path = crate_output.temp_path(OutputType::Bitcode, module_name);
930                 remove(sess, &path);
931             }
932         }
933
934         if metadata_config.emit_bc && !user_wants_bitcode {
935             let path = crate_output.temp_path(OutputType::Bitcode,
936                                               Some(&trans.metadata_module.name[..]));
937             remove(sess, &path);
938         }
939     }
940
941     // We leave the following files around by default:
942     //  - crate.o
943     //  - crate.metadata.o
944     //  - crate.bc
945     // These are used in linking steps and will be cleaned up afterward.
946
947     // FIXME: time_llvm_passes support - does this use a global context or
948     // something?
949     if sess.opts.cg.codegen_units == 1 && sess.time_llvm_passes() {
950         unsafe { llvm::LLVMRustPrintPassTimings(); }
951     }
952 }
953
954 fn dump_incremental_data(trans: &CrateTranslation) {
955     let mut reuse = 0;
956     for mtrans in trans.modules.iter() {
957         match mtrans.source {
958             ModuleSource::Preexisting(..) => reuse += 1,
959             ModuleSource::Translated(..) => (),
960         }
961     }
962     println!("incremental: re-using {} out of {} modules", reuse, trans.modules.len());
963 }
964
965 struct WorkItem {
966     mtrans: ModuleTranslation,
967     config: ModuleConfig,
968     output_names: OutputFilenames
969 }
970
971 fn build_work_item(sess: &Session,
972                    mtrans: ModuleTranslation,
973                    config: ModuleConfig,
974                    output_names: OutputFilenames)
975                    -> WorkItem
976 {
977     let mut config = config;
978     config.tm = create_target_machine(sess);
979     WorkItem {
980         mtrans: mtrans,
981         config: config,
982         output_names: output_names
983     }
984 }
985
986 fn execute_work_item(cgcx: &CodegenContext,
987                      work_item: WorkItem) {
988     unsafe {
989         match work_item.mtrans.source {
990             ModuleSource::Translated(mllvm) => {
991                 debug!("llvm-optimizing {:?}", work_item.mtrans.name);
992                 optimize_and_codegen(cgcx,
993                                      work_item.mtrans,
994                                      mllvm,
995                                      work_item.config,
996                                      work_item.output_names);
997             }
998             ModuleSource::Preexisting(wp) => {
999                 let incr_comp_session_dir = cgcx.incr_comp_session_dir
1000                                                 .as_ref()
1001                                                 .unwrap();
1002                 let name = &work_item.mtrans.name;
1003                 for (kind, saved_file) in wp.saved_files {
1004                     let obj_out = work_item.output_names.temp_path(kind, Some(name));
1005                     let source_file = in_incr_comp_dir(&incr_comp_session_dir,
1006                                                        &saved_file);
1007                     debug!("copying pre-existing module `{}` from {:?} to {}",
1008                            work_item.mtrans.name,
1009                            source_file,
1010                            obj_out.display());
1011                     match link_or_copy(&source_file, &obj_out) {
1012                         Ok(_) => { }
1013                         Err(err) => {
1014                             cgcx.handler.err(&format!("unable to copy {} to {}: {}",
1015                                                       source_file.display(),
1016                                                       obj_out.display(),
1017                                                       err));
1018                         }
1019                     }
1020                 }
1021             }
1022         }
1023     }
1024 }
1025
1026 fn run_work_singlethreaded(sess: &Session,
1027                            exported_symbols: &ExportedSymbols,
1028                            work_items: Vec<WorkItem>) {
1029     let cgcx = CodegenContext::new_with_session(sess, exported_symbols);
1030
1031     // Since we're running single-threaded, we can pass the session to
1032     // the proc, allowing `optimize_and_codegen` to perform LTO.
1033     for work in work_items.into_iter().rev() {
1034         execute_work_item(&cgcx, work);
1035     }
1036 }
1037
1038 fn run_work_multithreaded(sess: &Session,
1039                           work_items: Vec<WorkItem>,
1040                           num_workers: usize) {
1041     assert!(num_workers > 0);
1042
1043     // Run some workers to process the work items.
1044     let work_items_arc = Arc::new(Mutex::new(work_items));
1045     let mut diag_emitter = SharedEmitter::new();
1046     let mut futures = Vec::with_capacity(num_workers);
1047
1048     for i in 0..num_workers {
1049         let work_items_arc = work_items_arc.clone();
1050         let diag_emitter = diag_emitter.clone();
1051         let plugin_passes = sess.plugin_llvm_passes.borrow().clone();
1052         let remark = sess.opts.cg.remark.clone();
1053
1054         let (tx, rx) = channel();
1055         let mut tx = Some(tx);
1056         futures.push(rx);
1057
1058         let incr_comp_session_dir = sess.incr_comp_session_dir_opt().map(|r| r.clone());
1059
1060         let depth = time_depth();
1061         thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
1062             set_time_depth(depth);
1063
1064             let diag_handler = Handler::with_emitter(true, false, box diag_emitter);
1065
1066             // Must construct cgcx inside the proc because it has non-Send
1067             // fields.
1068             let cgcx = CodegenContext {
1069                 lto_ctxt: None,
1070                 handler: &diag_handler,
1071                 plugin_passes: plugin_passes,
1072                 remark: remark,
1073                 worker: i,
1074                 incr_comp_session_dir: incr_comp_session_dir
1075             };
1076
1077             loop {
1078                 // Avoid holding the lock for the entire duration of the match.
1079                 let maybe_work = work_items_arc.lock().unwrap().pop();
1080                 match maybe_work {
1081                     Some(work) => {
1082                         execute_work_item(&cgcx, work);
1083
1084                         // Make sure to fail the worker so the main thread can
1085                         // tell that there were errors.
1086                         cgcx.handler.abort_if_errors();
1087                     }
1088                     None => break,
1089                 }
1090             }
1091
1092             tx.take().unwrap().send(()).unwrap();
1093         }).unwrap();
1094     }
1095
1096     let mut panicked = false;
1097     for rx in futures {
1098         match rx.recv() {
1099             Ok(()) => {},
1100             Err(_) => {
1101                 panicked = true;
1102             },
1103         }
1104         // Display any new diagnostics.
1105         diag_emitter.dump(sess.diagnostic());
1106     }
1107     if panicked {
1108         sess.fatal("aborting due to worker thread panic");
1109     }
1110 }
1111
1112 pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
1113     let (pname, mut cmd, _) = get_linker(sess);
1114
1115     for arg in &sess.target.target.options.asm_args {
1116         cmd.arg(arg);
1117     }
1118
1119     cmd.arg("-c").arg("-o").arg(&outputs.path(OutputType::Object))
1120                            .arg(&outputs.temp_path(OutputType::Assembly, None));
1121     debug!("{:?}", cmd);
1122
1123     match cmd.output() {
1124         Ok(prog) => {
1125             if !prog.status.success() {
1126                 let mut note = prog.stderr.clone();
1127                 note.extend_from_slice(&prog.stdout);
1128
1129                 sess.struct_err(&format!("linking with `{}` failed: {}",
1130                                          pname,
1131                                          prog.status))
1132                     .note(&format!("{:?}", &cmd))
1133                     .note(str::from_utf8(&note[..]).unwrap())
1134                     .emit();
1135                 sess.abort_if_errors();
1136             }
1137         },
1138         Err(e) => {
1139             sess.err(&format!("could not exec the linker `{}`: {}", pname, e));
1140             sess.abort_if_errors();
1141         }
1142     }
1143 }
1144
1145 pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
1146                             config: &ModuleConfig,
1147                             f: &mut FnMut(llvm::PassManagerBuilderRef)) {
1148     // Create the PassManagerBuilder for LLVM. We configure it with
1149     // reasonable defaults and prepare it to actually populate the pass
1150     // manager.
1151     let builder = llvm::LLVMPassManagerBuilderCreate();
1152     let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
1153     let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
1154     let inline_threshold = config.inline_threshold;
1155
1156     llvm::LLVMRustConfigurePassManagerBuilder(builder, opt_level,
1157                                               config.merge_functions,
1158                                               config.vectorize_slp,
1159                                               config.vectorize_loop);
1160     llvm::LLVMPassManagerBuilderSetSizeLevel(builder, opt_size as u32);
1161
1162     if opt_size != llvm::CodeGenOptSizeNone {
1163         llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(builder, 1);
1164     }
1165
1166     llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
1167
1168     // Here we match what clang does (kinda). For O0 we only inline
1169     // always-inline functions (but don't add lifetime intrinsics), at O1 we
1170     // inline with lifetime intrinsics, and O2+ we add an inliner with a
1171     // thresholds copied from clang.
1172     match (opt_level, opt_size, inline_threshold) {
1173         (.., Some(t)) => {
1174             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
1175         }
1176         (llvm::CodeGenOptLevel::Aggressive, ..) => {
1177             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
1178         }
1179         (_, llvm::CodeGenOptSizeDefault, _) => {
1180             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 75);
1181         }
1182         (_, llvm::CodeGenOptSizeAggressive, _) => {
1183             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25);
1184         }
1185         (llvm::CodeGenOptLevel::None, ..) => {
1186             llvm::LLVMRustAddAlwaysInlinePass(builder, false);
1187         }
1188         (llvm::CodeGenOptLevel::Less, ..) => {
1189             llvm::LLVMRustAddAlwaysInlinePass(builder, true);
1190         }
1191         (llvm::CodeGenOptLevel::Default, ..) => {
1192             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
1193         }
1194         (llvm::CodeGenOptLevel::Other, ..) => {
1195             bug!("CodeGenOptLevel::Other selected")
1196         }
1197     }
1198
1199     f(builder);
1200     llvm::LLVMPassManagerBuilderDispose(builder);
1201 }