2014-12-12 23:39:27 +00:00
|
|
|
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
2014-08-11 17:33:58 +00:00
|
|
|
// 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;
|
2017-06-15 14:08:18 +00:00
|
|
|
use back::link::{self, get_linker, remove};
|
2016-11-30 15:03:42 +00:00
|
|
|
use back::symbol_export::ExportedSymbols;
|
2016-08-11 23:02:39 +00:00
|
|
|
use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
|
2017-05-27 18:48:09 +00:00
|
|
|
use rustc::session::config::{self, OutputFilenames, OutputType, OutputTypes, Passes, SomePasses,
|
|
|
|
AllPasses, Sanitizer};
|
|
|
|
use rustc::session::Session;
|
2014-08-11 17:33:58 +00:00
|
|
|
use llvm;
|
2017-07-21 12:29:23 +00:00
|
|
|
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
|
2014-09-27 08:33:36 +00:00
|
|
|
use llvm::SMDiagnosticRef;
|
2017-07-21 13:14:21 +00:00
|
|
|
use {CrateTranslation, OngoingCrateTranslation, ModuleLlvm, ModuleSource, ModuleTranslation};
|
2017-06-15 14:08:18 +00:00
|
|
|
use rustc::hir::def_id::CrateNum;
|
2017-05-27 18:48:09 +00:00
|
|
|
use rustc::util::common::{time, time_depth, set_time_depth, path2cstr};
|
|
|
|
use rustc::util::fs::link_or_copy;
|
2017-06-15 14:08:18 +00:00
|
|
|
use errors::{self, Handler, Level, DiagnosticBuilder, FatalError};
|
2017-07-21 15:15:18 +00:00
|
|
|
use errors::emitter::{Emitter};
|
2017-06-15 14:08:18 +00:00
|
|
|
use syntax::ext::hygiene::Mark;
|
2016-06-21 22:08:13 +00:00
|
|
|
use syntax_pos::MultiSpan;
|
2016-07-14 21:40:14 +00:00
|
|
|
use context::{is_pie_binary, get_reloc_model};
|
2017-06-15 14:08:18 +00:00
|
|
|
use jobserver::{Client, Acquired};
|
2017-06-29 14:52:43 +00:00
|
|
|
use rustc_demangle;
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2017-02-06 15:15:20 +00:00
|
|
|
use std::cmp;
|
2016-11-28 14:15:51 +00:00
|
|
|
use std::ffi::CString;
|
2017-07-24 12:51:00 +00:00
|
|
|
use std::fmt;
|
2015-02-27 05:00:43 +00:00
|
|
|
use std::fs;
|
2017-06-15 14:08:18 +00:00
|
|
|
use std::io;
|
2017-06-29 14:52:43 +00:00
|
|
|
use std::io::Write;
|
2015-09-30 17:08:37 +00:00
|
|
|
use std::path::{Path, PathBuf};
|
2014-08-11 17:33:58 +00:00
|
|
|
use std::str;
|
2017-07-24 12:21:28 +00:00
|
|
|
use std::sync::Arc;
|
2017-07-21 15:15:18 +00:00
|
|
|
use std::sync::mpsc::{channel, Sender, Receiver};
|
2017-06-29 14:52:43 +00:00
|
|
|
use std::slice;
|
2017-07-24 12:21:28 +00:00
|
|
|
use std::thread;
|
2017-06-29 14:52:43 +00:00
|
|
|
use libc::{c_uint, c_void, c_char, size_t};
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2017-04-26 00:05:51 +00:00
|
|
|
pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [
|
2016-08-06 05:50:48 +00:00
|
|
|
("pic", llvm::RelocMode::PIC),
|
|
|
|
("static", llvm::RelocMode::Static),
|
|
|
|
("default", llvm::RelocMode::Default),
|
|
|
|
("dynamic-no-pic", llvm::RelocMode::DynamicNoPic),
|
2017-04-26 00:05:51 +00:00
|
|
|
("ropi", llvm::RelocMode::ROPI),
|
|
|
|
("rwpi", llvm::RelocMode::RWPI),
|
|
|
|
("ropi-rwpi", llvm::RelocMode::ROPI_RWPI),
|
2016-07-24 07:27:23 +00:00
|
|
|
];
|
|
|
|
|
2016-08-06 05:50:48 +00:00
|
|
|
pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [
|
|
|
|
("default", llvm::CodeModel::Default),
|
|
|
|
("small", llvm::CodeModel::Small),
|
|
|
|
("kernel", llvm::CodeModel::Kernel),
|
|
|
|
("medium", llvm::CodeModel::Medium),
|
|
|
|
("large", llvm::CodeModel::Large),
|
2016-07-24 07:27:23 +00:00
|
|
|
];
|
|
|
|
|
2017-06-15 14:08:18 +00:00
|
|
|
pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
|
2015-10-23 05:07:19 +00:00
|
|
|
match llvm::last_error() {
|
2017-06-15 14:08:18 +00:00
|
|
|
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
|
|
|
|
None => handler.fatal(&msg),
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write_output_file(
|
2015-12-13 22:17:55 +00:00
|
|
|
handler: &errors::Handler,
|
2014-08-11 17:33:58 +00:00
|
|
|
target: llvm::TargetMachineRef,
|
|
|
|
pm: llvm::PassManagerRef,
|
|
|
|
m: ModuleRef,
|
|
|
|
output: &Path,
|
2017-06-15 14:08:18 +00:00
|
|
|
file_type: llvm::FileType) -> Result<(), FatalError> {
|
2014-08-11 17:33:58 +00:00
|
|
|
unsafe {
|
2015-02-27 05:00:43 +00:00
|
|
|
let output_c = path2cstr(output);
|
2014-11-25 21:28:35 +00:00
|
|
|
let result = llvm::LLVMRustWriteOutputFile(
|
2015-01-18 00:32:11 +00:00
|
|
|
target, pm, m, output_c.as_ptr(), file_type);
|
2016-08-01 21:16:16 +00:00
|
|
|
if result.into_result().is_err() {
|
2017-06-15 14:08:18 +00:00
|
|
|
let msg = format!("could not write output to {}", output.display());
|
|
|
|
Err(llvm_err(handler, msg))
|
|
|
|
} else {
|
|
|
|
Ok(())
|
2016-07-07 18:57:09 +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
|
|
|
// 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
|
2014-07-23 18:56:36 +00:00
|
|
|
fn target_feature(sess: &Session) -> String {
|
rustc: Implement #[link(cfg(..))] and crt-static
This commit is an implementation of [RFC 1721] which adds a new target feature
to the compiler, `crt-static`, which can be used to select how the C runtime for
a target is linked. Most targets dynamically linke the C runtime by default with
the notable exception of some of the musl targets.
[RFC 1721]: https://github.com/rust-lang/rfcs/blob/master/text/1721-crt-static.md
This commit first adds the new target-feature, `crt-static`. If enabled, then
the `cfg(target_feature = "crt-static")` will be available. Targets like musl
will have this enabled by default. This feature can be controlled through the
standard target-feature interface, `-C target-feature=+crt-static` or
`-C target-feature=-crt-static`.
Next this adds an gated and unstable `#[link(cfg(..))]` feature to enable the
`crt-static` semantics we want with libc. The exact behavior of this attribute
is a little squishy, but it's intended to be a forever-unstable
implementation detail of the liblibc crate.
Specifically the `#[link(cfg(..))]` annotation means that the `#[link]`
directive is only active in a compilation unit if that `cfg` value is satisfied.
For example when compiling an rlib, these directives are just encoded and
ignored for dylibs, and all staticlibs are continued to be put into the rlib as
usual. When placing that rlib into a staticlib, executable, or dylib, however,
the `cfg` is evaluated *as if it were defined in the final artifact* and the
library is decided to be linked or not.
Essentially, what'll happen is:
* On MSVC with `-C target-feature=-crt-static`, the `msvcrt.lib` library will be
linked to.
* On MSVC with `-C target-feature=+crt-static`, the `libcmt.lib` library will be
linked to.
* On musl with `-C target-feature=-crt-static`, the object files in liblibc.rlib
are removed and `-lc` is passed instead.
* On musl with `-C target-feature=+crt-static`, the object files in liblibc.rlib
are used and `-lc` is not passed.
This commit does **not** include an update to the liblibc module to implement
these changes. I plan to do that just after the 1.14.0 beta release is cut to
ensure we get ample time to test this feature.
cc #37406
2016-10-31 23:40:13 +00:00
|
|
|
let rustc_features = [
|
|
|
|
"crt-static",
|
|
|
|
];
|
|
|
|
let requested_features = sess.opts.cg.target_feature.split(',');
|
|
|
|
let llvm_features = requested_features.filter(|f| {
|
|
|
|
!rustc_features.iter().any(|s| f.contains(s))
|
|
|
|
});
|
|
|
|
format!("{},{}",
|
|
|
|
sess.target.target.options.features,
|
|
|
|
llvm_features.collect::<Vec<_>>().join(","))
|
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 get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
|
|
|
|
match optimize {
|
2016-08-01 21:16:16 +00:00
|
|
|
config::OptLevel::No => llvm::CodeGenOptLevel::None,
|
|
|
|
config::OptLevel::Less => llvm::CodeGenOptLevel::Less,
|
|
|
|
config::OptLevel::Default => llvm::CodeGenOptLevel::Default,
|
|
|
|
config::OptLevel::Aggressive => llvm::CodeGenOptLevel::Aggressive,
|
|
|
|
_ => llvm::CodeGenOptLevel::Default,
|
2016-03-27 19:42:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize {
|
|
|
|
match optimize {
|
|
|
|
config::OptLevel::Size => llvm::CodeGenOptSizeDefault,
|
|
|
|
config::OptLevel::SizeMin => llvm::CodeGenOptSizeAggressive,
|
|
|
|
_ => llvm::CodeGenOptSizeNone,
|
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
|
|
|
|
2015-07-16 22:48:16 +00:00
|
|
|
pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
|
2016-07-14 21:40:14 +00:00
|
|
|
let reloc_model = get_reloc_model(sess);
|
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;
|
|
|
|
|
2014-07-23 18:56:36 +00:00
|
|
|
let ffunction_sections = sess.target.target.options.function_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
|
|
|
let fdata_sections = ffunction_sections;
|
|
|
|
|
2014-07-23 18:56:36 +00:00
|
|
|
let code_model_arg = match sess.opts.cg.code_model {
|
2017-03-24 08:31:26 +00:00
|
|
|
Some(ref s) => &s,
|
|
|
|
None => &sess.target.target.options.code_model,
|
2014-07-23 18:56:36 +00:00
|
|
|
};
|
|
|
|
|
2016-07-24 07:27:23 +00:00
|
|
|
let code_model = match CODE_GEN_MODEL_ARGS.iter().find(
|
|
|
|
|&&arg| arg.0 == code_model_arg) {
|
|
|
|
Some(x) => x.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
|
|
|
_ => {
|
2015-01-07 16:58:31 +00:00
|
|
|
sess.err(&format!("{:?} is not a valid code model",
|
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
|
|
|
sess.opts
|
|
|
|
.cg
|
2015-02-20 19:08:14 +00:00
|
|
|
.code_model));
|
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
|
|
|
sess.abort_if_errors();
|
2016-03-28 23:46:02 +00:00
|
|
|
bug!();
|
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
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-20 19:08:14 +00:00
|
|
|
let triple = &sess.target.target.llvm_target;
|
2014-10-29 01:58:46 +00:00
|
|
|
|
|
|
|
let tm = unsafe {
|
2015-02-18 06:47:40 +00:00
|
|
|
let triple = CString::new(triple.as_bytes()).unwrap();
|
2014-11-25 21:28:35 +00:00
|
|
|
let cpu = match sess.opts.cg.target_cpu {
|
2015-02-02 02:53:25 +00:00
|
|
|
Some(ref s) => &**s,
|
|
|
|
None => &*sess.target.target.options.cpu
|
2014-11-25 21:28:35 +00:00
|
|
|
};
|
2015-02-18 06:47:40 +00:00
|
|
|
let cpu = CString::new(cpu.as_bytes()).unwrap();
|
|
|
|
let features = CString::new(target_feature(sess).as_bytes()).unwrap();
|
2014-11-25 21:28:35 +00:00
|
|
|
llvm::LLVMRustCreateTargetMachine(
|
|
|
|
triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
|
|
|
|
code_model,
|
|
|
|
reloc_model,
|
|
|
|
opt_level,
|
|
|
|
use_softfp,
|
2016-07-14 21:40:14 +00:00
|
|
|
is_pie_binary(sess),
|
2014-11-25 21:28:35 +00:00
|
|
|
ffunction_sections,
|
|
|
|
fdata_sections,
|
|
|
|
)
|
2014-10-29 01:58:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if tm.is_null() {
|
2017-06-15 14:08:18 +00:00
|
|
|
let msg = format!("Could not create LLVM TargetMachine for triple: {}",
|
|
|
|
triple);
|
|
|
|
panic!(llvm_err(sess.diagnostic(), msg));
|
2014-10-29 01:58:46 +00:00
|
|
|
} 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`.
|
2015-01-04 03:54:18 +00:00
|
|
|
#[derive(Clone)]
|
2015-07-22 23:22:51 +00:00
|
|
|
pub struct ModuleConfig {
|
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 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
|
|
|
|
2016-03-27 19:42:47 +00:00
|
|
|
/// Some(level) to optimize binary size, or None to not affect program size.
|
|
|
|
opt_size: Option<llvm::CodeGenOptSize>,
|
|
|
|
|
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,
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
vectorize_loop: bool,
|
|
|
|
vectorize_slp: bool,
|
|
|
|
merge_functions: bool,
|
2015-11-27 19:44:33 +00:00
|
|
|
inline_threshold: Option<usize>,
|
|
|
|
// Instead of creating an object file by doing LLVM codegen, just
|
|
|
|
// make the object file bitcode. Provides easy compatibility with
|
|
|
|
// emscripten's ecc compiler, when used as the linker.
|
|
|
|
obj_is_bitcode: 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
|
|
|
}
|
|
|
|
|
2014-12-21 23:49:42 +00:00
|
|
|
unsafe impl Send for ModuleConfig { }
|
2014-12-06 16:39:25 +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
|
|
|
impl ModuleConfig {
|
|
|
|
fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig {
|
|
|
|
ModuleConfig {
|
|
|
|
tm: tm,
|
|
|
|
passes: passes,
|
|
|
|
opt_level: None,
|
2016-03-27 19:42:47 +00:00
|
|
|
opt_size: None,
|
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
|
|
|
|
|
|
|
emit_no_opt_bc: false,
|
|
|
|
emit_bc: false,
|
|
|
|
emit_lto_bc: false,
|
|
|
|
emit_ir: false,
|
|
|
|
emit_asm: false,
|
|
|
|
emit_obj: false,
|
2015-11-27 19:44:33 +00:00
|
|
|
obj_is_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
|
|
|
|
|
|
|
no_verify: false,
|
|
|
|
no_prepopulate_passes: false,
|
|
|
|
no_builtins: false,
|
|
|
|
time_passes: false,
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
vectorize_loop: false,
|
|
|
|
vectorize_slp: false,
|
|
|
|
merge_functions: false,
|
2015-11-20 00:07:09 +00:00
|
|
|
inline_threshold: None
|
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
|
|
|
|
2017-07-21 13:14:21 +00:00
|
|
|
fn set_flags(&mut self, sess: &Session, trans: &OngoingCrateTranslation) {
|
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
|
|
|
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();
|
2015-11-20 00:07:09 +00:00
|
|
|
self.inline_threshold = sess.opts.cg.inline_threshold;
|
2015-11-27 19:44:33 +00:00
|
|
|
self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode;
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
|
|
|
|
// Copy what clang does by turning on loop vectorization at O2 and
|
|
|
|
// slp vectorization at O3. Otherwise configure other optimization aspects
|
|
|
|
// of this pass manager builder.
|
2017-02-20 22:20:06 +00:00
|
|
|
// Turn off vectorization for emscripten, as it's not very well supported.
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
|
2015-12-31 03:50:06 +00:00
|
|
|
(sess.opts.optimize == config::OptLevel::Default ||
|
2017-02-20 22:20:06 +00:00
|
|
|
sess.opts.optimize == config::OptLevel::Aggressive) &&
|
|
|
|
!sess.target.target.options.is_like_emscripten;
|
|
|
|
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
|
2017-02-20 22:20:06 +00:00
|
|
|
sess.opts.optimize == config::OptLevel::Aggressive &&
|
|
|
|
!sess.target.target.options.is_like_emscripten;
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
|
2015-12-31 03:50:06 +00:00
|
|
|
self.merge_functions = sess.opts.optimize == config::OptLevel::Default ||
|
|
|
|
sess.opts.optimize == config::OptLevel::Aggressive;
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Additional resources used by optimize_and_codegen (not module specific)
|
2017-07-24 11:54:18 +00:00
|
|
|
#[derive(Clone)]
|
2017-07-24 12:21:28 +00:00
|
|
|
pub struct CodegenContext {
|
2017-06-15 14:08:18 +00:00
|
|
|
// Resouces needed when running LTO
|
|
|
|
pub time_passes: bool,
|
|
|
|
pub lto: bool,
|
|
|
|
pub no_landing_pads: bool,
|
2017-07-24 12:21:28 +00:00
|
|
|
pub exported_symbols: Arc<ExportedSymbols>,
|
|
|
|
pub opts: Arc<config::Options>,
|
2017-06-15 14:08:18 +00:00
|
|
|
pub crate_types: Vec<config::CrateType>,
|
|
|
|
pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>,
|
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 to use for diagnostics produced during codegen.
|
2017-07-24 11:54:18 +00:00
|
|
|
pub diag_emitter: SharedEmitter,
|
2015-04-08 19:52:58 +00:00
|
|
|
// LLVM passes added by plugins.
|
2017-06-15 14:08:18 +00:00
|
|
|
pub plugin_passes: Vec<String>,
|
2014-09-12 15:17:58 +00:00
|
|
|
// LLVM optimizations for which we want to print remarks.
|
2017-06-15 14:08:18 +00:00
|
|
|
pub remark: Passes,
|
2015-10-26 20:03:03 +00:00
|
|
|
// Worker thread number
|
2017-06-15 14:08:18 +00:00
|
|
|
pub worker: usize,
|
2016-08-11 23:02:39 +00:00
|
|
|
// The incremental compilation session directory, or None if we are not
|
|
|
|
// compiling incrementally
|
2017-06-15 14:08:18 +00:00
|
|
|
pub incr_comp_session_dir: Option<PathBuf>,
|
|
|
|
// Channel back to the main control thread to send messages to
|
2017-07-24 11:54:18 +00:00
|
|
|
pub coordinator_send: Sender<Message>,
|
|
|
|
}
|
2017-07-21 15:15:18 +00:00
|
|
|
|
2017-07-24 12:21:28 +00:00
|
|
|
impl CodegenContext {
|
2017-07-24 11:54:18 +00:00
|
|
|
fn create_diag_handler(&self) -> Handler {
|
|
|
|
Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone()))
|
|
|
|
}
|
2014-09-12 15:17:58 +00:00
|
|
|
}
|
|
|
|
|
2014-09-27 08:33:36 +00:00
|
|
|
struct HandlerFreeVars<'a> {
|
2017-07-24 12:21:28 +00:00
|
|
|
cgcx: &'a CodegenContext,
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler: &'a Handler,
|
2014-09-12 15:17:58 +00:00
|
|
|
}
|
|
|
|
|
2017-07-24 12:21:28 +00:00
|
|
|
unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext,
|
2015-05-26 08:34:50 +00:00
|
|
|
msg: &'b str,
|
|
|
|
cookie: c_uint) {
|
2017-07-24 11:54:18 +00:00
|
|
|
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_string());
|
2014-09-27 08:33:36 +00:00
|
|
|
}
|
|
|
|
|
2015-01-22 18:43:39 +00:00
|
|
|
unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef,
|
|
|
|
user: *const c_void,
|
|
|
|
cookie: c_uint) {
|
2015-07-24 01:04:55 +00:00
|
|
|
let HandlerFreeVars { cgcx, .. } = *(user as *const HandlerFreeVars);
|
2015-01-22 18:43:39 +00:00
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
let msg = llvm::build_string(|s| llvm::LLVMRustWriteSMDiagnosticToString(diag, s))
|
2015-01-22 18:43:39 +00:00
|
|
|
.expect("non-UTF8 SMDiagnostic");
|
|
|
|
|
2017-03-24 08:31:26 +00:00
|
|
|
report_inline_asm(cgcx, &msg, cookie);
|
2015-01-22 18:43:39 +00:00
|
|
|
}
|
|
|
|
|
2014-09-12 15:17:58 +00:00
|
|
|
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
|
2017-07-24 11:54:18 +00:00
|
|
|
let HandlerFreeVars { cgcx, diag_handler, .. } = *(user as *const HandlerFreeVars);
|
2014-09-12 15:17:58 +00:00
|
|
|
|
|
|
|
match llvm::diagnostic::Diagnostic::unpack(info) {
|
2015-01-22 18:43:39 +00:00
|
|
|
llvm::diagnostic::InlineAsm(inline) => {
|
|
|
|
report_inline_asm(cgcx,
|
2016-02-09 20:24:11 +00:00
|
|
|
&llvm::twine_to_string(inline.message),
|
2015-01-22 18:43:39 +00:00
|
|
|
inline.cookie);
|
|
|
|
}
|
|
|
|
|
2014-09-12 15:17:58 +00:00
|
|
|
llvm::diagnostic::Optimization(opt) => {
|
|
|
|
let enabled = match cgcx.remark {
|
|
|
|
AllPasses => true,
|
2016-11-28 14:15:51 +00:00
|
|
|
SomePasses(ref v) => v.iter().any(|s| *s == opt.pass_name),
|
2014-09-12 15:17:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if enabled {
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler.note_without_error(&format!("optimization {} for {} at {}:{}:{}: {}",
|
2015-12-20 21:00:43 +00:00
|
|
|
opt.kind.describe(),
|
2016-11-28 14:15:51 +00:00
|
|
|
opt.pass_name,
|
2017-07-21 12:29:23 +00:00
|
|
|
opt.filename,
|
|
|
|
opt.line,
|
|
|
|
opt.column,
|
2016-11-24 16:33:47 +00:00
|
|
|
opt.message));
|
2014-09-12 15:17:58 +00:00
|
|
|
}
|
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,
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler: &Handler,
|
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
|
|
|
mtrans: ModuleTranslation,
|
2016-07-21 16:49:59 +00:00
|
|
|
mllvm: ModuleLlvm,
|
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
|
|
|
config: ModuleConfig,
|
2017-06-15 14:08:18 +00:00
|
|
|
output_names: OutputFilenames)
|
|
|
|
-> Result<(), FatalError>
|
|
|
|
{
|
2016-07-21 16:49:59 +00:00
|
|
|
let llmod = mllvm.llmod;
|
|
|
|
let llcx = mllvm.llcx;
|
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 tm = config.tm;
|
|
|
|
|
2014-09-27 08:33:36 +00:00
|
|
|
let fv = HandlerFreeVars {
|
2014-09-12 15:17:58 +00:00
|
|
|
cgcx: cgcx,
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler: diag_handler,
|
2014-09-12 15:17:58 +00:00
|
|
|
};
|
2014-09-27 08:33:36 +00:00
|
|
|
let fv = &fv as *const HandlerFreeVars as *mut c_void;
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, fv);
|
2015-01-22 18:43:39 +00:00
|
|
|
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, fv);
|
2014-09-12 15:17:58 +00:00
|
|
|
|
2016-05-14 00:48:32 +00:00
|
|
|
let module_name = Some(&mtrans.name[..]);
|
|
|
|
|
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 {
|
2016-05-14 00:48:32 +00:00
|
|
|
let out = output_names.temp_path_ext("no-opt.bc", module_name);
|
2015-02-27 05:00:43 +00:00
|
|
|
let out = path2cstr(&out);
|
2014-11-25 21:28:35 +00:00
|
|
|
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
|
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
|
|
|
}
|
|
|
|
|
2015-07-22 23:22:51 +00:00
|
|
|
if config.opt_level.is_some() {
|
|
|
|
// 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.
|
2016-01-25 01:22:24 +00:00
|
|
|
let addpass = |pass_name: &str| {
|
|
|
|
let pass_name = CString::new(pass_name).unwrap();
|
|
|
|
let pass = llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr());
|
|
|
|
if pass.is_null() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
let pass_manager = match llvm::LLVMRustPassKind(pass) {
|
2016-08-01 21:16:16 +00:00
|
|
|
llvm::PassKind::Function => fpm,
|
|
|
|
llvm::PassKind::Module => mpm,
|
|
|
|
llvm::PassKind::Other => {
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler.err("Encountered LLVM pass kind we can't handle");
|
2016-01-25 01:22:24 +00:00
|
|
|
return true
|
|
|
|
},
|
|
|
|
};
|
|
|
|
llvm::LLVMRustAddPass(pass_manager, pass);
|
|
|
|
true
|
2015-07-22 23:22:51 +00:00
|
|
|
};
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2015-07-22 23:22:51 +00:00
|
|
|
if !config.no_verify { assert!(addpass("verify")); }
|
|
|
|
if !config.no_prepopulate_passes {
|
|
|
|
llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
|
|
|
|
llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
|
|
|
|
with_llvm_pmb(llmod, &config, &mut |b| {
|
|
|
|
llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
|
|
|
|
llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
|
|
|
|
})
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2015-07-22 23:22:51 +00:00
|
|
|
for pass in &config.passes {
|
|
|
|
if !addpass(pass) {
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler.warn(&format!("unknown pass `{}`, ignoring",
|
2015-07-22 23:22:51 +00:00
|
|
|
pass));
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
2015-07-22 23:22:51 +00:00
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2015-07-22 23:22:51 +00:00
|
|
|
for pass in &cgcx.plugin_passes {
|
|
|
|
if !addpass(pass) {
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler.err(&format!("a plugin asked for LLVM pass \
|
2015-07-22 23:22:51 +00:00
|
|
|
`{}` but LLVM does not \
|
|
|
|
recognize it", pass));
|
2015-04-08 19:52:58 +00:00
|
|
|
}
|
2015-07-22 23:22:51 +00:00
|
|
|
}
|
2015-04-08 19:52:58 +00:00
|
|
|
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler.abort_if_errors();
|
2015-04-08 19:52:58 +00:00
|
|
|
|
2015-07-22 23:22:51 +00:00
|
|
|
// Finally, run the actual optimization passes
|
2015-10-26 20:03:03 +00:00
|
|
|
time(config.time_passes, &format!("llvm function passes [{}]", cgcx.worker), ||
|
2015-07-22 23:22:51 +00:00
|
|
|
llvm::LLVMRustRunFunctionPassManager(fpm, llmod));
|
2015-10-26 20:03:03 +00:00
|
|
|
time(config.time_passes, &format!("llvm module passes [{}]", cgcx.worker), ||
|
2015-07-22 23:22:51 +00:00
|
|
|
llvm::LLVMRunPassManager(mpm, llmod));
|
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
|
|
|
|
2015-07-22 23:22:51 +00:00
|
|
|
// Deallocate managers that we're now done with
|
|
|
|
llvm::LLVMDisposePassManager(fpm);
|
|
|
|
llvm::LLVMDisposePassManager(mpm);
|
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
|
|
|
|
2017-06-15 14:08:18 +00:00
|
|
|
if cgcx.lto {
|
|
|
|
time(cgcx.time_passes, "all lto passes", || {
|
|
|
|
let temp_no_opt_bc_filename =
|
|
|
|
output_names.temp_path_ext("no-opt.lto.bc", module_name);
|
|
|
|
lto::run(cgcx,
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler,
|
2017-06-15 14:08:18 +00:00
|
|
|
llmod,
|
|
|
|
tm,
|
|
|
|
&config,
|
|
|
|
&temp_no_opt_bc_filename)
|
|
|
|
})?;
|
|
|
|
if config.emit_lto_bc {
|
|
|
|
let out = output_names.temp_path_ext("lto.bc", module_name);
|
|
|
|
let out = path2cstr(&out);
|
|
|
|
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
|
|
|
|
}
|
2015-07-22 23:22:51 +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
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2017-06-15 14:08:18 +00:00
|
|
|
unsafe fn with_codegen<F, R>(tm: TargetMachineRef,
|
|
|
|
llmod: ModuleRef,
|
|
|
|
no_builtins: bool,
|
|
|
|
f: F) -> R
|
|
|
|
where F: FnOnce(PassManagerRef) -> R,
|
2014-12-09 18:44:51 +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 cpm = llvm::LLVMCreatePassManager();
|
|
|
|
llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
|
|
|
|
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
2017-06-15 14:08:18 +00:00
|
|
|
f(cpm)
|
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
|
|
|
}
|
|
|
|
|
2015-11-27 19:44:33 +00:00
|
|
|
// Change what we write and cleanup based on whether obj files are
|
|
|
|
// just llvm bitcode. In that case write bitcode, and possibly
|
|
|
|
// delete the bitcode if it wasn't requested. Don't generate the
|
|
|
|
// machine code, instead copy the .o file from the .bc
|
|
|
|
let write_bc = config.emit_bc || config.obj_is_bitcode;
|
|
|
|
let rm_bc = !config.emit_bc && config.obj_is_bitcode;
|
|
|
|
let write_obj = config.emit_obj && !config.obj_is_bitcode;
|
|
|
|
let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
|
|
|
|
|
2016-05-14 00:48:32 +00:00
|
|
|
let bc_out = output_names.temp_path(OutputType::Bitcode, module_name);
|
|
|
|
let obj_out = output_names.temp_path(OutputType::Object, module_name);
|
2015-11-27 19:44:33 +00:00
|
|
|
|
|
|
|
if write_bc {
|
|
|
|
let bc_out_c = path2cstr(&bc_out);
|
|
|
|
llvm::LLVMWriteBitcodeToFile(llmod, bc_out_c.as_ptr());
|
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
|
|
|
}
|
|
|
|
|
2017-06-15 14:08:18 +00:00
|
|
|
time(config.time_passes, &format!("codegen passes [{}]", cgcx.worker),
|
|
|
|
|| -> Result<(), FatalError> {
|
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_ir {
|
2016-05-14 00:48:32 +00:00
|
|
|
let out = output_names.temp_path(OutputType::LlvmAssembly, module_name);
|
2015-02-27 05:00:43 +00:00
|
|
|
let out = path2cstr(&out);
|
2017-06-29 14:52:43 +00:00
|
|
|
|
|
|
|
extern "C" fn demangle_callback(input_ptr: *const c_char,
|
|
|
|
input_len: size_t,
|
|
|
|
output_ptr: *mut c_char,
|
|
|
|
output_len: size_t) -> size_t {
|
|
|
|
let input = unsafe {
|
|
|
|
slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
|
|
|
|
};
|
|
|
|
|
|
|
|
let input = match str::from_utf8(input) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(_) => return 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
let output = unsafe {
|
|
|
|
slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
|
|
|
|
};
|
|
|
|
let mut cursor = io::Cursor::new(output);
|
|
|
|
|
|
|
|
let demangled = match rustc_demangle::try_demangle(input) {
|
|
|
|
Ok(d) => d,
|
|
|
|
Err(_) => return 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Err(_) = write!(cursor, "{:#}", demangled) {
|
|
|
|
// Possible only if provided buffer is not big enough
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cursor.position() as size_t
|
|
|
|
}
|
|
|
|
|
2014-11-25 21:28:35 +00:00
|
|
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
2017-06-29 14:52:43 +00:00
|
|
|
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
llvm::LLVMDisposePassManager(cpm);
|
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
|
|
|
if config.emit_asm {
|
2016-05-14 00:48:32 +00:00
|
|
|
let path = output_names.temp_path(OutputType::Assembly, module_name);
|
2015-12-18 00:24:40 +00:00
|
|
|
|
|
|
|
// We can't use the same module for asm and binary output, because that triggers
|
|
|
|
// various errors like invalid IR or broken binaries, so we might have to clone the
|
|
|
|
// module to produce the asm output
|
|
|
|
let llmod = if config.emit_obj {
|
|
|
|
llvm::LLVMCloneModule(llmod)
|
|
|
|
} else {
|
|
|
|
llmod
|
|
|
|
};
|
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
|
|
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
2017-07-24 11:54:18 +00:00
|
|
|
write_output_file(diag_handler, tm, cpm, llmod, &path,
|
2017-06-15 14:08:18 +00:00
|
|
|
llvm::FileType::AssemblyFile)
|
|
|
|
})?;
|
2015-12-18 00:24:40 +00:00
|
|
|
if config.emit_obj {
|
|
|
|
llvm::LLVMDisposeModule(llmod);
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2015-11-27 19:44:33 +00:00
|
|
|
if write_obj {
|
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
|
|
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
2017-07-24 11:54:18 +00:00
|
|
|
write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
|
2017-06-15 14:08:18 +00:00
|
|
|
llvm::FileType::ObjectFile)
|
|
|
|
})?;
|
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
|
|
|
}
|
2017-06-15 14:08:18 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})?;
|
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
|
|
|
|
2015-11-27 19:44:33 +00:00
|
|
|
if copy_bc_to_obj {
|
|
|
|
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
|
2016-07-25 14:51:14 +00:00
|
|
|
if let Err(e) = link_or_copy(&bc_out, &obj_out) {
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
|
2015-11-27 19:44:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if rm_bc {
|
|
|
|
debug!("removing_bitcode {:?}", bc_out);
|
|
|
|
if let Err(e) = fs::remove_file(&bc_out) {
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler.err(&format!("failed to remove bitcode: {}", e));
|
2015-11-27 19:44:33 +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
|
|
|
llvm::LLVMRustDisposeTargetMachine(tm);
|
2017-06-15 14:08:18 +00:00
|
|
|
Ok(())
|
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
|
|
|
}
|
|
|
|
|
2016-06-30 20:32:13 +00:00
|
|
|
|
|
|
|
pub fn cleanup_llvm(trans: &CrateTranslation) {
|
|
|
|
for module in trans.modules.iter() {
|
|
|
|
unsafe {
|
2016-07-21 16:49:59 +00:00
|
|
|
match module.source {
|
|
|
|
ModuleSource::Translated(llvm) => {
|
|
|
|
llvm::LLVMDisposeModule(llvm.llmod);
|
|
|
|
llvm::LLVMContextDispose(llvm.llcx);
|
|
|
|
}
|
|
|
|
ModuleSource::Preexisting(_) => {
|
|
|
|
}
|
|
|
|
}
|
2016-06-30 20:32:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-21 15:15:18 +00:00
|
|
|
pub struct RunLLVMPassesResult {
|
|
|
|
pub modules: Vec<ModuleTranslation>,
|
|
|
|
pub metadata_module: ModuleTranslation,
|
|
|
|
pub allocator_module: Option<ModuleTranslation>,
|
|
|
|
}
|
|
|
|
|
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 run_passes(sess: &Session,
|
2017-07-21 13:14:21 +00:00
|
|
|
trans: &OngoingCrateTranslation,
|
2017-07-21 15:15:18 +00:00
|
|
|
modules: Vec<ModuleTranslation>,
|
|
|
|
metadata_module: ModuleTranslation,
|
|
|
|
allocator_module: Option<ModuleTranslation>,
|
2016-08-02 20:53:58 +00:00
|
|
|
output_types: &OutputTypes,
|
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
|
|
|
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
|
2017-07-21 15:15:18 +00:00
|
|
|
assert!(modules.len() == sess.opts.cg.codegen_units ||
|
2017-01-19 16:32:55 +00:00
|
|
|
sess.opts.debugging_opts.incremental.is_some() ||
|
2017-01-20 01:18:12 +00:00
|
|
|
!sess.opts.output_types.should_trans() ||
|
|
|
|
sess.opts.debugging_opts.no_trans);
|
2014-09-05 21:30:36 +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 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());
|
2016-10-29 21:54:04 +00:00
|
|
|
let mut metadata_config = ModuleConfig::new(tm, vec![]);
|
2017-06-03 21:54:08 +00:00
|
|
|
let mut allocator_config = ModuleConfig::new(tm, vec![]);
|
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
|
|
|
|
2016-12-30 04:28:11 +00:00
|
|
|
if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer {
|
|
|
|
match *sanitizer {
|
|
|
|
Sanitizer::Address => {
|
|
|
|
modules_config.passes.push("asan".to_owned());
|
|
|
|
modules_config.passes.push("asan-module".to_owned());
|
|
|
|
}
|
|
|
|
Sanitizer::Memory => {
|
|
|
|
modules_config.passes.push("msan".to_owned())
|
|
|
|
}
|
|
|
|
Sanitizer::Thread => {
|
|
|
|
modules_config.passes.push("tsan".to_owned())
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 09:57:50 +00:00
|
|
|
if sess.opts.debugging_opts.profile {
|
|
|
|
modules_config.passes.push("insert-gcov-profiling".to_owned())
|
|
|
|
}
|
|
|
|
|
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
|
|
|
modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize));
|
2016-03-27 19:42:47 +00:00
|
|
|
modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize));
|
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
|
|
|
|
|
|
|
// 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;
|
2017-06-03 21:54:08 +00:00
|
|
|
allocator_config.emit_bc = 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
|
|
|
// 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) &&
|
2015-09-30 17:08:37 +00:00
|
|
|
sess.opts.output_types.contains_key(&OutputType::Exe);
|
2015-07-07 01:21:57 +00:00
|
|
|
let needs_crate_object =
|
2015-09-30 17:08:37 +00:00
|
|
|
sess.opts.output_types.contains_key(&OutputType::Exe);
|
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;
|
|
|
|
}
|
|
|
|
|
2015-09-30 17:08:37 +00:00
|
|
|
for output_type in output_types.keys() {
|
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 *output_type {
|
2016-12-23 06:39:20 +00:00
|
|
|
OutputType::Bitcode => { modules_config.emit_bc = true; }
|
|
|
|
OutputType::LlvmAssembly => { modules_config.emit_ir = true; }
|
2015-09-30 17:08:37 +00:00
|
|
|
OutputType::Assembly => {
|
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
|
|
|
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.
|
2015-09-30 17:08:37 +00:00
|
|
|
if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
|
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
|
|
|
metadata_config.emit_obj = true;
|
2017-06-03 21:54:08 +00:00
|
|
|
allocator_config.emit_obj = true;
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
2016-12-23 06:39:20 +00:00
|
|
|
}
|
|
|
|
OutputType::Object => { modules_config.emit_obj = true; }
|
|
|
|
OutputType::Metadata => { metadata_config.emit_obj = true; }
|
2015-09-30 17:08:37 +00:00
|
|
|
OutputType::Exe => {
|
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
|
|
|
modules_config.emit_obj = true;
|
|
|
|
metadata_config.emit_obj = true;
|
2017-06-03 21:54:08 +00:00
|
|
|
allocator_config.emit_obj = 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
|
|
|
},
|
2017-02-16 21:59:09 +00:00
|
|
|
OutputType::Mir => {}
|
2015-09-30 17:08:37 +00:00
|
|
|
OutputType::DepInfo => {}
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
modules_config.set_flags(sess, trans);
|
|
|
|
metadata_config.set_flags(sess, trans);
|
2017-06-03 21:54:08 +00:00
|
|
|
allocator_config.set_flags(sess, trans);
|
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
|
|
|
|
|
|
|
|
2015-05-08 15:12:29 +00:00
|
|
|
// Populate a buffer with a list of codegen threads. Items are processed in
|
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
|
|
|
// LIFO order, just because it's a tiny bit simpler that way. (The order
|
|
|
|
// doesn't actually matter.)
|
2017-07-21 15:15:18 +00:00
|
|
|
let mut work_items = Vec::with_capacity(1 + modules.len());
|
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 work = build_work_item(sess,
|
2017-07-21 15:15:18 +00:00
|
|
|
metadata_module.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
|
|
|
metadata_config.clone(),
|
2016-05-14 00:48:32 +00:00
|
|
|
crate_output.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
|
|
|
work_items.push(work);
|
|
|
|
}
|
|
|
|
|
2017-07-21 15:15:18 +00:00
|
|
|
if let Some(allocator) = allocator_module.clone() {
|
2017-06-03 21:54:08 +00:00
|
|
|
let work = build_work_item(sess,
|
|
|
|
allocator,
|
|
|
|
allocator_config.clone(),
|
|
|
|
crate_output.clone());
|
|
|
|
work_items.push(work);
|
|
|
|
}
|
|
|
|
|
2017-07-21 15:15:18 +00:00
|
|
|
for mtrans in modules.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
|
|
|
let work = build_work_item(sess,
|
2016-05-14 00:48:32 +00:00
|
|
|
mtrans.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
|
|
|
modules_config.clone(),
|
2016-05-14 00:48:32 +00:00
|
|
|
crate_output.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
|
|
|
work_items.push(work);
|
|
|
|
}
|
|
|
|
|
2017-06-15 14:08:18 +00:00
|
|
|
let client = sess.jobserver_from_env.clone().unwrap_or_else(|| {
|
|
|
|
// Pick a "reasonable maximum" if we don't otherwise have a jobserver in
|
|
|
|
// our environment, capping out at 32 so we don't take everything down
|
|
|
|
// by hogging the process run queue.
|
|
|
|
let num_workers = cmp::min(work_items.len() - 1, 32);
|
|
|
|
Client::new(num_workers).expect("failed to create jobserver")
|
|
|
|
});
|
2017-07-24 12:21:28 +00:00
|
|
|
|
2017-07-24 12:51:00 +00:00
|
|
|
let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
|
|
|
|
let (trans_worker_send, trans_worker_receive) = channel();
|
2017-07-24 13:50:42 +00:00
|
|
|
let (coordinator_send, coordinator_receive) = channel();
|
2017-07-24 12:51:00 +00:00
|
|
|
|
|
|
|
let coordinator_thread = start_executing_work(sess,
|
2017-07-24 13:50:42 +00:00
|
|
|
work_items.len(),
|
2017-07-24 12:51:00 +00:00
|
|
|
shared_emitter,
|
|
|
|
trans_worker_send,
|
2017-07-24 13:50:42 +00:00
|
|
|
coordinator_send.clone(),
|
|
|
|
coordinator_receive,
|
2017-07-24 12:51:00 +00:00
|
|
|
client,
|
|
|
|
trans.exported_symbols.clone());
|
2017-07-24 13:50:42 +00:00
|
|
|
for work_item in work_items {
|
|
|
|
coordinator_send.send(Message::WorkItem(work_item)).unwrap();
|
|
|
|
}
|
|
|
|
|
2017-07-24 12:51:00 +00:00
|
|
|
loop {
|
|
|
|
shared_emitter_main.check(sess);
|
|
|
|
|
|
|
|
match trans_worker_receive.recv() {
|
2017-07-24 13:50:42 +00:00
|
|
|
Err(_) => {
|
|
|
|
// An `Err` here means that all senders for this channel have
|
|
|
|
// been closed. This could happen because all work has
|
|
|
|
// completed successfully or there has been some error.
|
|
|
|
// At this point we don't care which it is.
|
|
|
|
break
|
|
|
|
}
|
2017-07-24 12:51:00 +00:00
|
|
|
|
|
|
|
Ok(Message::CheckErrorMessages) => continue,
|
|
|
|
Ok(msg) => {
|
|
|
|
bug!("unexpected message {:?}", msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-24 13:50:42 +00:00
|
|
|
match coordinator_thread.join() {
|
|
|
|
Ok(()) => {},
|
|
|
|
Err(err) => {
|
|
|
|
panic!("error: {:?}", err);
|
|
|
|
}
|
|
|
|
}
|
2017-07-24 12:51:00 +00:00
|
|
|
|
|
|
|
// Just in case, check this on the way out.
|
2017-07-24 13:50:42 +00:00
|
|
|
shared_emitter_main.check(sess);
|
2017-07-24 12:51:00 +00:00
|
|
|
sess.diagnostic().abort_if_errors();
|
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
|
|
|
|
2016-07-21 16:49:59 +00:00
|
|
|
// If in incr. comp. mode, preserve the `.o` files for potential re-use
|
2017-07-21 15:15:18 +00:00
|
|
|
for mtrans in modules.iter() {
|
2016-07-25 14:51:14 +00:00
|
|
|
let mut files = vec![];
|
|
|
|
|
|
|
|
if modules_config.emit_obj {
|
|
|
|
let path = crate_output.temp_path(OutputType::Object, Some(&mtrans.name));
|
|
|
|
files.push((OutputType::Object, path));
|
|
|
|
}
|
|
|
|
|
|
|
|
if modules_config.emit_bc {
|
|
|
|
let path = crate_output.temp_path(OutputType::Bitcode, Some(&mtrans.name));
|
|
|
|
files.push((OutputType::Bitcode, path));
|
|
|
|
}
|
|
|
|
|
|
|
|
save_trans_partition(sess, &mtrans.name, mtrans.symbol_name_hash, &files);
|
2016-07-21 16:49:59 +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
|
|
|
// All codegen is finished.
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDisposeTargetMachine(tm);
|
|
|
|
}
|
|
|
|
|
2014-09-17 23:18:12 +00:00
|
|
|
let mut user_wants_bitcode = false;
|
2015-07-07 01:21:57 +00:00
|
|
|
let mut user_wants_objects = false;
|
2017-07-21 15:15:18 +00:00
|
|
|
{
|
|
|
|
// Produce final compile outputs.
|
|
|
|
let copy_gracefully = |from: &Path, to: &Path| {
|
|
|
|
if let Err(e) = fs::copy(from, to) {
|
|
|
|
sess.err(&format!("could not copy {:?} to {:?}: {}", from, to, e));
|
2014-11-16 01:30:33 +00:00
|
|
|
}
|
2017-07-21 15:15:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let copy_if_one_unit = |output_type: OutputType,
|
|
|
|
keep_numbered: bool| {
|
|
|
|
if modules.len() == 1 {
|
|
|
|
// 1) Only one codegen unit. In this case it's no difficulty
|
|
|
|
// to copy `foo.0.x` to `foo.x`.
|
|
|
|
let module_name = Some(&modules[0].name[..]);
|
|
|
|
let path = crate_output.temp_path(output_type, module_name);
|
|
|
|
copy_gracefully(&path,
|
|
|
|
&crate_output.path(output_type));
|
|
|
|
if !sess.opts.cg.save_temps && !keep_numbered {
|
|
|
|
// The user just wants `foo.x`, not `foo.#module-name#.x`.
|
|
|
|
remove(sess, &path);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let ext = crate_output.temp_path(output_type, None)
|
|
|
|
.extension()
|
|
|
|
.unwrap()
|
|
|
|
.to_str()
|
|
|
|
.unwrap()
|
|
|
|
.to_owned();
|
|
|
|
|
|
|
|
if crate_output.outputs.contains_key(&output_type) {
|
|
|
|
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
|
|
|
|
// no good solution for this case, so warn the user.
|
|
|
|
sess.warn(&format!("ignoring emit path because multiple .{} files \
|
|
|
|
were produced", ext));
|
|
|
|
} else if crate_output.single_output_file.is_some() {
|
|
|
|
// 3) Multiple codegen units, with `-o some_name`. We have
|
|
|
|
// no good solution for this case, so warn the user.
|
|
|
|
sess.warn(&format!("ignoring -o because multiple .{} files \
|
|
|
|
were produced", ext));
|
|
|
|
} else {
|
|
|
|
// 4) Multiple codegen units, but no explicit name. We
|
|
|
|
// just leave the `foo.0.x` files in place.
|
|
|
|
// (We don't have to do any work in this case.)
|
|
|
|
}
|
2014-11-16 01:30:33 +00:00
|
|
|
}
|
2017-07-21 15:15:18 +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.
|
|
|
|
for output_type in output_types.keys() {
|
|
|
|
match *output_type {
|
|
|
|
OutputType::Bitcode => {
|
|
|
|
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(OutputType::Bitcode, true);
|
|
|
|
}
|
|
|
|
OutputType::LlvmAssembly => {
|
|
|
|
copy_if_one_unit(OutputType::LlvmAssembly, false);
|
|
|
|
}
|
|
|
|
OutputType::Assembly => {
|
|
|
|
copy_if_one_unit(OutputType::Assembly, false);
|
|
|
|
}
|
|
|
|
OutputType::Object => {
|
|
|
|
user_wants_objects = true;
|
|
|
|
copy_if_one_unit(OutputType::Object, true);
|
|
|
|
}
|
|
|
|
OutputType::Mir |
|
|
|
|
OutputType::Metadata |
|
|
|
|
OutputType::Exe |
|
|
|
|
OutputType::DepInfo => {}
|
2014-11-16 01:30:33 +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:
|
2017-02-07 17:24:43 +00:00
|
|
|
// - #crate#.#module-name#.bc
|
|
|
|
// - #crate#.#module-name#.o
|
|
|
|
// - #crate#.crate.metadata.bc
|
|
|
|
// - #crate#.crate.metadata.o
|
|
|
|
// - #crate#.o (linked from crate.##.o)
|
|
|
|
// - #crate#.bc (copied from crate.##.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 {
|
2016-05-14 00:48:32 +00:00
|
|
|
// Remove the temporary .#module-name#.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
|
2016-05-14 00:48:32 +00:00
|
|
|
// needed for building an rlib, then we must remove .#module-name#.bc as
|
|
|
|
// well.
|
2014-09-17 23:18:12 +00:00
|
|
|
|
2016-05-14 00:48:32 +00:00
|
|
|
// Specific rules for keeping .#module-name#.bc:
|
2014-09-17 23:18:12 +00:00
|
|
|
// - 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
|
2016-05-14 00:48:32 +00:00
|
|
|
// can toss .#module-name#.bc because we copied it to .bc earlier.
|
2014-09-17 23:18:12 +00:00
|
|
|
// - If we're not building an rlib and the user didn't request
|
2016-05-14 00:48:32 +00:00
|
|
|
// bitcode, then delete .#module-name#.bc.
|
2014-09-17 23:18:12 +00:00
|
|
|
// If you change how this works, also update back::link::link_rlib,
|
2016-05-14 00:48:32 +00:00
|
|
|
// where .#module-name#.bc files are (maybe) deleted after making an
|
|
|
|
// rlib.
|
2014-09-17 23:18:12 +00:00
|
|
|
let keep_numbered_bitcode = needs_crate_bitcode ||
|
|
|
|
(user_wants_bitcode && sess.opts.cg.codegen_units > 1);
|
|
|
|
|
2015-07-07 01:21:57 +00:00
|
|
|
let keep_numbered_objects = needs_crate_object ||
|
|
|
|
(user_wants_objects && sess.opts.cg.codegen_units > 1);
|
|
|
|
|
2017-07-21 15:15:18 +00:00
|
|
|
for module_name in modules.iter().map(|m| Some(&m.name[..])) {
|
2015-07-07 01:21:57 +00:00
|
|
|
if modules_config.emit_obj && !keep_numbered_objects {
|
2016-05-14 00:48:32 +00:00
|
|
|
let path = crate_output.temp_path(OutputType::Object, module_name);
|
|
|
|
remove(sess, &path);
|
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 {
|
2016-05-14 00:48:32 +00:00
|
|
|
let path = crate_output.temp_path(OutputType::Bitcode, module_name);
|
|
|
|
remove(sess, &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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-17 23:18:12 +00:00
|
|
|
if metadata_config.emit_bc && !user_wants_bitcode {
|
2016-05-14 00:48:32 +00:00
|
|
|
let path = crate_output.temp_path(OutputType::Bitcode,
|
2017-07-21 15:15:18 +00:00
|
|
|
Some(&metadata_module.name));
|
2016-05-14 00:48:32 +00:00
|
|
|
remove(sess, &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
|
|
|
}
|
2017-06-03 21:54:08 +00:00
|
|
|
if allocator_config.emit_bc && !user_wants_bitcode {
|
2017-07-21 15:15:18 +00:00
|
|
|
if let Some(ref module) = allocator_module {
|
2017-06-03 21:54:08 +00:00
|
|
|
let path = crate_output.temp_path(OutputType::Bitcode,
|
|
|
|
Some(&module.name));
|
|
|
|
remove(sess, &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
|
|
|
}
|
|
|
|
|
|
|
|
// We leave the following files around by default:
|
2017-02-07 17:24:43 +00:00
|
|
|
// - #crate#.o
|
|
|
|
// - #crate#.crate.metadata.o
|
|
|
|
// - #crate#.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
|
|
|
// 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?
|
2015-02-28 21:40:39 +00:00
|
|
|
if sess.opts.cg.codegen_units == 1 && sess.time_llvm_passes() {
|
|
|
|
unsafe { llvm::LLVMRustPrintPassTimings(); }
|
|
|
|
}
|
2017-07-21 15:15:18 +00:00
|
|
|
|
|
|
|
*trans.result.borrow_mut() = Some(
|
|
|
|
RunLLVMPassesResult {
|
|
|
|
modules,
|
|
|
|
metadata_module,
|
|
|
|
allocator_module,
|
|
|
|
}
|
|
|
|
);
|
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
|
|
|
}
|
|
|
|
|
2017-07-21 13:14:21 +00:00
|
|
|
pub fn dump_incremental_data(trans: &CrateTranslation) {
|
2016-08-01 23:56:19 +00:00
|
|
|
let mut reuse = 0;
|
|
|
|
for mtrans in trans.modules.iter() {
|
|
|
|
match mtrans.source {
|
|
|
|
ModuleSource::Preexisting(..) => reuse += 1,
|
|
|
|
ModuleSource::Translated(..) => (),
|
|
|
|
}
|
|
|
|
}
|
2017-06-22 08:27:45 +00:00
|
|
|
eprintln!("incremental: re-using {} out of {} modules", reuse, trans.modules.len());
|
2016-08-01 23:56:19 +00:00
|
|
|
}
|
|
|
|
|
2017-07-24 12:51:00 +00:00
|
|
|
pub struct WorkItem {
|
2014-11-26 15:07:58 +00:00
|
|
|
mtrans: ModuleTranslation,
|
|
|
|
config: ModuleConfig,
|
2016-05-14 00:48:32 +00:00
|
|
|
output_names: OutputFilenames
|
2014-11-26 15:07: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
|
|
|
|
2017-07-24 12:51:00 +00:00
|
|
|
impl fmt::Debug for WorkItem {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "WorkItem({})", self.mtrans.name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 build_work_item(sess: &Session,
|
|
|
|
mtrans: ModuleTranslation,
|
|
|
|
config: ModuleConfig,
|
2016-05-14 00:48:32 +00:00
|
|
|
output_names: OutputFilenames)
|
2014-11-26 15:07:58 +00:00
|
|
|
-> WorkItem
|
|
|
|
{
|
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 mut config = config;
|
|
|
|
config.tm = create_target_machine(sess);
|
2016-05-14 00:48:32 +00:00
|
|
|
WorkItem {
|
|
|
|
mtrans: mtrans,
|
|
|
|
config: config,
|
|
|
|
output_names: output_names
|
|
|
|
}
|
2014-11-26 15:07: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
|
|
|
|
2017-06-15 14:08:18 +00:00
|
|
|
fn execute_work_item(cgcx: &CodegenContext, work_item: WorkItem)
|
|
|
|
-> Result<(), FatalError>
|
|
|
|
{
|
2017-07-24 11:54:18 +00:00
|
|
|
let diag_handler = cgcx.create_diag_handler();
|
2014-11-26 15:07:58 +00:00
|
|
|
unsafe {
|
2016-07-21 16:49:59 +00:00
|
|
|
match work_item.mtrans.source {
|
|
|
|
ModuleSource::Translated(mllvm) => {
|
|
|
|
debug!("llvm-optimizing {:?}", work_item.mtrans.name);
|
|
|
|
optimize_and_codegen(cgcx,
|
2017-07-24 11:54:18 +00:00
|
|
|
&diag_handler,
|
2016-07-21 16:49:59 +00:00
|
|
|
work_item.mtrans,
|
|
|
|
mllvm,
|
|
|
|
work_item.config,
|
2017-06-15 14:08:18 +00:00
|
|
|
work_item.output_names)?;
|
2016-07-21 16:49:59 +00:00
|
|
|
}
|
2016-07-25 14:51:14 +00:00
|
|
|
ModuleSource::Preexisting(wp) => {
|
2016-08-11 23:02:39 +00:00
|
|
|
let incr_comp_session_dir = cgcx.incr_comp_session_dir
|
|
|
|
.as_ref()
|
|
|
|
.unwrap();
|
2016-07-25 14:51:14 +00:00
|
|
|
let name = &work_item.mtrans.name;
|
|
|
|
for (kind, saved_file) in wp.saved_files {
|
|
|
|
let obj_out = work_item.output_names.temp_path(kind, Some(name));
|
2016-08-11 23:02:39 +00:00
|
|
|
let source_file = in_incr_comp_dir(&incr_comp_session_dir,
|
|
|
|
&saved_file);
|
2016-07-25 14:51:14 +00:00
|
|
|
debug!("copying pre-existing module `{}` from {:?} to {}",
|
|
|
|
work_item.mtrans.name,
|
|
|
|
source_file,
|
|
|
|
obj_out.display());
|
|
|
|
match link_or_copy(&source_file, &obj_out) {
|
2016-08-11 23:02:39 +00:00
|
|
|
Ok(_) => { }
|
2016-07-25 14:51:14 +00:00
|
|
|
Err(err) => {
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_handler.err(&format!("unable to copy {} to {}: {}",
|
2016-07-25 14:51:14 +00:00
|
|
|
source_file.display(),
|
|
|
|
obj_out.display(),
|
|
|
|
err));
|
|
|
|
}
|
2016-07-21 16:49:59 +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
|
|
|
}
|
2017-06-15 14:08:18 +00:00
|
|
|
|
|
|
|
Ok(())
|
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
|
|
|
}
|
|
|
|
|
2017-07-24 12:51:00 +00:00
|
|
|
#[derive(Debug)]
|
2017-06-15 14:08:18 +00:00
|
|
|
pub enum Message {
|
|
|
|
Token(io::Result<Acquired>),
|
|
|
|
Done { success: bool },
|
2017-07-24 12:51:00 +00:00
|
|
|
WorkItem(WorkItem),
|
|
|
|
CheckErrorMessages,
|
2017-06-15 14:08:18 +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
|
|
|
|
2017-07-24 12:51:00 +00:00
|
|
|
|
2017-06-15 14:08:18 +00:00
|
|
|
pub struct Diagnostic {
|
|
|
|
msg: String,
|
|
|
|
code: Option<String>,
|
|
|
|
lvl: Level,
|
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
|
|
|
}
|
|
|
|
|
2017-07-24 12:51:00 +00:00
|
|
|
fn start_executing_work(sess: &Session,
|
2017-07-24 13:50:42 +00:00
|
|
|
total_work_item_count: usize,
|
2017-07-24 12:51:00 +00:00
|
|
|
shared_emitter: SharedEmitter,
|
|
|
|
trans_worker_send: Sender<Message>,
|
2017-07-24 13:50:42 +00:00
|
|
|
coordinator_send: Sender<Message>,
|
|
|
|
coordinator_receive: Receiver<Message>,
|
2017-07-24 12:51:00 +00:00
|
|
|
jobserver: Client,
|
|
|
|
exported_symbols: Arc<ExportedSymbols>)
|
2017-07-24 13:50:42 +00:00
|
|
|
-> thread::JoinHandle<()> {
|
2017-06-15 14:08:18 +00:00
|
|
|
// First up, convert our jobserver into a helper thread so we can use normal
|
|
|
|
// mpsc channels to manage our messages and such. Once we've got the helper
|
|
|
|
// thread then request `n-1` tokens because all of our work items are ready
|
|
|
|
// to go.
|
|
|
|
//
|
|
|
|
// Note that the `n-1` is here because we ourselves have a token (our
|
|
|
|
// process) and we'll use that token to execute at least one unit of work.
|
|
|
|
//
|
|
|
|
// After we've requested all these tokens then we'll, when we can, get
|
|
|
|
// tokens on `rx` above which will get managed in the main loop below.
|
2017-07-24 13:50:42 +00:00
|
|
|
let coordinator_send2 = coordinator_send.clone();
|
2017-06-15 14:08:18 +00:00
|
|
|
let helper = jobserver.into_helper_thread(move |token| {
|
2017-07-24 13:50:42 +00:00
|
|
|
drop(coordinator_send2.send(Message::Token(token)));
|
2017-06-15 14:08:18 +00:00
|
|
|
}).expect("failed to spawn helper thread");
|
2017-07-24 13:50:42 +00:00
|
|
|
for _ in 0..total_work_item_count - 1 {
|
2017-06-15 14:08:18 +00:00
|
|
|
helper.request_token();
|
|
|
|
}
|
|
|
|
|
2017-07-24 11:54:18 +00:00
|
|
|
let mut each_linked_rlib_for_lto = Vec::new();
|
|
|
|
drop(link::each_linked_rlib(sess, &mut |cnum, path| {
|
|
|
|
if link::ignored_for_lto(sess, cnum) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
|
|
|
}));
|
|
|
|
|
|
|
|
let cgcx = CodegenContext {
|
|
|
|
crate_types: sess.crate_types.borrow().clone(),
|
|
|
|
each_linked_rlib_for_lto: each_linked_rlib_for_lto,
|
|
|
|
lto: sess.lto(),
|
|
|
|
no_landing_pads: sess.no_landing_pads(),
|
2017-07-24 12:21:28 +00:00
|
|
|
opts: Arc::new(sess.opts.clone()),
|
2017-07-24 11:54:18 +00:00
|
|
|
time_passes: sess.time_passes(),
|
|
|
|
exported_symbols: exported_symbols,
|
|
|
|
plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
|
|
|
|
remark: sess.opts.cg.remark.clone(),
|
|
|
|
worker: 0,
|
|
|
|
incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
|
2017-07-24 13:50:42 +00:00
|
|
|
coordinator_send: coordinator_send,
|
2017-07-24 11:54:18 +00:00
|
|
|
diag_emitter: shared_emitter.clone(),
|
|
|
|
};
|
|
|
|
|
2017-06-15 14:08:18 +00:00
|
|
|
// This is the "main loop" of parallel work happening for parallel codegen.
|
|
|
|
// It's here that we manage parallelism, schedule work, and work with
|
|
|
|
// messages coming from clients.
|
|
|
|
//
|
|
|
|
// Our channel `rx` created above is a channel of messages coming from our
|
|
|
|
// various worker threads. This includes the jobserver helper thread above
|
|
|
|
// as well as the work we'll spawn off here. Each turn of this loop starts
|
|
|
|
// off by trying to spawn as much work as possible. After we've done that we
|
|
|
|
// then wait for an event and dispatch accordingly once the event is
|
|
|
|
// received. We're only done once all our work items have been drained and
|
|
|
|
// nothing is running, at which point we return back up the stack.
|
|
|
|
//
|
|
|
|
// ## Parallelism management
|
|
|
|
//
|
|
|
|
// It's worth also touching on the management of parallelism here. We don't
|
|
|
|
// want to just spawn a thread per work item because while that's optimal
|
|
|
|
// parallelism it may overload a system with too many threads or violate our
|
|
|
|
// configuration for the maximum amount of cpu to use for this process. To
|
|
|
|
// manage this we use the `jobserver` crate.
|
|
|
|
//
|
|
|
|
// Job servers are an artifact of GNU make and are used to manage
|
|
|
|
// parallelism between processes. A jobserver is a glorified IPC semaphore
|
|
|
|
// basically. Whenever we want to run some work we acquire the semaphore,
|
|
|
|
// and whenever we're done with that work we release the semaphore. In this
|
|
|
|
// manner we can ensure that the maximum number of parallel workers is
|
|
|
|
// capped at any one point in time.
|
|
|
|
//
|
|
|
|
// The jobserver protocol is a little unique, however. We, as a running
|
|
|
|
// process, already have an ephemeral token assigned to us. We're not going
|
|
|
|
// to be doing any productive work in this thread though so we're going to
|
|
|
|
// give this token to a worker thread (there's no actual token to give, this
|
|
|
|
// is just conceptually). As a result you'll see a few `+1` and `-1`
|
|
|
|
// instances below, and it's about working with this ephemeral token.
|
|
|
|
//
|
|
|
|
// To acquire tokens we have our `helper` thread above which is just in a
|
|
|
|
// loop acquiring tokens and sending them to us. We then store all tokens
|
|
|
|
// locally in a `tokens` vector once they're acquired. Currently we don't
|
|
|
|
// literally send a token to a worker thread to assist with management of
|
|
|
|
// our "ephemeral token".
|
|
|
|
//
|
|
|
|
// As a result, our "spawn as much work as possible" basically means that we
|
|
|
|
// fill up the `running` counter up to the limit of the `tokens` list.
|
|
|
|
// Whenever we get a new token this'll mean a new unit of work is spawned,
|
|
|
|
// and then whenever a unit of work finishes we relinquish a token, if we
|
|
|
|
// had one, to maybe get re-acquired later.
|
|
|
|
//
|
|
|
|
// Note that there's a race which may mean that we acquire more tokens than
|
|
|
|
// we originally anticipated. For example let's say we have 2 units of work.
|
|
|
|
// First we request one token from the helper thread and then we
|
|
|
|
// immediately spawn one unit of work with our ephemeral token after. We may
|
|
|
|
// then finish the first piece of work before the token is acquired, but we
|
|
|
|
// can continue to spawn the second piece of work with our ephemeral token.
|
|
|
|
// Before that work finishes, however, we may acquire a token. In that case
|
|
|
|
// we actually wastefully acquired the token, so we relinquish it back to
|
|
|
|
// the jobserver.
|
2017-07-24 11:54:18 +00:00
|
|
|
|
2017-07-24 12:21:28 +00:00
|
|
|
thread::spawn(move || {
|
2017-07-24 13:50:42 +00:00
|
|
|
let mut work_items_left = total_work_item_count;
|
|
|
|
let mut work_items = Vec::with_capacity(total_work_item_count);
|
2017-07-24 12:21:28 +00:00
|
|
|
let mut tokens = Vec::new();
|
|
|
|
let mut running = 0;
|
2017-07-24 13:50:42 +00:00
|
|
|
while work_items_left > 0 || running > 0 {
|
2017-06-15 14:08:18 +00:00
|
|
|
|
2017-07-24 12:21:28 +00:00
|
|
|
// Spin up what work we can, only doing this while we've got available
|
|
|
|
// parallelism slots and work left to spawn.
|
2017-07-24 13:50:42 +00:00
|
|
|
while work_items_left > 0 && running < tokens.len() + 1 {
|
|
|
|
if let Some(item) = work_items.pop() {
|
|
|
|
work_items_left -= 1;
|
|
|
|
let worker_index = work_items_left;
|
|
|
|
|
|
|
|
let cgcx = CodegenContext {
|
|
|
|
worker: worker_index,
|
|
|
|
.. cgcx.clone()
|
|
|
|
};
|
|
|
|
|
|
|
|
spawn_work(cgcx, item);
|
|
|
|
running += 1;
|
|
|
|
} else {
|
|
|
|
break
|
|
|
|
}
|
2017-06-15 14:08:18 +00:00
|
|
|
}
|
2017-07-24 12:21:28 +00:00
|
|
|
|
|
|
|
// Relinquish accidentally acquired extra tokens
|
|
|
|
tokens.truncate(running.saturating_sub(1));
|
|
|
|
|
2017-07-24 13:50:42 +00:00
|
|
|
match coordinator_receive.recv().unwrap() {
|
2017-07-24 12:21:28 +00:00
|
|
|
// Save the token locally and the next turn of the loop will use
|
|
|
|
// this to spawn a new unit of work, or it may get dropped
|
|
|
|
// immediately if we have no more work to spawn.
|
|
|
|
Message::Token(token) => {
|
|
|
|
tokens.push(token.expect("failed to acquire jobserver token"));
|
|
|
|
}
|
|
|
|
|
2017-07-24 13:50:42 +00:00
|
|
|
Message::WorkItem(work_item) => {
|
|
|
|
work_items.push(work_item);
|
|
|
|
}
|
|
|
|
|
2017-07-24 12:21:28 +00:00
|
|
|
// If a thread exits successfully then we drop a token associated
|
|
|
|
// with that worker and update our `running` count. We may later
|
|
|
|
// re-acquire a token to continue running more work. We may also not
|
|
|
|
// actually drop a token here if the worker was running with an
|
|
|
|
// "ephemeral token"
|
|
|
|
//
|
|
|
|
// Note that if the thread failed that means it panicked, so we
|
|
|
|
// abort immediately.
|
|
|
|
Message::Done { success: true } => {
|
|
|
|
drop(tokens.pop());
|
|
|
|
running -= 1;
|
2017-07-24 12:51:00 +00:00
|
|
|
trans_worker_send.send(Message::CheckErrorMessages).unwrap();
|
2017-07-24 12:21:28 +00:00
|
|
|
}
|
|
|
|
Message::Done { success: false } => {
|
|
|
|
shared_emitter.fatal("aborting due to worker thread panic".to_string());
|
2017-07-24 12:51:00 +00:00
|
|
|
trans_worker_send.send(Message::CheckErrorMessages).unwrap();
|
|
|
|
}
|
|
|
|
msg @ Message::CheckErrorMessages => {
|
|
|
|
bug!("unexpected message: {:?}", msg);
|
2017-07-24 12:21:28 +00:00
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
2017-06-15 14:08:18 +00:00
|
|
|
}
|
2017-07-24 12:51:00 +00:00
|
|
|
})
|
2017-06-15 14:08:18 +00:00
|
|
|
}
|
|
|
|
|
2017-07-24 12:21:28 +00:00
|
|
|
fn spawn_work(cgcx: CodegenContext, work: WorkItem) {
|
2017-06-15 14:08:18 +00:00
|
|
|
let depth = time_depth();
|
|
|
|
|
2017-07-24 12:21:28 +00:00
|
|
|
thread::spawn(move || {
|
2017-06-15 14:08:18 +00:00
|
|
|
set_time_depth(depth);
|
|
|
|
|
|
|
|
// Set up a destructor which will fire off a message that we're done as
|
|
|
|
// we exit.
|
|
|
|
struct Bomb {
|
2017-07-24 11:54:18 +00:00
|
|
|
coordinator_send: Sender<Message>,
|
2017-06-15 14:08:18 +00:00
|
|
|
success: bool,
|
|
|
|
}
|
|
|
|
impl Drop for Bomb {
|
|
|
|
fn drop(&mut self) {
|
2017-07-24 11:54:18 +00:00
|
|
|
drop(self.coordinator_send.send(Message::Done { success: self.success }));
|
2017-06-15 14:08:18 +00:00
|
|
|
}
|
|
|
|
}
|
2017-07-24 11:54:18 +00:00
|
|
|
|
2017-06-15 14:08:18 +00:00
|
|
|
let mut bomb = Bomb {
|
2017-07-24 11:54:18 +00:00
|
|
|
coordinator_send: cgcx.coordinator_send.clone(),
|
2017-06-15 14:08:18 +00:00
|
|
|
success: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Execute the work itself, and if it finishes successfully then flag
|
|
|
|
// ourselves as a success as well.
|
|
|
|
//
|
|
|
|
// Note that we ignore the result coming out of `execute_work_item`
|
|
|
|
// which will tell us if the worker failed with a `FatalError`. If that
|
|
|
|
// has happened, however, then a diagnostic was sent off to the main
|
|
|
|
// thread, along with an `AbortIfErrors` message. In that case the main
|
|
|
|
// thread is already exiting anyway most likely.
|
|
|
|
//
|
|
|
|
// In any case, there's no need for us to take further action here, so
|
|
|
|
// we just ignore the result and then send off our message saying that
|
|
|
|
// we're done, which if `execute_work_item` failed is unlikely to be
|
|
|
|
// seen by the main thread, but hey we might as well try anyway.
|
|
|
|
drop(execute_work_item(&cgcx, work).is_err());
|
|
|
|
bomb.success = true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-08-11 17:33:58 +00:00
|
|
|
pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
|
2016-06-28 20:29:58 +00:00
|
|
|
let (pname, mut cmd, _) = get_linker(sess);
|
2014-08-11 17:33:58 +00:00
|
|
|
|
2016-12-19 03:25:46 +00:00
|
|
|
for arg in &sess.target.target.options.asm_args {
|
|
|
|
cmd.arg(arg);
|
|
|
|
}
|
|
|
|
|
2015-09-30 17:08:37 +00:00
|
|
|
cmd.arg("-c").arg("-o").arg(&outputs.path(OutputType::Object))
|
2016-05-14 00:48:32 +00:00
|
|
|
.arg(&outputs.temp_path(OutputType::Assembly, None));
|
2015-02-27 05:00:43 +00:00
|
|
|
debug!("{:?}", cmd);
|
2014-08-11 17:33:58 +00:00
|
|
|
|
|
|
|
match cmd.output() {
|
|
|
|
Ok(prog) => {
|
|
|
|
if !prog.status.success() {
|
2015-02-27 05:00:43 +00:00
|
|
|
let mut note = prog.stderr.clone();
|
2015-12-03 01:31:49 +00:00
|
|
|
note.extend_from_slice(&prog.stdout);
|
2015-12-20 21:00:43 +00:00
|
|
|
|
|
|
|
sess.struct_err(&format!("linking with `{}` failed: {}",
|
|
|
|
pname,
|
|
|
|
prog.status))
|
|
|
|
.note(&format!("{:?}", &cmd))
|
|
|
|
.note(str::from_utf8(¬e[..]).unwrap())
|
|
|
|
.emit();
|
2014-08-11 17:33:58 +00:00
|
|
|
sess.abort_if_errors();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(e) => {
|
2015-06-30 06:16:24 +00:00
|
|
|
sess.err(&format!("could not exec the linker `{}`: {}", pname, e));
|
2014-08-11 17:33:58 +00:00
|
|
|
sess.abort_if_errors();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-22 23:22:51 +00:00
|
|
|
pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
|
|
|
|
config: &ModuleConfig,
|
|
|
|
f: &mut FnMut(llvm::PassManagerBuilderRef)) {
|
2014-08-11 17:33:58 +00:00
|
|
|
// Create the PassManagerBuilder for LLVM. We configure it with
|
|
|
|
// reasonable defaults and prepare it to actually populate the pass
|
|
|
|
// manager.
|
|
|
|
let builder = llvm::LLVMPassManagerBuilderCreate();
|
2016-08-01 21:16:16 +00:00
|
|
|
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
|
2016-03-27 19:42:47 +00:00
|
|
|
let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
|
2015-11-20 00:07:09 +00:00
|
|
|
let inline_threshold = config.inline_threshold;
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
|
2016-03-27 19:42:47 +00:00
|
|
|
llvm::LLVMRustConfigurePassManagerBuilder(builder, opt_level,
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
config.merge_functions,
|
|
|
|
config.vectorize_slp,
|
|
|
|
config.vectorize_loop);
|
2016-03-27 19:42:47 +00:00
|
|
|
llvm::LLVMPassManagerBuilderSetSizeLevel(builder, opt_size as u32);
|
|
|
|
|
|
|
|
if opt_size != llvm::CodeGenOptSizeNone {
|
|
|
|
llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(builder, 1);
|
|
|
|
}
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
|
|
|
|
llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
|
|
|
|
|
|
|
|
// Here we match what clang does (kinda). For O0 we only inline
|
|
|
|
// always-inline functions (but don't add lifetime intrinsics), at O1 we
|
|
|
|
// inline with lifetime intrinsics, and O2+ we add an inliner with a
|
|
|
|
// thresholds copied from clang.
|
2016-03-27 19:42:47 +00:00
|
|
|
match (opt_level, opt_size, inline_threshold) {
|
2016-08-26 16:23:42 +00:00
|
|
|
(.., Some(t)) => {
|
2015-11-20 00:07:09 +00:00
|
|
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
|
|
|
|
}
|
2016-08-26 16:23:42 +00:00
|
|
|
(llvm::CodeGenOptLevel::Aggressive, ..) => {
|
2016-03-27 19:42:47 +00:00
|
|
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
|
|
|
|
}
|
|
|
|
(_, llvm::CodeGenOptSizeDefault, _) => {
|
|
|
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 75);
|
|
|
|
}
|
|
|
|
(_, llvm::CodeGenOptSizeAggressive, _) => {
|
|
|
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25);
|
|
|
|
}
|
2016-08-26 16:23:42 +00:00
|
|
|
(llvm::CodeGenOptLevel::None, ..) => {
|
2014-08-11 17:33:58 +00:00
|
|
|
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
|
|
|
|
}
|
2016-08-26 16:23:42 +00:00
|
|
|
(llvm::CodeGenOptLevel::Less, ..) => {
|
2014-08-11 17:33:58 +00:00
|
|
|
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
|
|
|
|
}
|
2016-08-26 16:23:42 +00:00
|
|
|
(llvm::CodeGenOptLevel::Default, ..) => {
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
2016-08-26 16:23:42 +00:00
|
|
|
(llvm::CodeGenOptLevel::Other, ..) => {
|
2016-08-01 21:16:16 +00:00
|
|
|
bug!("CodeGenOptLevel::Other selected")
|
|
|
|
}
|
2014-08-11 17:33:58 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 23:22:51 +00:00
|
|
|
f(builder);
|
2014-08-11 17:33:58 +00:00
|
|
|
llvm::LLVMPassManagerBuilderDispose(builder);
|
|
|
|
}
|
2017-07-21 15:15:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
enum SharedEmitterMessage {
|
|
|
|
Diagnostic(Diagnostic),
|
|
|
|
InlineAsmError(u32, String),
|
|
|
|
AbortIfErrors,
|
|
|
|
Fatal(String),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct SharedEmitter {
|
|
|
|
sender: Sender<SharedEmitterMessage>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SharedEmitterMain {
|
|
|
|
receiver: Receiver<SharedEmitterMessage>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SharedEmitter {
|
|
|
|
pub fn new() -> (SharedEmitter, SharedEmitterMain) {
|
|
|
|
let (sender, receiver) = channel();
|
|
|
|
|
|
|
|
(SharedEmitter { sender }, SharedEmitterMain { receiver })
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inline_asm_error(&self, cookie: u32, msg: String) {
|
|
|
|
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg)));
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fatal(&self, msg: String) {
|
|
|
|
drop(self.sender.send(SharedEmitterMessage::Fatal(msg)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Emitter for SharedEmitter {
|
|
|
|
fn emit(&mut self, db: &DiagnosticBuilder) {
|
|
|
|
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
|
|
|
msg: db.message(),
|
|
|
|
code: db.code.clone(),
|
|
|
|
lvl: db.level,
|
|
|
|
})));
|
|
|
|
for child in &db.children {
|
|
|
|
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
|
|
|
msg: child.message(),
|
|
|
|
code: None,
|
|
|
|
lvl: child.level,
|
|
|
|
})));
|
|
|
|
}
|
|
|
|
drop(self.sender.send(SharedEmitterMessage::AbortIfErrors));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SharedEmitterMain {
|
|
|
|
pub fn check(&self, sess: &Session) {
|
|
|
|
loop {
|
|
|
|
match self.receiver.try_recv() {
|
|
|
|
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
|
|
|
|
let handler = sess.diagnostic();
|
|
|
|
match diag.code {
|
|
|
|
Some(ref code) => {
|
|
|
|
handler.emit_with_code(&MultiSpan::new(),
|
|
|
|
&diag.msg,
|
|
|
|
&code,
|
|
|
|
diag.lvl);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
handler.emit(&MultiSpan::new(),
|
|
|
|
&diag.msg,
|
|
|
|
diag.lvl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => {
|
|
|
|
match Mark::from_u32(cookie).expn_info() {
|
|
|
|
Some(ei) => sess.span_err(ei.call_site, &msg),
|
|
|
|
None => sess.err(&msg),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(SharedEmitterMessage::AbortIfErrors) => {
|
|
|
|
sess.abort_if_errors();
|
|
|
|
}
|
|
|
|
Ok(SharedEmitterMessage::Fatal(msg)) => {
|
|
|
|
sess.fatal(&msg);
|
|
|
|
}
|
|
|
|
Err(_) => {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|