2014-08-11 17:33:58 +00:00
|
|
|
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
use back::lto;
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
use back::link::{get_cc_prog, remove};
|
|
|
|
use driver::driver::{CrateTranslation, ModuleTranslation, OutputFilenames};
|
2014-09-11 05:07:49 +00:00
|
|
|
use driver::config::{NoDebugInfo, Passes, SomePasses, AllPasses};
|
2014-08-11 17:33:58 +00:00
|
|
|
use driver::session::Session;
|
|
|
|
use driver::config;
|
|
|
|
use llvm;
|
2014-09-12 15:17:58 +00:00
|
|
|
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
|
2014-09-27 08:33:36 +00:00
|
|
|
use llvm::SMDiagnosticRef;
|
2014-08-11 17:33:58 +00:00
|
|
|
use util::common::time;
|
|
|
|
use syntax::abi;
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
use syntax::codemap;
|
|
|
|
use syntax::diagnostic;
|
|
|
|
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
|
2014-08-11 17:33:58 +00:00
|
|
|
|
|
|
|
use std::c_str::{ToCStr, CString};
|
|
|
|
use std::io::Command;
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
use std::io::fs;
|
|
|
|
use std::iter::Unfold;
|
2014-08-11 17:33:58 +00:00
|
|
|
use std::ptr;
|
|
|
|
use std::str;
|
2014-09-12 15:17:58 +00:00
|
|
|
use std::mem;
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use std::task::TaskBuilder;
|
2014-09-12 15:17:58 +00:00
|
|
|
use libc::{c_uint, c_int, c_void};
|
2014-08-11 17:33:58 +00:00
|
|
|
|
|
|
|
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
|
|
|
|
pub enum OutputType {
|
|
|
|
OutputTypeBitcode,
|
|
|
|
OutputTypeAssembly,
|
|
|
|
OutputTypeLlvmAssembly,
|
|
|
|
OutputTypeObject,
|
|
|
|
OutputTypeExe,
|
|
|
|
}
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
|
2014-08-11 17:33:58 +00:00
|
|
|
unsafe {
|
|
|
|
let cstr = llvm::LLVMRustGetLastError();
|
|
|
|
if cstr == ptr::null() {
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
handler.fatal(msg.as_slice());
|
2014-08-11 17:33:58 +00:00
|
|
|
} else {
|
|
|
|
let err = CString::new(cstr, true);
|
|
|
|
let err = String::from_utf8_lossy(err.as_bytes());
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
handler.fatal(format!("{}: {}",
|
|
|
|
msg.as_slice(),
|
|
|
|
err.as_slice()).as_slice());
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write_output_file(
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
handler: &diagnostic::Handler,
|
2014-08-11 17:33:58 +00:00
|
|
|
target: llvm::TargetMachineRef,
|
|
|
|
pm: llvm::PassManagerRef,
|
|
|
|
m: ModuleRef,
|
|
|
|
output: &Path,
|
|
|
|
file_type: llvm::FileType) {
|
|
|
|
unsafe {
|
|
|
|
output.with_c_str(|output| {
|
|
|
|
let result = llvm::LLVMRustWriteOutputFile(
|
|
|
|
target, pm, m, output, file_type);
|
|
|
|
if !result {
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
llvm_err(handler, "could not write output".to_string());
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
struct Diagnostic {
|
|
|
|
msg: String,
|
|
|
|
code: Option<String>,
|
|
|
|
lvl: Level,
|
|
|
|
}
|
|
|
|
|
|
|
|
// We use an Arc instead of just returning a list of diagnostics from the
|
|
|
|
// child task because we need to make sure that the messages are seen even
|
2014-10-09 19:17:22 +00:00
|
|
|
// if the child task panics (for example, when `fatal` is called).
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
#[deriving(Clone)]
|
|
|
|
struct SharedEmitter {
|
|
|
|
buffer: Arc<Mutex<Vec<Diagnostic>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SharedEmitter {
|
|
|
|
fn new() -> SharedEmitter {
|
|
|
|
SharedEmitter {
|
|
|
|
buffer: Arc::new(Mutex::new(Vec::new())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn dump(&mut self, handler: &Handler) {
|
|
|
|
let mut buffer = self.buffer.lock();
|
|
|
|
for diag in buffer.iter() {
|
|
|
|
match diag.code {
|
|
|
|
Some(ref code) => {
|
|
|
|
handler.emit_with_code(None,
|
|
|
|
diag.msg.as_slice(),
|
|
|
|
code.as_slice(),
|
|
|
|
diag.lvl);
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
handler.emit(None,
|
|
|
|
diag.msg.as_slice(),
|
|
|
|
diag.lvl);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buffer.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Emitter for SharedEmitter {
|
|
|
|
fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, codemap::Span)>,
|
|
|
|
msg: &str, code: Option<&str>, lvl: Level) {
|
|
|
|
assert!(cmsp.is_none(), "SharedEmitter doesn't support spans");
|
|
|
|
|
|
|
|
self.buffer.lock().push(Diagnostic {
|
|
|
|
msg: msg.to_string(),
|
|
|
|
code: code.map(|s| s.to_string()),
|
|
|
|
lvl: lvl,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn custom_emit(&mut self, _cm: &codemap::CodeMap,
|
|
|
|
_sp: diagnostic::RenderSpan, _msg: &str, _lvl: Level) {
|
2014-10-09 19:17:22 +00:00
|
|
|
panic!("SharedEmitter doesn't support custom_emit");
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-11 17:33:58 +00:00
|
|
|
// On android, we by default compile for armv7 processors. This enables
|
|
|
|
// things like double word CAS instructions (rather than emulating them)
|
|
|
|
// which are *far* more efficient. This is obviously undesirable in some
|
|
|
|
// cases, so if any sort of target feature is specified we don't append v7
|
|
|
|
// to the feature list.
|
|
|
|
//
|
|
|
|
// On iOS only armv7 and newer are supported. So it is useful to
|
|
|
|
// get all hardware potential via VFP3 (hardware floating point)
|
|
|
|
// and NEON (SIMD) instructions supported by LLVM.
|
|
|
|
// Note that without those flags various linking errors might
|
|
|
|
// arise as some of intrinsics are converted into function calls
|
|
|
|
// and nobody provides implementations those functions
|
|
|
|
fn target_feature<'a>(sess: &'a Session) -> &'a str {
|
|
|
|
match sess.targ_cfg.os {
|
|
|
|
abi::OsAndroid => {
|
|
|
|
if "" == sess.opts.cg.target_feature.as_slice() {
|
|
|
|
"+v7"
|
|
|
|
} else {
|
|
|
|
sess.opts.cg.target_feature.as_slice()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
abi::OsiOS if sess.targ_cfg.arch == abi::Arm => {
|
|
|
|
"+v7,+thumb2,+vfp3,+neon"
|
|
|
|
},
|
|
|
|
_ => sess.opts.cg.target_feature.as_slice()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
|
|
|
|
match optimize {
|
|
|
|
config::No => llvm::CodeGenLevelNone,
|
|
|
|
config::Less => llvm::CodeGenLevelLess,
|
|
|
|
config::Default => llvm::CodeGenLevelDefault,
|
|
|
|
config::Aggressive => llvm::CodeGenLevelAggressive,
|
|
|
|
}
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
fn create_target_machine(sess: &Session) -> TargetMachineRef {
|
|
|
|
let reloc_model = match sess.opts.cg.relocation_model.as_slice() {
|
|
|
|
"pic" => llvm::RelocPIC,
|
|
|
|
"static" => llvm::RelocStatic,
|
|
|
|
"default" => llvm::RelocDefault,
|
|
|
|
"dynamic-no-pic" => llvm::RelocDynamicNoPic,
|
|
|
|
_ => {
|
|
|
|
sess.err(format!("{} is not a valid relocation mode",
|
|
|
|
sess.opts
|
|
|
|
.cg
|
|
|
|
.relocation_model).as_slice());
|
|
|
|
sess.abort_if_errors();
|
|
|
|
unreachable!();
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
};
|
2014-08-11 17:33:58 +00:00
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
let opt_level = get_llvm_opt_level(sess.opts.optimize);
|
|
|
|
let use_softfp = sess.opts.cg.soft_float;
|
|
|
|
|
|
|
|
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
|
|
|
|
// FIXME: #11954: mac64 unwinding may not work with fp elim
|
|
|
|
let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
|
|
|
|
(sess.targ_cfg.os == abi::OsMacos &&
|
|
|
|
sess.targ_cfg.arch == abi::X86_64);
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2014-08-09 16:43:45 +00:00
|
|
|
let any_library = sess.crate_types.borrow().iter().any(|ty| {
|
|
|
|
*ty != config::CrateTypeExecutable
|
|
|
|
});
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
// OSX has -dead_strip, which doesn't rely on ffunction_sections
|
|
|
|
// FIXME(#13846) this should be enabled for windows
|
|
|
|
let ffunction_sections = sess.targ_cfg.os != abi::OsMacos &&
|
|
|
|
sess.targ_cfg.os != abi::OsWindows;
|
|
|
|
let fdata_sections = ffunction_sections;
|
|
|
|
|
|
|
|
let code_model = match sess.opts.cg.code_model.as_slice() {
|
|
|
|
"default" => llvm::CodeModelDefault,
|
|
|
|
"small" => llvm::CodeModelSmall,
|
|
|
|
"kernel" => llvm::CodeModelKernel,
|
|
|
|
"medium" => llvm::CodeModelMedium,
|
|
|
|
"large" => llvm::CodeModelLarge,
|
|
|
|
_ => {
|
|
|
|
sess.err(format!("{} is not a valid code model",
|
|
|
|
sess.opts
|
|
|
|
.cg
|
|
|
|
.code_model).as_slice());
|
|
|
|
sess.abort_if_errors();
|
|
|
|
unreachable!();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-10-29 01:58:46 +00:00
|
|
|
let triple = sess.targ_cfg.target_strs.target_triple.as_slice();
|
|
|
|
|
|
|
|
let tm = unsafe {
|
|
|
|
triple.with_c_str(|t| {
|
2014-08-11 17:33:58 +00:00
|
|
|
sess.opts.cg.target_cpu.as_slice().with_c_str(|cpu| {
|
|
|
|
target_feature(sess).with_c_str(|features| {
|
|
|
|
llvm::LLVMRustCreateTargetMachine(
|
|
|
|
t, cpu, features,
|
|
|
|
code_model,
|
|
|
|
reloc_model,
|
|
|
|
opt_level,
|
|
|
|
true /* EnableSegstk */,
|
|
|
|
use_softfp,
|
|
|
|
no_fp_elim,
|
2014-08-09 16:43:45 +00:00
|
|
|
!any_library && reloc_model == llvm::RelocPIC,
|
2014-08-11 17:33:58 +00:00
|
|
|
ffunction_sections,
|
|
|
|
fdata_sections,
|
|
|
|
)
|
|
|
|
})
|
|
|
|
})
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
})
|
2014-10-29 01:58:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if tm.is_null() {
|
|
|
|
llvm_err(sess.diagnostic().handler(),
|
|
|
|
format!("Could not create LLVM TargetMachine for triple: {}",
|
|
|
|
triple).to_string());
|
|
|
|
} else {
|
|
|
|
return tm;
|
|
|
|
};
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Module-specific configuration for `optimize_and_codegen`.
|
|
|
|
#[deriving(Clone)]
|
|
|
|
struct ModuleConfig {
|
|
|
|
/// LLVM TargetMachine to use for codegen.
|
|
|
|
tm: TargetMachineRef,
|
|
|
|
/// Names of additional optimization passes to run.
|
|
|
|
passes: Vec<String>,
|
|
|
|
/// Some(level) to optimize at a certain level, or None to run
|
|
|
|
/// absolutely no optimizations (used for the metadata module).
|
|
|
|
opt_level: Option<llvm::CodeGenOptLevel>,
|
2014-08-11 17:33:58 +00:00
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
// Flags indicating which outputs to produce.
|
|
|
|
emit_no_opt_bc: bool,
|
|
|
|
emit_bc: bool,
|
|
|
|
emit_lto_bc: bool,
|
|
|
|
emit_ir: bool,
|
|
|
|
emit_asm: bool,
|
|
|
|
emit_obj: bool,
|
|
|
|
|
|
|
|
// Miscellaneous flags. These are mostly copied from command-line
|
|
|
|
// options.
|
|
|
|
no_verify: bool,
|
|
|
|
no_prepopulate_passes: bool,
|
|
|
|
no_builtins: bool,
|
|
|
|
time_passes: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ModuleConfig {
|
|
|
|
fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig {
|
|
|
|
ModuleConfig {
|
|
|
|
tm: tm,
|
|
|
|
passes: passes,
|
|
|
|
opt_level: None,
|
|
|
|
|
|
|
|
emit_no_opt_bc: false,
|
|
|
|
emit_bc: false,
|
|
|
|
emit_lto_bc: false,
|
|
|
|
emit_ir: false,
|
|
|
|
emit_asm: false,
|
|
|
|
emit_obj: false,
|
|
|
|
|
|
|
|
no_verify: false,
|
|
|
|
no_prepopulate_passes: false,
|
|
|
|
no_builtins: false,
|
|
|
|
time_passes: false,
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
fn set_flags(&mut self, sess: &Session, trans: &CrateTranslation) {
|
|
|
|
self.no_verify = sess.no_verify();
|
|
|
|
self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
|
|
|
|
self.no_builtins = trans.no_builtins;
|
|
|
|
self.time_passes = sess.time_passes();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Additional resources used by optimize_and_codegen (not module specific)
|
|
|
|
struct CodegenContext<'a> {
|
|
|
|
// Extra resources used for LTO: (sess, reachable). This will be `None`
|
|
|
|
// when running in a worker thread.
|
|
|
|
lto_ctxt: Option<(&'a Session, &'a [String])>,
|
|
|
|
// Handler to use for diagnostics produced during codegen.
|
|
|
|
handler: &'a Handler,
|
2014-09-12 15:17:58 +00:00
|
|
|
// LLVM optimizations for which we want to print remarks.
|
|
|
|
remark: Passes,
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> CodegenContext<'a> {
|
|
|
|
fn new_with_session(sess: &'a Session, reachable: &'a [String]) -> CodegenContext<'a> {
|
|
|
|
CodegenContext {
|
|
|
|
lto_ctxt: Some((sess, reachable)),
|
|
|
|
handler: sess.diagnostic().handler(),
|
2014-09-12 15:17:58 +00:00
|
|
|
remark: sess.opts.cg.remark.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-27 08:33:36 +00:00
|
|
|
struct HandlerFreeVars<'a> {
|
2014-09-12 15:17:58 +00:00
|
|
|
llcx: ContextRef,
|
|
|
|
cgcx: &'a CodegenContext<'a>,
|
|
|
|
}
|
|
|
|
|
2014-09-27 08:33:36 +00:00
|
|
|
unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
|
|
|
|
user: *const c_void,
|
|
|
|
cookie: c_uint) {
|
|
|
|
use syntax::codemap::ExpnId;
|
|
|
|
|
|
|
|
let HandlerFreeVars { cgcx, .. }
|
|
|
|
= *mem::transmute::<_, *const HandlerFreeVars>(user);
|
|
|
|
|
|
|
|
let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
|
|
|
|
.expect("non-UTF8 SMDiagnostic");
|
|
|
|
|
|
|
|
match cgcx.lto_ctxt {
|
|
|
|
Some((sess, _)) => {
|
2014-09-28 16:25:48 +00:00
|
|
|
sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info {
|
2014-09-27 08:33:36 +00:00
|
|
|
Some(ei) => sess.span_err(ei.call_site, msg.as_slice()),
|
|
|
|
None => sess.err(msg.as_slice()),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
None => {
|
|
|
|
cgcx.handler.err(msg.as_slice());
|
|
|
|
cgcx.handler.note("build without -C codegen-units for more exact errors");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-12 15:17:58 +00:00
|
|
|
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
|
2014-09-27 08:33:36 +00:00
|
|
|
let HandlerFreeVars { llcx, cgcx }
|
|
|
|
= *mem::transmute::<_, *const HandlerFreeVars>(user);
|
2014-09-12 15:17:58 +00:00
|
|
|
|
|
|
|
match llvm::diagnostic::Diagnostic::unpack(info) {
|
|
|
|
llvm::diagnostic::Optimization(opt) => {
|
|
|
|
let pass_name = CString::new(opt.pass_name, false);
|
|
|
|
let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
|
|
|
|
let enabled = match cgcx.remark {
|
|
|
|
AllPasses => true,
|
2014-09-11 05:07:49 +00:00
|
|
|
SomePasses(ref v) => v.iter().any(|s| s.as_slice() == pass_name),
|
2014-09-12 15:17:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if enabled {
|
|
|
|
let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
|
|
|
|
cgcx.handler.note(format!("optimization {:s} for {:s} at {:s}: {:s}",
|
|
|
|
opt.kind.describe(),
|
|
|
|
pass_name,
|
|
|
|
if loc.is_empty() { "[unknown]" } else { loc.as_slice() },
|
|
|
|
llvm::twine_to_string(opt.message)).as_slice());
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
2014-09-12 15:17:58 +00:00
|
|
|
|
|
|
|
_ => (),
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unsafe due to LLVM calls.
|
|
|
|
unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
|
|
|
mtrans: ModuleTranslation,
|
|
|
|
config: ModuleConfig,
|
|
|
|
name_extra: String,
|
|
|
|
output_names: OutputFilenames) {
|
|
|
|
let ModuleTranslation { llmod, llcx } = mtrans;
|
|
|
|
let tm = config.tm;
|
|
|
|
|
2014-09-12 15:17:58 +00:00
|
|
|
// llcx doesn't outlive this function, so we can put this on the stack.
|
2014-09-27 08:33:36 +00:00
|
|
|
let fv = HandlerFreeVars {
|
2014-09-12 15:17:58 +00:00
|
|
|
llcx: llcx,
|
|
|
|
cgcx: cgcx,
|
|
|
|
};
|
2014-09-27 08:33:36 +00:00
|
|
|
let fv = &fv as *const HandlerFreeVars as *mut c_void;
|
|
|
|
|
|
|
|
llvm::LLVMSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
|
|
|
|
|
2014-09-12 15:17:58 +00:00
|
|
|
if !cgcx.remark.is_empty() {
|
2014-09-27 08:33:36 +00:00
|
|
|
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
|
2014-09-12 15:17:58 +00:00
|
|
|
}
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
if config.emit_no_opt_bc {
|
|
|
|
let ext = format!("{}.no-opt.bc", name_extra);
|
|
|
|
output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
|
|
|
|
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
match config.opt_level {
|
|
|
|
Some(opt_level) => {
|
|
|
|
// Create the two optimizing pass managers. These mirror what clang
|
|
|
|
// does, and are by populated by LLVM's default PassManagerBuilder.
|
|
|
|
// Each manager has a different set of passes, but they also share
|
|
|
|
// some common passes.
|
|
|
|
let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
|
|
|
|
let mpm = llvm::LLVMCreatePassManager();
|
|
|
|
|
|
|
|
// If we're verifying or linting, add them to the function pass
|
|
|
|
// manager.
|
|
|
|
let addpass = |pass: &str| {
|
|
|
|
pass.as_slice().with_c_str(|s| llvm::LLVMRustAddPass(fpm, s))
|
|
|
|
};
|
|
|
|
if !config.no_verify { assert!(addpass("verify")); }
|
2014-08-11 17:33:58 +00:00
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
if !config.no_prepopulate_passes {
|
|
|
|
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
|
|
|
|
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
|
|
|
|
populate_llvm_passes(fpm, mpm, llmod, opt_level,
|
|
|
|
config.no_builtins);
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
for pass in config.passes.iter() {
|
|
|
|
pass.as_slice().with_c_str(|s| {
|
|
|
|
if !llvm::LLVMRustAddPass(mpm, s) {
|
|
|
|
cgcx.handler.warn(format!("unknown pass {}, ignoring",
|
|
|
|
*pass).as_slice());
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
// Finally, run the actual optimization passes
|
|
|
|
time(config.time_passes, "llvm function passes", (), |()|
|
|
|
|
llvm::LLVMRustRunFunctionPassManager(fpm, llmod));
|
|
|
|
time(config.time_passes, "llvm module passes", (), |()|
|
|
|
|
llvm::LLVMRunPassManager(mpm, llmod));
|
|
|
|
|
|
|
|
// Deallocate managers that we're now done with
|
|
|
|
llvm::LLVMDisposePassManager(fpm);
|
|
|
|
llvm::LLVMDisposePassManager(mpm);
|
|
|
|
|
|
|
|
match cgcx.lto_ctxt {
|
|
|
|
Some((sess, reachable)) if sess.lto() => {
|
|
|
|
time(sess.time_passes(), "all lto passes", (), |()|
|
|
|
|
lto::run(sess, llmod, tm, reachable));
|
|
|
|
|
|
|
|
if config.emit_lto_bc {
|
|
|
|
let name = format!("{}.lto.bc", name_extra);
|
|
|
|
output_names.with_extension(name.as_slice()).with_c_str(|buf| {
|
|
|
|
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => {},
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
},
|
|
|
|
None => {},
|
|
|
|
}
|
|
|
|
|
|
|
|
// A codegen-specific pass manager is used to generate object
|
|
|
|
// files for an LLVM module.
|
|
|
|
//
|
|
|
|
// Apparently each of these pass managers is a one-shot kind of
|
|
|
|
// thing, so we create a new one for each type of output. The
|
|
|
|
// pass manager passed to the closure should be ensured to not
|
|
|
|
// escape the closure itself, and the manager should only be
|
|
|
|
// used once.
|
|
|
|
unsafe fn with_codegen(tm: TargetMachineRef, llmod: ModuleRef,
|
|
|
|
no_builtins: bool, f: |PassManagerRef|) {
|
|
|
|
let cpm = llvm::LLVMCreatePassManager();
|
|
|
|
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
|
|
|
|
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
|
|
|
f(cpm);
|
|
|
|
llvm::LLVMDisposePassManager(cpm);
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.emit_bc {
|
|
|
|
let ext = format!("{}.bc", name_extra);
|
|
|
|
output_names.with_extension(ext.as_slice()).with_c_str(|buf| {
|
|
|
|
llvm::LLVMWriteBitcodeToFile(llmod, buf);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
time(config.time_passes, "codegen passes", (), |()| {
|
|
|
|
if config.emit_ir {
|
|
|
|
let ext = format!("{}.ll", name_extra);
|
|
|
|
output_names.with_extension(ext.as_slice()).with_c_str(|output| {
|
|
|
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
|
|
|
llvm::LLVMRustPrintModule(cpm, llmod, output);
|
|
|
|
})
|
|
|
|
})
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
if config.emit_asm {
|
|
|
|
let path = output_names.with_extension(format!("{}.s", name_extra).as_slice());
|
|
|
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
2014-09-11 05:07:49 +00:00
|
|
|
write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.emit_obj {
|
|
|
|
let path = output_names.with_extension(format!("{}.o", name_extra).as_slice());
|
|
|
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
2014-09-11 05:07:49 +00:00
|
|
|
write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::ObjectFileType);
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
llvm::LLVMDisposeModule(llmod);
|
|
|
|
llvm::LLVMContextDispose(llcx);
|
|
|
|
llvm::LLVMRustDisposeTargetMachine(tm);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run_passes(sess: &Session,
|
|
|
|
trans: &CrateTranslation,
|
|
|
|
output_types: &[OutputType],
|
|
|
|
crate_output: &OutputFilenames) {
|
|
|
|
// It's possible that we have `codegen_units > 1` but only one item in
|
|
|
|
// `trans.modules`. We could theoretically proceed and do LTO in that
|
|
|
|
// case, but it would be confusing to have the validity of
|
|
|
|
// `-Z lto -C codegen-units=2` depend on details of the crate being
|
|
|
|
// compiled, so we complain regardless.
|
|
|
|
if sess.lto() && sess.opts.cg.codegen_units > 1 {
|
|
|
|
// This case is impossible to handle because LTO expects to be able
|
|
|
|
// to combine the entire crate and all its dependencies into a
|
|
|
|
// single compilation unit, but each codegen unit is in a separate
|
|
|
|
// LLVM context, so they can't easily be combined.
|
|
|
|
sess.fatal("can't perform LTO when using multiple codegen units");
|
|
|
|
}
|
|
|
|
|
2014-09-05 21:30:36 +00:00
|
|
|
// Sanity check
|
|
|
|
assert!(trans.modules.len() == sess.opts.cg.codegen_units);
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
unsafe {
|
|
|
|
configure_llvm(sess);
|
|
|
|
}
|
|
|
|
|
|
|
|
let tm = create_target_machine(sess);
|
|
|
|
|
|
|
|
// Figure out what we actually need to build.
|
|
|
|
|
|
|
|
let mut modules_config = ModuleConfig::new(tm, sess.opts.cg.passes.clone());
|
|
|
|
let mut metadata_config = ModuleConfig::new(tm, vec!());
|
|
|
|
|
|
|
|
modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize));
|
|
|
|
|
|
|
|
// Save all versions of the bytecode if we're saving our temporaries.
|
|
|
|
if sess.opts.cg.save_temps {
|
|
|
|
modules_config.emit_no_opt_bc = true;
|
|
|
|
modules_config.emit_bc = true;
|
|
|
|
modules_config.emit_lto_bc = true;
|
|
|
|
metadata_config.emit_bc = true;
|
|
|
|
}
|
|
|
|
|
2014-09-17 23:18:12 +00:00
|
|
|
// Emit bitcode files for the crate if we're emitting an rlib.
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
// Whenever an rlib is created, the bitcode is inserted into the
|
|
|
|
// archive in order to allow LTO against it.
|
|
|
|
let needs_crate_bitcode =
|
|
|
|
sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
|
2014-09-17 23:18:12 +00:00
|
|
|
sess.opts.output_types.contains(&OutputTypeExe);
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
if needs_crate_bitcode {
|
|
|
|
modules_config.emit_bc = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for output_type in output_types.iter() {
|
|
|
|
match *output_type {
|
|
|
|
OutputTypeBitcode => { modules_config.emit_bc = true; },
|
|
|
|
OutputTypeLlvmAssembly => { modules_config.emit_ir = true; },
|
|
|
|
OutputTypeAssembly => {
|
|
|
|
modules_config.emit_asm = true;
|
|
|
|
// If we're not using the LLVM assembler, this function
|
|
|
|
// could be invoked specially with output_type_assembly, so
|
|
|
|
// in this case we still want the metadata object file.
|
|
|
|
if !sess.opts.output_types.contains(&OutputTypeAssembly) {
|
|
|
|
metadata_config.emit_obj = true;
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
},
|
|
|
|
OutputTypeObject => { modules_config.emit_obj = true; },
|
|
|
|
OutputTypeExe => {
|
|
|
|
modules_config.emit_obj = true;
|
|
|
|
metadata_config.emit_obj = true;
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
modules_config.set_flags(sess, trans);
|
|
|
|
metadata_config.set_flags(sess, trans);
|
|
|
|
|
|
|
|
|
|
|
|
// Populate a buffer with a list of codegen tasks. Items are processed in
|
|
|
|
// LIFO order, just because it's a tiny bit simpler that way. (The order
|
|
|
|
// doesn't actually matter.)
|
|
|
|
let mut work_items = Vec::with_capacity(1 + trans.modules.len());
|
|
|
|
|
|
|
|
{
|
|
|
|
let work = build_work_item(sess,
|
|
|
|
trans.metadata_module,
|
|
|
|
metadata_config.clone(),
|
|
|
|
crate_output.clone(),
|
|
|
|
"metadata".to_string());
|
|
|
|
work_items.push(work);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (index, mtrans) in trans.modules.iter().enumerate() {
|
|
|
|
let work = build_work_item(sess,
|
|
|
|
*mtrans,
|
|
|
|
modules_config.clone(),
|
|
|
|
crate_output.clone(),
|
|
|
|
format!("{}", index));
|
|
|
|
work_items.push(work);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process the work items, optionally using worker threads.
|
|
|
|
if sess.opts.cg.codegen_units == 1 {
|
|
|
|
run_work_singlethreaded(sess, trans.reachable.as_slice(), work_items);
|
|
|
|
} else {
|
|
|
|
run_work_multithreaded(sess, work_items, sess.opts.cg.codegen_units);
|
|
|
|
}
|
|
|
|
|
|
|
|
// All codegen is finished.
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDisposeTargetMachine(tm);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Produce final compile outputs.
|
|
|
|
|
2014-09-17 23:18:12 +00:00
|
|
|
let copy_if_one_unit = |ext: &str, output_type: OutputType, keep_numbered: bool| {
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
// Three cases:
|
|
|
|
if sess.opts.cg.codegen_units == 1 {
|
|
|
|
// 1) Only one codegen unit. In this case it's no difficulty
|
|
|
|
// to copy `foo.0.x` to `foo.x`.
|
|
|
|
fs::copy(&crate_output.with_extension(ext),
|
|
|
|
&crate_output.path(output_type)).unwrap();
|
2014-09-17 23:18:12 +00:00
|
|
|
if !sess.opts.cg.save_temps && !keep_numbered {
|
2014-08-27 21:49:17 +00:00
|
|
|
// The user just wants `foo.x`, not `foo.0.x`.
|
|
|
|
remove(sess, &crate_output.with_extension(ext));
|
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
} else {
|
|
|
|
if crate_output.single_output_file.is_some() {
|
|
|
|
// 2) Multiple codegen units, with `-o some_name`. We have
|
|
|
|
// no good solution for this case, so warn the user.
|
2014-08-27 21:49:17 +00:00
|
|
|
sess.warn(format!("ignoring -o because multiple .{} files were produced",
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
ext).as_slice());
|
|
|
|
} else {
|
|
|
|
// 3) Multiple codegen units, but no `-o some_name`. We
|
|
|
|
// just leave the `foo.0.x` files in place.
|
|
|
|
// (We don't have to do any work in this case.)
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let link_obj = |output_path: &Path| {
|
2014-09-05 21:30:36 +00:00
|
|
|
// Running `ld -r` on a single input is kind of pointless.
|
|
|
|
if sess.opts.cg.codegen_units == 1 {
|
|
|
|
fs::copy(&crate_output.with_extension("0.o"),
|
|
|
|
output_path).unwrap();
|
|
|
|
// Leave the .0.o file around, to mimic the behavior of the normal
|
|
|
|
// code path.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-08-29 19:46:04 +00:00
|
|
|
// Some builds of MinGW GCC will pass --force-exe-suffix to ld, which
|
|
|
|
// will automatically add a .exe extension if the extension is not
|
|
|
|
// already .exe or .dll. To ensure consistent behavior on Windows, we
|
|
|
|
// add the .exe suffix explicitly and then rename the output file to
|
|
|
|
// the desired path. This will give the correct behavior whether or
|
|
|
|
// not GCC adds --force-exe-suffix.
|
|
|
|
let windows_output_path =
|
|
|
|
if sess.targ_cfg.os == abi::OsWindows {
|
|
|
|
Some(output_path.with_extension("o.exe"))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2014-08-26 22:53:56 +00:00
|
|
|
let pname = get_cc_prog(sess);
|
|
|
|
let mut cmd = Command::new(pname.as_slice());
|
|
|
|
|
|
|
|
cmd.args(sess.targ_cfg.target_strs.cc_args.as_slice());
|
|
|
|
cmd.arg("-nostdlib");
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
|
|
|
|
for index in range(0, trans.modules.len()) {
|
|
|
|
cmd.arg(crate_output.with_extension(format!("{}.o", index).as_slice()));
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2014-08-29 19:46:04 +00:00
|
|
|
cmd.arg("-r")
|
|
|
|
.arg("-o")
|
|
|
|
.arg(windows_output_path.as_ref().unwrap_or(output_path));
|
2014-08-26 22:53:56 +00:00
|
|
|
|
|
|
|
if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
|
|
|
|
println!("{}", &cmd);
|
|
|
|
}
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
cmd.stdin(::std::io::process::Ignored)
|
|
|
|
.stdout(::std::io::process::InheritFd(1))
|
|
|
|
.stderr(::std::io::process::InheritFd(2));
|
2014-08-26 22:53:56 +00:00
|
|
|
match cmd.status() {
|
2014-10-22 20:23:22 +00:00
|
|
|
Ok(status) => {
|
|
|
|
if !status.success() {
|
|
|
|
sess.err(format!("linking of {} with `{}` failed",
|
|
|
|
output_path.display(), cmd).as_slice());
|
|
|
|
sess.abort_if_errors();
|
|
|
|
}
|
|
|
|
},
|
2014-08-26 22:53:56 +00:00
|
|
|
Err(e) => {
|
|
|
|
sess.err(format!("could not exec the linker `{}`: {}",
|
|
|
|
pname,
|
|
|
|
e).as_slice());
|
|
|
|
sess.abort_if_errors();
|
|
|
|
},
|
|
|
|
}
|
2014-08-29 19:46:04 +00:00
|
|
|
|
|
|
|
match windows_output_path {
|
|
|
|
Some(ref windows_path) => {
|
|
|
|
fs::rename(windows_path, output_path).unwrap();
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
// The file is already named according to `output_path`.
|
|
|
|
}
|
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Flag to indicate whether the user explicitly requested bitcode.
|
|
|
|
// Otherwise, we produced it only as a temporary output, and will need
|
|
|
|
// to get rid of it.
|
2014-09-17 23:18:12 +00:00
|
|
|
let mut user_wants_bitcode = false;
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
for output_type in output_types.iter() {
|
|
|
|
match *output_type {
|
|
|
|
OutputTypeBitcode => {
|
2014-09-17 23:18:12 +00:00
|
|
|
user_wants_bitcode = true;
|
|
|
|
// Copy to .bc, but always keep the .0.bc. There is a later
|
|
|
|
// check to figure out if we should delete .0.bc files, or keep
|
|
|
|
// them for making an rlib.
|
|
|
|
copy_if_one_unit("0.bc", OutputTypeBitcode, true);
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
},
|
2014-09-17 23:18:12 +00:00
|
|
|
OutputTypeLlvmAssembly => { copy_if_one_unit("0.ll", OutputTypeLlvmAssembly, false); },
|
|
|
|
OutputTypeAssembly => { copy_if_one_unit("0.s", OutputTypeAssembly, false); },
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
OutputTypeObject => { link_obj(&crate_output.path(OutputTypeObject)); },
|
|
|
|
OutputTypeExe => {
|
|
|
|
// If OutputTypeObject is already in the list, then
|
|
|
|
// `crate.o` will be handled by the OutputTypeObject case.
|
|
|
|
// Otherwise, we need to create the temporary object so we
|
|
|
|
// can run the linker.
|
|
|
|
if !sess.opts.output_types.contains(&OutputTypeObject) {
|
|
|
|
link_obj(&crate_output.temp_path(OutputTypeObject));
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2014-09-17 23:18:12 +00:00
|
|
|
let user_wants_bitcode = user_wants_bitcode;
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
|
|
|
|
// Clean up unwanted temporary files.
|
|
|
|
|
|
|
|
// We create the following files by default:
|
|
|
|
// - crate.0.bc
|
|
|
|
// - crate.0.o
|
|
|
|
// - crate.metadata.bc
|
|
|
|
// - crate.metadata.o
|
|
|
|
// - crate.o (linked from crate.##.o)
|
2014-08-27 21:49:17 +00:00
|
|
|
// - crate.bc (copied from crate.0.bc)
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
// We may create additional files if requested by the user (through
|
|
|
|
// `-C save-temps` or `--emit=` flags).
|
|
|
|
|
|
|
|
if !sess.opts.cg.save_temps {
|
|
|
|
// Remove the temporary .0.o objects. If the user didn't
|
2014-09-17 23:18:12 +00:00
|
|
|
// explicitly request bitcode (with --emit=bc), and the bitcode is not
|
|
|
|
// needed for building an rlib, then we must remove .0.bc as well.
|
|
|
|
|
|
|
|
// Specific rules for keeping .0.bc:
|
|
|
|
// - If we're building an rlib (`needs_crate_bitcode`), then keep
|
|
|
|
// it.
|
|
|
|
// - If the user requested bitcode (`user_wants_bitcode`), and
|
|
|
|
// codegen_units > 1, then keep it.
|
|
|
|
// - If the user requested bitcode but codegen_units == 1, then we
|
|
|
|
// can toss .0.bc because we copied it to .bc earlier.
|
|
|
|
// - If we're not building an rlib and the user didn't request
|
|
|
|
// bitcode, then delete .0.bc.
|
|
|
|
// If you change how this works, also update back::link::link_rlib,
|
|
|
|
// where .0.bc files are (maybe) deleted after making an rlib.
|
|
|
|
let keep_numbered_bitcode = needs_crate_bitcode ||
|
|
|
|
(user_wants_bitcode && sess.opts.cg.codegen_units > 1);
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
for i in range(0, trans.modules.len()) {
|
|
|
|
if modules_config.emit_obj {
|
|
|
|
let ext = format!("{}.o", i);
|
|
|
|
remove(sess, &crate_output.with_extension(ext.as_slice()));
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
|
2014-09-17 23:18:12 +00:00
|
|
|
if modules_config.emit_bc && !keep_numbered_bitcode {
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
let ext = format!("{}.bc", i);
|
|
|
|
remove(sess, &crate_output.with_extension(ext.as_slice()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-17 23:18:12 +00:00
|
|
|
if metadata_config.emit_bc && !user_wants_bitcode {
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
remove(sess, &crate_output.with_extension("metadata.bc"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We leave the following files around by default:
|
|
|
|
// - crate.o
|
|
|
|
// - crate.metadata.o
|
|
|
|
// - crate.bc
|
|
|
|
// These are used in linking steps and will be cleaned up afterward.
|
|
|
|
|
|
|
|
// FIXME: time_llvm_passes support - does this use a global context or
|
|
|
|
// something?
|
|
|
|
//if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
|
|
|
|
}
|
|
|
|
|
|
|
|
type WorkItem = proc(&CodegenContext):Send;
|
|
|
|
|
|
|
|
fn build_work_item(sess: &Session,
|
|
|
|
mtrans: ModuleTranslation,
|
|
|
|
config: ModuleConfig,
|
|
|
|
output_names: OutputFilenames,
|
|
|
|
name_extra: String) -> WorkItem {
|
|
|
|
let mut config = config;
|
|
|
|
config.tm = create_target_machine(sess);
|
|
|
|
|
|
|
|
proc(cgcx) unsafe {
|
|
|
|
optimize_and_codegen(cgcx, mtrans, config, name_extra, output_names);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run_work_singlethreaded(sess: &Session,
|
|
|
|
reachable: &[String],
|
|
|
|
work_items: Vec<WorkItem>) {
|
|
|
|
let cgcx = CodegenContext::new_with_session(sess, reachable);
|
|
|
|
let mut work_items = work_items;
|
|
|
|
|
|
|
|
// Since we're running single-threaded, we can pass the session to
|
|
|
|
// the proc, allowing `optimize_and_codegen` to perform LTO.
|
|
|
|
for work in Unfold::new((), |_| work_items.pop()) {
|
|
|
|
work(&cgcx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn run_work_multithreaded(sess: &Session,
|
|
|
|
work_items: Vec<WorkItem>,
|
|
|
|
num_workers: uint) {
|
|
|
|
// Run some workers to process the work items.
|
|
|
|
let work_items_arc = Arc::new(Mutex::new(work_items));
|
|
|
|
let mut diag_emitter = SharedEmitter::new();
|
|
|
|
let mut futures = Vec::with_capacity(num_workers);
|
|
|
|
|
|
|
|
for i in range(0, num_workers) {
|
|
|
|
let work_items_arc = work_items_arc.clone();
|
|
|
|
let diag_emitter = diag_emitter.clone();
|
2014-09-12 15:17:58 +00:00
|
|
|
let remark = sess.opts.cg.remark.clone();
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
|
|
|
|
let future = TaskBuilder::new().named(format!("codegen-{}", i)).try_future(proc() {
|
|
|
|
let diag_handler = mk_handler(box diag_emitter);
|
|
|
|
|
|
|
|
// Must construct cgcx inside the proc because it has non-Send
|
|
|
|
// fields.
|
2014-09-12 15:17:58 +00:00
|
|
|
let cgcx = CodegenContext {
|
|
|
|
lto_ctxt: None,
|
|
|
|
handler: &diag_handler,
|
|
|
|
remark: remark,
|
|
|
|
};
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
|
|
|
|
loop {
|
|
|
|
// Avoid holding the lock for the entire duration of the match.
|
|
|
|
let maybe_work = work_items_arc.lock().pop();
|
|
|
|
match maybe_work {
|
|
|
|
Some(work) => {
|
|
|
|
work(&cgcx);
|
|
|
|
|
|
|
|
// Make sure to fail the worker so the main thread can
|
|
|
|
// tell that there were errors.
|
|
|
|
cgcx.handler.abort_if_errors();
|
|
|
|
}
|
|
|
|
None => break,
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
|
|
|
});
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
futures.push(future);
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2014-10-09 19:17:22 +00:00
|
|
|
let mut panicked = false;
|
2014-09-15 03:27:36 +00:00
|
|
|
for future in futures.into_iter() {
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
match future.unwrap() {
|
|
|
|
Ok(()) => {},
|
|
|
|
Err(_) => {
|
2014-10-09 19:17:22 +00:00
|
|
|
panicked = true;
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
// Display any new diagnostics.
|
|
|
|
diag_emitter.dump(sess.diagnostic().handler());
|
|
|
|
}
|
2014-10-09 19:17:22 +00:00
|
|
|
if panicked {
|
|
|
|
sess.fatal("aborting due to worker thread panic");
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
|
|
|
|
let pname = get_cc_prog(sess);
|
|
|
|
let mut cmd = Command::new(pname.as_slice());
|
|
|
|
|
|
|
|
cmd.arg("-c").arg("-o").arg(outputs.path(OutputTypeObject))
|
|
|
|
.arg(outputs.temp_path(OutputTypeAssembly));
|
|
|
|
debug!("{}", &cmd);
|
|
|
|
|
|
|
|
match cmd.output() {
|
|
|
|
Ok(prog) => {
|
|
|
|
if !prog.status.success() {
|
|
|
|
sess.err(format!("linking with `{}` failed: {}",
|
|
|
|
pname,
|
|
|
|
prog.status).as_slice());
|
|
|
|
sess.note(format!("{}", &cmd).as_slice());
|
|
|
|
let mut note = prog.error.clone();
|
|
|
|
note.push_all(prog.output.as_slice());
|
|
|
|
sess.note(str::from_utf8(note.as_slice()).unwrap());
|
|
|
|
sess.abort_if_errors();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(e) => {
|
|
|
|
sess.err(format!("could not exec the linker `{}`: {}",
|
|
|
|
pname,
|
|
|
|
e).as_slice());
|
|
|
|
sess.abort_if_errors();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn configure_llvm(sess: &Session) {
|
|
|
|
use std::sync::{Once, ONCE_INIT};
|
2014-10-11 04:59:10 +00:00
|
|
|
static INIT: Once = ONCE_INIT;
|
2014-08-11 17:33:58 +00:00
|
|
|
|
|
|
|
// Copy what clang does by turning on loop vectorization at O2 and
|
|
|
|
// slp vectorization at O3
|
|
|
|
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
|
|
|
|
(sess.opts.optimize == config::Default ||
|
|
|
|
sess.opts.optimize == config::Aggressive);
|
|
|
|
let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
|
|
|
|
sess.opts.optimize == config::Aggressive;
|
|
|
|
|
|
|
|
let mut llvm_c_strs = Vec::new();
|
|
|
|
let mut llvm_args = Vec::new();
|
|
|
|
{
|
|
|
|
let add = |arg: &str| {
|
|
|
|
let s = arg.to_c_str();
|
|
|
|
llvm_args.push(s.as_ptr());
|
|
|
|
llvm_c_strs.push(s);
|
|
|
|
};
|
|
|
|
add("rustc"); // fake program name
|
|
|
|
if vectorize_loop { add("-vectorize-loops"); }
|
|
|
|
if vectorize_slp { add("-vectorize-slp"); }
|
|
|
|
if sess.time_llvm_passes() { add("-time-passes"); }
|
|
|
|
if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
|
|
|
|
|
|
|
|
for arg in sess.opts.cg.llvm_args.iter() {
|
|
|
|
add((*arg).as_slice());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
INIT.doit(|| {
|
|
|
|
llvm::LLVMInitializePasses();
|
|
|
|
|
|
|
|
// Only initialize the platforms supported by Rust here, because
|
|
|
|
// using --llvm-root will have multiple platforms that rustllvm
|
|
|
|
// doesn't actually link to and it's pointless to put target info
|
|
|
|
// into the registry that Rust cannot generate machine code for.
|
|
|
|
llvm::LLVMInitializeX86TargetInfo();
|
|
|
|
llvm::LLVMInitializeX86Target();
|
|
|
|
llvm::LLVMInitializeX86TargetMC();
|
|
|
|
llvm::LLVMInitializeX86AsmPrinter();
|
|
|
|
llvm::LLVMInitializeX86AsmParser();
|
|
|
|
|
|
|
|
llvm::LLVMInitializeARMTargetInfo();
|
|
|
|
llvm::LLVMInitializeARMTarget();
|
|
|
|
llvm::LLVMInitializeARMTargetMC();
|
|
|
|
llvm::LLVMInitializeARMAsmPrinter();
|
|
|
|
llvm::LLVMInitializeARMAsmParser();
|
|
|
|
|
|
|
|
llvm::LLVMInitializeMipsTargetInfo();
|
|
|
|
llvm::LLVMInitializeMipsTarget();
|
|
|
|
llvm::LLVMInitializeMipsTargetMC();
|
|
|
|
llvm::LLVMInitializeMipsAsmPrinter();
|
|
|
|
llvm::LLVMInitializeMipsAsmParser();
|
|
|
|
|
|
|
|
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
|
|
|
|
llvm_args.as_ptr());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
|
|
|
|
mpm: llvm::PassManagerRef,
|
|
|
|
llmod: ModuleRef,
|
|
|
|
opt: llvm::CodeGenOptLevel,
|
|
|
|
no_builtins: bool) {
|
|
|
|
// Create the PassManagerBuilder for LLVM. We configure it with
|
|
|
|
// reasonable defaults and prepare it to actually populate the pass
|
|
|
|
// manager.
|
|
|
|
let builder = llvm::LLVMPassManagerBuilderCreate();
|
|
|
|
match opt {
|
|
|
|
llvm::CodeGenLevelNone => {
|
|
|
|
// Don't add lifetime intrinsics at O0
|
|
|
|
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
|
|
|
|
}
|
|
|
|
llvm::CodeGenLevelLess => {
|
|
|
|
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
|
|
|
|
}
|
|
|
|
// numeric values copied from clang
|
|
|
|
llvm::CodeGenLevelDefault => {
|
|
|
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
|
|
|
|
225);
|
|
|
|
}
|
|
|
|
llvm::CodeGenLevelAggressive => {
|
|
|
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
|
|
|
|
275);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
|
|
|
|
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
|
|
|
|
|
|
|
|
// Use the builder to populate the function/module pass managers.
|
|
|
|
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
|
|
|
|
llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
|
|
|
|
llvm::LLVMPassManagerBuilderDispose(builder);
|
|
|
|
|
|
|
|
match opt {
|
|
|
|
llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
|
|
|
|
"mergefunc".with_c_str(|s| llvm::LLVMRustAddPass(mpm, s));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
};
|
|
|
|
}
|