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