Rename trans to codegen everywhere.
This commit is contained in:
parent
e3150564f8
commit
b63d7e2b1c
264 changed files with 1547 additions and 1548 deletions
|
@ -1896,6 +1896,52 @@ dependencies = [
|
||||||
"syntax_pos 0.0.0",
|
"syntax_pos 0.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_codegen_llvm"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc 0.0.0",
|
||||||
|
"rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc_allocator 0.0.0",
|
||||||
|
"rustc_apfloat 0.0.0",
|
||||||
|
"rustc_codegen_utils 0.0.0",
|
||||||
|
"rustc_data_structures 0.0.0",
|
||||||
|
"rustc_errors 0.0.0",
|
||||||
|
"rustc_incremental 0.0.0",
|
||||||
|
"rustc_llvm 0.0.0",
|
||||||
|
"rustc_mir 0.0.0",
|
||||||
|
"rustc_platform_intrinsics 0.0.0",
|
||||||
|
"rustc_target 0.0.0",
|
||||||
|
"serialize 0.0.0",
|
||||||
|
"syntax 0.0.0",
|
||||||
|
"syntax_pos 0.0.0",
|
||||||
|
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_codegen_utils"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc 0.0.0",
|
||||||
|
"rustc_data_structures 0.0.0",
|
||||||
|
"rustc_incremental 0.0.0",
|
||||||
|
"rustc_mir 0.0.0",
|
||||||
|
"rustc_target 0.0.0",
|
||||||
|
"syntax 0.0.0",
|
||||||
|
"syntax_pos 0.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_cratesio_shim"
|
name = "rustc_cratesio_shim"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -1932,6 +1978,7 @@ dependencies = [
|
||||||
"rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc_allocator 0.0.0",
|
"rustc_allocator 0.0.0",
|
||||||
"rustc_borrowck 0.0.0",
|
"rustc_borrowck 0.0.0",
|
||||||
|
"rustc_codegen_utils 0.0.0",
|
||||||
"rustc_data_structures 0.0.0",
|
"rustc_data_structures 0.0.0",
|
||||||
"rustc_errors 0.0.0",
|
"rustc_errors 0.0.0",
|
||||||
"rustc_incremental 0.0.0",
|
"rustc_incremental 0.0.0",
|
||||||
|
@ -1945,7 +1992,6 @@ dependencies = [
|
||||||
"rustc_save_analysis 0.0.0",
|
"rustc_save_analysis 0.0.0",
|
||||||
"rustc_target 0.0.0",
|
"rustc_target 0.0.0",
|
||||||
"rustc_traits 0.0.0",
|
"rustc_traits 0.0.0",
|
||||||
"rustc_trans_utils 0.0.0",
|
|
||||||
"rustc_typeck 0.0.0",
|
"rustc_typeck 0.0.0",
|
||||||
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serialize 0.0.0",
|
"serialize 0.0.0",
|
||||||
|
@ -2155,52 +2201,6 @@ dependencies = [
|
||||||
"syntax_pos 0.0.0",
|
"syntax_pos 0.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc_trans"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rustc 0.0.0",
|
|
||||||
"rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rustc_allocator 0.0.0",
|
|
||||||
"rustc_apfloat 0.0.0",
|
|
||||||
"rustc_data_structures 0.0.0",
|
|
||||||
"rustc_errors 0.0.0",
|
|
||||||
"rustc_incremental 0.0.0",
|
|
||||||
"rustc_llvm 0.0.0",
|
|
||||||
"rustc_mir 0.0.0",
|
|
||||||
"rustc_platform_intrinsics 0.0.0",
|
|
||||||
"rustc_target 0.0.0",
|
|
||||||
"rustc_trans_utils 0.0.0",
|
|
||||||
"serialize 0.0.0",
|
|
||||||
"syntax 0.0.0",
|
|
||||||
"syntax_pos 0.0.0",
|
|
||||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc_trans_utils"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rustc 0.0.0",
|
|
||||||
"rustc_data_structures 0.0.0",
|
|
||||||
"rustc_incremental 0.0.0",
|
|
||||||
"rustc_mir 0.0.0",
|
|
||||||
"rustc_target 0.0.0",
|
|
||||||
"syntax 0.0.0",
|
|
||||||
"syntax_pos 0.0.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_tsan"
|
name = "rustc_tsan"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
|
|
@ -4,7 +4,7 @@ members = [
|
||||||
"rustc",
|
"rustc",
|
||||||
"libstd",
|
"libstd",
|
||||||
"libtest",
|
"libtest",
|
||||||
"librustc_trans",
|
"librustc_codegen_llvm",
|
||||||
"tools/cargotest",
|
"tools/cargotest",
|
||||||
"tools/clippy",
|
"tools/clippy",
|
||||||
"tools/compiletest",
|
"tools/compiletest",
|
||||||
|
|
|
@ -844,7 +844,7 @@ impl<'a> Builder<'a> {
|
||||||
// default via `-ldylib=winapi_foo`. That is, they're linked with the
|
// default via `-ldylib=winapi_foo`. That is, they're linked with the
|
||||||
// `dylib` type with a `winapi_` prefix (so the winapi ones don't
|
// `dylib` type with a `winapi_` prefix (so the winapi ones don't
|
||||||
// conflict with the system MinGW ones). This consequently means that
|
// conflict with the system MinGW ones). This consequently means that
|
||||||
// the binaries we ship of things like rustc_trans (aka the rustc_trans
|
// the binaries we ship of things like rustc_codegen_llvm (aka the rustc_codegen_llvm
|
||||||
// DLL) when linked against *again*, for example with procedural macros
|
// DLL) when linked against *again*, for example with procedural macros
|
||||||
// or plugins, will trigger the propagation logic of `-ldylib`, passing
|
// or plugins, will trigger the propagation logic of `-ldylib`, passing
|
||||||
// `-lwinapi_foo` to the linker again. This isn't actually available in
|
// `-lwinapi_foo` to the linker again. This isn't actually available in
|
||||||
|
|
|
@ -118,7 +118,7 @@ impl Step for CodegenBackend {
|
||||||
const DEFAULT: bool = true;
|
const DEFAULT: bool = true;
|
||||||
|
|
||||||
fn should_run(run: ShouldRun) -> ShouldRun {
|
fn should_run(run: ShouldRun) -> ShouldRun {
|
||||||
run.all_krates("rustc_trans")
|
run.all_krates("rustc_codegen_llvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_run(run: RunConfig) {
|
fn make_run(run: RunConfig) {
|
||||||
|
@ -139,12 +139,12 @@ impl Step for CodegenBackend {
|
||||||
|
|
||||||
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
|
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
|
||||||
let features = builder.rustc_features().to_string();
|
let features = builder.rustc_features().to_string();
|
||||||
cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_trans/Cargo.toml"));
|
cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
|
||||||
rustc_cargo_env(builder, &mut cargo);
|
rustc_cargo_env(builder, &mut cargo);
|
||||||
|
|
||||||
// We won't build LLVM if it's not available, as it shouldn't affect `check`.
|
// We won't build LLVM if it's not available, as it shouldn't affect `check`.
|
||||||
|
|
||||||
let _folder = builder.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
|
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
|
||||||
run_cargo(builder,
|
run_cargo(builder,
|
||||||
cargo.arg("--features").arg(features),
|
cargo.arg("--features").arg(features),
|
||||||
&codegen_backend_stamp(builder, compiler, target, backend),
|
&codegen_backend_stamp(builder, compiler, target, backend),
|
||||||
|
@ -259,14 +259,14 @@ pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<St
|
||||||
builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp")
|
builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cargo's output path for librustc_trans in a given stage, compiled by a particular
|
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
|
||||||
/// compiler for the specified target and backend.
|
/// compiler for the specified target and backend.
|
||||||
fn codegen_backend_stamp(builder: &Builder,
|
fn codegen_backend_stamp(builder: &Builder,
|
||||||
compiler: Compiler,
|
compiler: Compiler,
|
||||||
target: Interned<String>,
|
target: Interned<String>,
|
||||||
backend: Interned<String>) -> PathBuf {
|
backend: Interned<String>) -> PathBuf {
|
||||||
builder.cargo_out(compiler, Mode::Librustc, target)
|
builder.cargo_out(compiler, Mode::Librustc, target)
|
||||||
.join(format!(".librustc_trans-{}-check.stamp", backend))
|
.join(format!(".librustc_codegen_llvm-{}-check.stamp", backend))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cargo's output path for rustdoc in a given stage, compiled by a particular
|
/// Cargo's output path for rustdoc in a given stage, compiled by a particular
|
||||||
|
|
|
@ -603,7 +603,7 @@ impl Step for CodegenBackend {
|
||||||
const DEFAULT: bool = true;
|
const DEFAULT: bool = true;
|
||||||
|
|
||||||
fn should_run(run: ShouldRun) -> ShouldRun {
|
fn should_run(run: ShouldRun) -> ShouldRun {
|
||||||
run.all_krates("rustc_trans")
|
run.all_krates("rustc_codegen_llvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_run(run: RunConfig) {
|
fn make_run(run: RunConfig) {
|
||||||
|
@ -637,7 +637,7 @@ impl Step for CodegenBackend {
|
||||||
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
|
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
|
||||||
let mut features = builder.rustc_features().to_string();
|
let mut features = builder.rustc_features().to_string();
|
||||||
cargo.arg("--manifest-path")
|
cargo.arg("--manifest-path")
|
||||||
.arg(builder.src.join("src/librustc_trans/Cargo.toml"));
|
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
|
||||||
rustc_cargo_env(builder, &mut cargo);
|
rustc_cargo_env(builder, &mut cargo);
|
||||||
|
|
||||||
features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
|
features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
|
||||||
|
@ -645,7 +645,7 @@ impl Step for CodegenBackend {
|
||||||
let tmp_stamp = builder.cargo_out(compiler, Mode::Librustc, target)
|
let tmp_stamp = builder.cargo_out(compiler, Mode::Librustc, target)
|
||||||
.join(".tmp.stamp");
|
.join(".tmp.stamp");
|
||||||
|
|
||||||
let _folder = builder.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
|
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
|
||||||
let files = run_cargo(builder,
|
let files = run_cargo(builder,
|
||||||
cargo.arg("--features").arg(features),
|
cargo.arg("--features").arg(features),
|
||||||
&tmp_stamp,
|
&tmp_stamp,
|
||||||
|
@ -656,7 +656,7 @@ impl Step for CodegenBackend {
|
||||||
let mut files = files.into_iter()
|
let mut files = files.into_iter()
|
||||||
.filter(|f| {
|
.filter(|f| {
|
||||||
let filename = f.file_name().unwrap().to_str().unwrap();
|
let filename = f.file_name().unwrap().to_str().unwrap();
|
||||||
is_dylib(filename) && filename.contains("rustc_trans-")
|
is_dylib(filename) && filename.contains("rustc_codegen_llvm-")
|
||||||
});
|
});
|
||||||
let codegen_backend = match files.next() {
|
let codegen_backend = match files.next() {
|
||||||
Some(f) => f,
|
Some(f) => f,
|
||||||
|
@ -697,7 +697,7 @@ pub fn build_codegen_backend(builder: &Builder,
|
||||||
compiler.stage, &compiler.host, target, backend));
|
compiler.stage, &compiler.host, target, backend));
|
||||||
|
|
||||||
// Pass down configuration from the LLVM build into the build of
|
// Pass down configuration from the LLVM build into the build of
|
||||||
// librustc_llvm and librustc_trans.
|
// librustc_llvm and librustc_codegen_llvm.
|
||||||
if builder.is_rust_llvm(target) {
|
if builder.is_rust_llvm(target) {
|
||||||
cargo.env("LLVM_RUSTLLVM", "1");
|
cargo.env("LLVM_RUSTLLVM", "1");
|
||||||
}
|
}
|
||||||
|
@ -762,7 +762,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
|
||||||
t!(t!(File::open(&stamp)).read_to_string(&mut dylib));
|
t!(t!(File::open(&stamp)).read_to_string(&mut dylib));
|
||||||
let file = Path::new(&dylib);
|
let file = Path::new(&dylib);
|
||||||
let filename = file.file_name().unwrap().to_str().unwrap();
|
let filename = file.file_name().unwrap().to_str().unwrap();
|
||||||
// change `librustc_trans-xxxxxx.so` to `librustc_trans-llvm.so`
|
// change `librustc_codegen_llvm-xxxxxx.so` to `librustc_codegen_llvm-llvm.so`
|
||||||
let target_filename = {
|
let target_filename = {
|
||||||
let dash = filename.find("-").unwrap();
|
let dash = filename.find("-").unwrap();
|
||||||
let dot = filename.find(".").unwrap();
|
let dot = filename.find(".").unwrap();
|
||||||
|
@ -808,14 +808,14 @@ pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<St
|
||||||
builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
|
builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cargo's output path for librustc_trans in a given stage, compiled by a particular
|
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
|
||||||
/// compiler for the specified target and backend.
|
/// compiler for the specified target and backend.
|
||||||
fn codegen_backend_stamp(builder: &Builder,
|
fn codegen_backend_stamp(builder: &Builder,
|
||||||
compiler: Compiler,
|
compiler: Compiler,
|
||||||
target: Interned<String>,
|
target: Interned<String>,
|
||||||
backend: Interned<String>) -> PathBuf {
|
backend: Interned<String>) -> PathBuf {
|
||||||
builder.cargo_out(compiler, Mode::Librustc, target)
|
builder.cargo_out(compiler, Mode::Librustc, target)
|
||||||
.join(format!(".librustc_trans-{}.stamp", backend))
|
.join(format!(".librustc_codegen_llvm-{}.stamp", backend))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compiler_file(builder: &Builder,
|
pub fn compiler_file(builder: &Builder,
|
||||||
|
|
|
@ -69,7 +69,7 @@ for details on how to format and write long error codes.
|
||||||
[librustc_passes](https://github.com/rust-lang/rust/blob/master/src/librustc_passes/diagnostics.rs),
|
[librustc_passes](https://github.com/rust-lang/rust/blob/master/src/librustc_passes/diagnostics.rs),
|
||||||
[librustc_privacy](https://github.com/rust-lang/rust/blob/master/src/librustc_privacy/diagnostics.rs),
|
[librustc_privacy](https://github.com/rust-lang/rust/blob/master/src/librustc_privacy/diagnostics.rs),
|
||||||
[librustc_resolve](https://github.com/rust-lang/rust/blob/master/src/librustc_resolve/diagnostics.rs),
|
[librustc_resolve](https://github.com/rust-lang/rust/blob/master/src/librustc_resolve/diagnostics.rs),
|
||||||
[librustc_trans](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/diagnostics.rs),
|
[librustc_codegen_llvm](https://github.com/rust-lang/rust/blob/master/src/librustc_codegen_llvm/diagnostics.rs),
|
||||||
[librustc_plugin](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/diagnostics.rs),
|
[librustc_plugin](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/diagnostics.rs),
|
||||||
[librustc_typeck](https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/diagnostics.rs).
|
[librustc_typeck](https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/diagnostics.rs).
|
||||||
* Explanations have full markdown support. Use it, especially to highlight
|
* Explanations have full markdown support. Use it, especially to highlight
|
||||||
|
|
|
@ -134,7 +134,7 @@ unsafe impl Alloc for Global {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The allocator for unique pointers.
|
/// The allocator for unique pointers.
|
||||||
// This function must not unwind. If it does, MIR trans will fail.
|
// This function must not unwind. If it does, MIR codegen will fail.
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[lang = "exchange_malloc"]
|
#[lang = "exchange_malloc"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
//! rustc compiler intrinsics.
|
//! rustc compiler intrinsics.
|
||||||
//!
|
//!
|
||||||
//! The corresponding definitions are in librustc_trans/intrinsic.rs.
|
//! The corresponding definitions are in librustc_codegen_llvm/intrinsic.rs.
|
||||||
//!
|
//!
|
||||||
//! # Volatiles
|
//! # Volatiles
|
||||||
//!
|
//!
|
||||||
|
|
|
@ -35,13 +35,13 @@ byteorder = { version = "1.1", features = ["i128"]}
|
||||||
# rlib/dylib pair but all crates.io crates tend to just be rlibs. This means
|
# rlib/dylib pair but all crates.io crates tend to just be rlibs. This means
|
||||||
# we've got a problem for dependency graphs that look like:
|
# we've got a problem for dependency graphs that look like:
|
||||||
#
|
#
|
||||||
# foo - rustc_trans
|
# foo - rustc_codegen_llvm
|
||||||
# / \
|
# / \
|
||||||
# rustc ---- rustc_driver
|
# rustc ---- rustc_driver
|
||||||
# \ /
|
# \ /
|
||||||
# foo - rustc_metadata
|
# foo - rustc_metadata
|
||||||
#
|
#
|
||||||
# Here the crate `foo` is linked into the `rustc_trans` and the
|
# Here the crate `foo` is linked into the `rustc_codegen_llvm` and the
|
||||||
# `rustc_metadata` dylibs, meaning we've got duplicate copies! When we then
|
# `rustc_metadata` dylibs, meaning we've got duplicate copies! When we then
|
||||||
# go to link `rustc_driver` the compiler notices this and gives us a compiler
|
# go to link `rustc_driver` the compiler notices this and gives us a compiler
|
||||||
# error.
|
# error.
|
||||||
|
@ -49,7 +49,7 @@ byteorder = { version = "1.1", features = ["i128"]}
|
||||||
# To work around this problem we just add these crates.io dependencies to the
|
# To work around this problem we just add these crates.io dependencies to the
|
||||||
# `rustc` crate which is a shared dependency above. That way the crate `foo`
|
# `rustc` crate which is a shared dependency above. That way the crate `foo`
|
||||||
# shows up in the dylib for the `rustc` crate, deduplicating it and allowing
|
# shows up in the dylib for the `rustc` crate, deduplicating it and allowing
|
||||||
# crates like `rustc_trans` to use `foo` *through* the `rustc` crate.
|
# crates like `rustc_codegen_llvm` to use `foo` *through* the `rustc` crate.
|
||||||
#
|
#
|
||||||
# tl;dr; this is not needed to get `rustc` to compile, but if you remove it then
|
# tl;dr; this is not needed to get `rustc` to compile, but if you remove it then
|
||||||
# later crate stop compiling. If you can remove this and everything
|
# later crate stop compiling. If you can remove this and everything
|
||||||
|
|
|
@ -452,13 +452,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||||
// The CFG for match expression is quite complex, so no ASCII
|
// The CFG for match expression is quite complex, so no ASCII
|
||||||
// art for it (yet).
|
// art for it (yet).
|
||||||
//
|
//
|
||||||
// The CFG generated below matches roughly what trans puts
|
// The CFG generated below matches roughly what MIR contains.
|
||||||
// out. Each pattern and guard is visited in parallel, with
|
// Each pattern and guard is visited in parallel, with
|
||||||
// arms containing multiple patterns generating multiple nodes
|
// arms containing multiple patterns generating multiple nodes
|
||||||
// for the same guard expression. The guard expressions chain
|
// for the same guard expression. The guard expressions chain
|
||||||
// into each other from top to bottom, with a specific
|
// into each other from top to bottom, with a specific
|
||||||
// exception to allow some additional valid programs
|
// exception to allow some additional valid programs
|
||||||
// (explained below). Trans differs slightly in that the
|
// (explained below). MIR differs slightly in that the
|
||||||
// pattern matching may continue after a guard but the visible
|
// pattern matching may continue after a guard but the visible
|
||||||
// behaviour should be the same.
|
// behaviour should be the same.
|
||||||
//
|
//
|
||||||
|
|
|
@ -565,7 +565,7 @@ define_dep_nodes!( <'tcx>
|
||||||
[] IsUnreachableLocalDefinition(DefId),
|
[] IsUnreachableLocalDefinition(DefId),
|
||||||
[] IsMirAvailable(DefId),
|
[] IsMirAvailable(DefId),
|
||||||
[] ItemAttrs(DefId),
|
[] ItemAttrs(DefId),
|
||||||
[] TransFnAttrs(DefId),
|
[] CodegenFnAttrs(DefId),
|
||||||
[] FnArgNames(DefId),
|
[] FnArgNames(DefId),
|
||||||
[] RenderedConst(DefId),
|
[] RenderedConst(DefId),
|
||||||
[] DylibDepFormats(CrateNum),
|
[] DylibDepFormats(CrateNum),
|
||||||
|
@ -637,8 +637,8 @@ define_dep_nodes!( <'tcx>
|
||||||
[eval_always] AllTraits,
|
[eval_always] AllTraits,
|
||||||
[input] AllCrateNums,
|
[input] AllCrateNums,
|
||||||
[] ExportedSymbols(CrateNum),
|
[] ExportedSymbols(CrateNum),
|
||||||
[eval_always] CollectAndPartitionTranslationItems,
|
[eval_always] CollectAndPartitionMonoItems,
|
||||||
[] IsTranslatedItem(DefId),
|
[] IsCodegenedItem(DefId),
|
||||||
[] CodegenUnit(InternedString),
|
[] CodegenUnit(InternedString),
|
||||||
[] CompileCodegenUnit(InternedString),
|
[] CompileCodegenUnit(InternedString),
|
||||||
[input] OutputFilenames,
|
[input] OutputFilenames,
|
||||||
|
|
|
@ -856,10 +856,10 @@ impl DepGraph {
|
||||||
/// each partition. In the first run, we create partitions based on
|
/// each partition. In the first run, we create partitions based on
|
||||||
/// the symbols that need to be compiled. For each partition P, we
|
/// the symbols that need to be compiled. For each partition P, we
|
||||||
/// hash the symbols in P and create a `WorkProduct` record associated
|
/// hash the symbols in P and create a `WorkProduct` record associated
|
||||||
/// with `DepNode::TransPartition(P)`; the hash is the set of symbols
|
/// with `DepNode::CodegenUnit(P)`; the hash is the set of symbols
|
||||||
/// in P.
|
/// in P.
|
||||||
///
|
///
|
||||||
/// The next time we compile, if the `DepNode::TransPartition(P)` is
|
/// The next time we compile, if the `DepNode::CodegenUnit(P)` is
|
||||||
/// judged to be clean (which means none of the things we read to
|
/// judged to be clean (which means none of the things we read to
|
||||||
/// generate the partition were found to be dirty), it will be loaded
|
/// generate the partition were found to be dirty), it will be loaded
|
||||||
/// into previous work products. We will then regenerate the set of
|
/// into previous work products. We will then regenerate the set of
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
|
||||||
/// Check any attribute.
|
/// Check any attribute.
|
||||||
fn check_attributes(&self, item: &hir::Item, target: Target) {
|
fn check_attributes(&self, item: &hir::Item, target: Target) {
|
||||||
if target == Target::Fn {
|
if target == Target::Fn {
|
||||||
self.tcx.trans_fn_attrs(self.tcx.hir.local_def_id(item.id));
|
self.tcx.codegen_fn_attrs(self.tcx.hir.local_def_id(item.id));
|
||||||
} else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) {
|
} else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) {
|
||||||
self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
|
self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
|
||||||
.span_label(item.span, "not a function")
|
.span_label(item.span, "not a function")
|
||||||
|
|
|
@ -2244,8 +2244,8 @@ pub fn provide(providers: &mut Providers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Hash)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Hash)]
|
||||||
pub struct TransFnAttrs {
|
pub struct CodegenFnAttrs {
|
||||||
pub flags: TransFnAttrFlags,
|
pub flags: CodegenFnAttrFlags,
|
||||||
pub inline: InlineAttr,
|
pub inline: InlineAttr,
|
||||||
pub export_name: Option<Symbol>,
|
pub export_name: Option<Symbol>,
|
||||||
pub target_features: Vec<Symbol>,
|
pub target_features: Vec<Symbol>,
|
||||||
|
@ -2254,7 +2254,7 @@ pub struct TransFnAttrs {
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct TransFnAttrFlags: u8 {
|
pub struct CodegenFnAttrFlags: u8 {
|
||||||
const COLD = 0b0000_0001;
|
const COLD = 0b0000_0001;
|
||||||
const ALLOCATOR = 0b0000_0010;
|
const ALLOCATOR = 0b0000_0010;
|
||||||
const UNWIND = 0b0000_0100;
|
const UNWIND = 0b0000_0100;
|
||||||
|
@ -2266,10 +2266,10 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TransFnAttrs {
|
impl CodegenFnAttrs {
|
||||||
pub fn new() -> TransFnAttrs {
|
pub fn new() -> CodegenFnAttrs {
|
||||||
TransFnAttrs {
|
CodegenFnAttrs {
|
||||||
flags: TransFnAttrFlags::empty(),
|
flags: CodegenFnAttrFlags::empty(),
|
||||||
inline: InlineAttr::None,
|
inline: InlineAttr::None,
|
||||||
export_name: None,
|
export_name: None,
|
||||||
target_features: vec![],
|
target_features: vec![],
|
||||||
|
@ -2287,7 +2287,6 @@ impl TransFnAttrs {
|
||||||
|
|
||||||
/// True if `#[no_mangle]` or `#[export_name(...)]` is present.
|
/// True if `#[no_mangle]` or `#[export_name(...)]` is present.
|
||||||
pub fn contains_extern_indicator(&self) -> bool {
|
pub fn contains_extern_indicator(&self) -> bool {
|
||||||
self.flags.contains(TransFnAttrFlags::NO_MANGLE) || self.export_name.is_some()
|
self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) || self.export_name.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1155,12 +1155,12 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::TraitCandidate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrs
|
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::CodegenFnAttrs
|
||||||
{
|
{
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
hcx: &mut StableHashingContext<'hir>,
|
hcx: &mut StableHashingContext<'hir>,
|
||||||
hasher: &mut StableHasher<W>) {
|
hasher: &mut StableHasher<W>) {
|
||||||
let hir::TransFnAttrs {
|
let hir::CodegenFnAttrs {
|
||||||
flags,
|
flags,
|
||||||
inline,
|
inline,
|
||||||
export_name,
|
export_name,
|
||||||
|
@ -1176,7 +1176,7 @@ impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrFlags
|
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::CodegenFnAttrFlags
|
||||||
{
|
{
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
hcx: &mut StableHashingContext<'hir>,
|
hcx: &mut StableHashingContext<'hir>,
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub const ATTR_CLEAN: &'static str = "rustc_clean";
|
||||||
pub const ATTR_IF_THIS_CHANGED: &'static str = "rustc_if_this_changed";
|
pub const ATTR_IF_THIS_CHANGED: &'static str = "rustc_if_this_changed";
|
||||||
pub const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need";
|
pub const ATTR_THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need";
|
||||||
pub const ATTR_PARTITION_REUSED: &'static str = "rustc_partition_reused";
|
pub const ATTR_PARTITION_REUSED: &'static str = "rustc_partition_reused";
|
||||||
pub const ATTR_PARTITION_TRANSLATED: &'static str = "rustc_partition_translated";
|
pub const ATTR_PARTITION_CODEGENED: &'static str = "rustc_partition_codegened";
|
||||||
|
|
||||||
|
|
||||||
pub const DEP_GRAPH_ASSERT_ATTRS: &'static [&'static str] = &[
|
pub const DEP_GRAPH_ASSERT_ATTRS: &'static [&'static str] = &[
|
||||||
|
@ -39,7 +39,7 @@ pub const DEP_GRAPH_ASSERT_ATTRS: &'static [&'static str] = &[
|
||||||
ATTR_DIRTY,
|
ATTR_DIRTY,
|
||||||
ATTR_CLEAN,
|
ATTR_CLEAN,
|
||||||
ATTR_PARTITION_REUSED,
|
ATTR_PARTITION_REUSED,
|
||||||
ATTR_PARTITION_TRANSLATED,
|
ATTR_PARTITION_CODEGENED,
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
|
pub const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
|
||||||
|
@ -49,5 +49,5 @@ pub const IGNORED_ATTRIBUTES: &'static [&'static str] = &[
|
||||||
ATTR_DIRTY,
|
ATTR_DIRTY,
|
||||||
ATTR_CLEAN,
|
ATTR_CLEAN,
|
||||||
ATTR_PARTITION_REUSED,
|
ATTR_PARTITION_REUSED,
|
||||||
ATTR_PARTITION_TRANSLATED,
|
ATTR_PARTITION_CODEGENED,
|
||||||
];
|
];
|
||||||
|
|
|
@ -614,7 +614,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx>
|
||||||
// compiler; those regions are ignored for the
|
// compiler; those regions are ignored for the
|
||||||
// outlives relation, and hence don't affect trait
|
// outlives relation, and hence don't affect trait
|
||||||
// selection or auto traits, and they are erased
|
// selection or auto traits, and they are erased
|
||||||
// during trans.
|
// during codegen.
|
||||||
|
|
||||||
let generics = self.tcx.generics_of(def_id);
|
let generics = self.tcx.generics_of(def_id);
|
||||||
let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
|
let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
|
||||||
|
|
|
@ -10,15 +10,15 @@
|
||||||
|
|
||||||
//! Implementation of lint checking.
|
//! Implementation of lint checking.
|
||||||
//!
|
//!
|
||||||
//! The lint checking is mostly consolidated into one pass which runs just
|
//! The lint checking is mostly consolidated into one pass which runs
|
||||||
//! before translation to LLVM bytecode. Throughout compilation, lint warnings
|
//! after all other analyses. Throughout compilation, lint warnings
|
||||||
//! can be added via the `add_lint` method on the Session structure. This
|
//! can be added via the `add_lint` method on the Session structure. This
|
||||||
//! requires a span and an id of the node that the lint is being added to. The
|
//! requires a span and an id of the node that the lint is being added to. The
|
||||||
//! lint isn't actually emitted at that time because it is unknown what the
|
//! lint isn't actually emitted at that time because it is unknown what the
|
||||||
//! actual lint level at that location is.
|
//! actual lint level at that location is.
|
||||||
//!
|
//!
|
||||||
//! To actually emit lint warnings/errors, a separate pass is used just before
|
//! To actually emit lint warnings/errors, a separate pass is used.
|
||||||
//! translation. A context keeps track of the current state of all lint levels.
|
//! A context keeps track of the current state of all lint levels.
|
||||||
//! Upon entering a node of the ast which can modify the lint settings, the
|
//! Upon entering a node of the ast which can modify the lint settings, the
|
||||||
//! previous lint state is pushed onto a stack and the ast is then recursed
|
//! previous lint state is pushed onto a stack and the ast is then recursed
|
||||||
//! upon. As the ast is traversed, this keeps track of the current lint level
|
//! upon. As the ast is traversed, this keeps track of the current lint level
|
||||||
|
|
|
@ -16,15 +16,15 @@
|
||||||
//! other phases of the compiler, which are generally required to hold in order
|
//! other phases of the compiler, which are generally required to hold in order
|
||||||
//! to compile the program at all.
|
//! to compile the program at all.
|
||||||
//!
|
//!
|
||||||
//! Most lints can be written as `LintPass` instances. These run just before
|
//! Most lints can be written as `LintPass` instances. These run after
|
||||||
//! translation to LLVM bytecode. The `LintPass`es built into rustc are defined
|
//! all other analyses. The `LintPass`es built into rustc are defined
|
||||||
//! within `builtin.rs`, which has further comments on how to add such a lint.
|
//! within `builtin.rs`, which has further comments on how to add such a lint.
|
||||||
//! rustc can also load user-defined lint plugins via the plugin mechanism.
|
//! rustc can also load user-defined lint plugins via the plugin mechanism.
|
||||||
//!
|
//!
|
||||||
//! Some of rustc's lints are defined elsewhere in the compiler and work by
|
//! Some of rustc's lints are defined elsewhere in the compiler and work by
|
||||||
//! calling `add_lint()` on the overall `Session` object. This works when
|
//! calling `add_lint()` on the overall `Session` object. This works when
|
||||||
//! it happens before the main lint pass, which emits the lints stored by
|
//! it happens before the main lint pass, which emits the lints stored by
|
||||||
//! `add_lint()`. To emit lints after the main lint pass (from trans, for
|
//! `add_lint()`. To emit lints after the main lint pass (from codegen, for
|
||||||
//! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
|
//! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
|
||||||
//! in `context.rs`.
|
//! in `context.rs`.
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
let sess = &tcx.sess;
|
let sess = &tcx.sess;
|
||||||
|
|
||||||
if !sess.opts.output_types.should_trans() {
|
if !sess.opts.output_types.should_codegen() {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,9 @@
|
||||||
//!
|
//!
|
||||||
//! ## By-reference upvars
|
//! ## By-reference upvars
|
||||||
//!
|
//!
|
||||||
//! One part of the translation which may be non-obvious is that we translate
|
//! One part of the codegen which may be non-obvious is that we translate
|
||||||
//! closure upvars into the dereference of a borrowed pointer; this more closely
|
//! closure upvars into the dereference of a borrowed pointer; this more closely
|
||||||
//! resembles the runtime translation. So, for example, if we had:
|
//! resembles the runtime codegen. So, for example, if we had:
|
||||||
//!
|
//!
|
||||||
//! let mut x = 3;
|
//! let mut x = 3;
|
||||||
//! let y = 5;
|
//! let y = 5;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
// makes all other generics or inline functions that it references
|
// makes all other generics or inline functions that it references
|
||||||
// reachable as well.
|
// reachable as well.
|
||||||
|
|
||||||
use hir::TransFnAttrs;
|
use hir::CodegenFnAttrs;
|
||||||
use hir::map as hir_map;
|
use hir::map as hir_map;
|
||||||
use hir::def::Def;
|
use hir::def::Def;
|
||||||
use hir::def_id::{DefId, CrateNum};
|
use hir::def_id::{DefId, CrateNum};
|
||||||
|
@ -44,7 +44,7 @@ fn generics_require_inlining(generics: &hir::Generics) -> bool {
|
||||||
// Returns true if the given item must be inlined because it may be
|
// Returns true if the given item must be inlined because it may be
|
||||||
// monomorphized or it was marked with `#[inline]`. This will only return
|
// monomorphized or it was marked with `#[inline]`. This will only return
|
||||||
// true for functions.
|
// true for functions.
|
||||||
fn item_might_be_inlined(item: &hir::Item, attrs: TransFnAttrs) -> bool {
|
fn item_might_be_inlined(item: &hir::Item, attrs: CodegenFnAttrs) -> bool {
|
||||||
if attrs.requests_inline() {
|
if attrs.requests_inline() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -61,15 +61,15 @@ fn item_might_be_inlined(item: &hir::Item, attrs: TransFnAttrs) -> bool {
|
||||||
fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
impl_item: &hir::ImplItem,
|
impl_item: &hir::ImplItem,
|
||||||
impl_src: DefId) -> bool {
|
impl_src: DefId) -> bool {
|
||||||
let trans_fn_attrs = tcx.trans_fn_attrs(impl_item.hir_id.owner_def_id());
|
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
|
||||||
if trans_fn_attrs.requests_inline() ||
|
if codegen_fn_attrs.requests_inline() ||
|
||||||
generics_require_inlining(&impl_item.generics) {
|
generics_require_inlining(&impl_item.generics) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
|
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
|
||||||
match tcx.hir.find(impl_node_id) {
|
match tcx.hir.find(impl_node_id) {
|
||||||
Some(hir_map::NodeItem(item)) =>
|
Some(hir_map::NodeItem(item)) =>
|
||||||
item_might_be_inlined(&item, trans_fn_attrs),
|
item_might_be_inlined(&item, codegen_fn_attrs),
|
||||||
Some(..) | None =>
|
Some(..) | None =>
|
||||||
span_bug!(impl_item.span, "impl did is not an item")
|
span_bug!(impl_item.span, "impl did is not an item")
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||||
Some(hir_map::NodeItem(item)) => {
|
Some(hir_map::NodeItem(item)) => {
|
||||||
match item.node {
|
match item.node {
|
||||||
hir::ItemFn(..) =>
|
hir::ItemFn(..) =>
|
||||||
item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)),
|
item_might_be_inlined(&item, self.tcx.codegen_fn_attrs(def_id)),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||||
match impl_item.node {
|
match impl_item.node {
|
||||||
hir::ImplItemKind::Const(..) => true,
|
hir::ImplItemKind::Const(..) => true,
|
||||||
hir::ImplItemKind::Method(..) => {
|
hir::ImplItemKind::Method(..) => {
|
||||||
let attrs = self.tcx.trans_fn_attrs(def_id);
|
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||||
if generics_require_inlining(&impl_item.generics) ||
|
if generics_require_inlining(&impl_item.generics) ||
|
||||||
attrs.requests_inline() {
|
attrs.requests_inline() {
|
||||||
true
|
true
|
||||||
|
@ -233,7 +233,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||||
let is_extern = self.tcx.trans_fn_attrs(def_id).contains_extern_indicator();
|
let is_extern = self.tcx.codegen_fn_attrs(def_id).contains_extern_indicator();
|
||||||
if reachable || is_extern {
|
if reachable || is_extern {
|
||||||
self.reachable_symbols.insert(search_item);
|
self.reachable_symbols.insert(search_item);
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||||
match item.node {
|
match item.node {
|
||||||
hir::ItemFn(.., body) => {
|
hir::ItemFn(.., body) => {
|
||||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||||
if item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)) {
|
if item_might_be_inlined(&item, self.tcx.codegen_fn_attrs(def_id)) {
|
||||||
self.visit_nested_body(body);
|
self.visit_nested_body(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1279,7 +1279,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
|
||||||
loop {
|
loop {
|
||||||
// Note: give all the expressions matching `ET` with the
|
// Note: give all the expressions matching `ET` with the
|
||||||
// extended temporary lifetime, not just the innermost rvalue,
|
// extended temporary lifetime, not just the innermost rvalue,
|
||||||
// because in trans if we must compile e.g. `*rvalue()`
|
// because in codegen if we must compile e.g. `*rvalue()`
|
||||||
// into a temporary, we request the temporary scope of the
|
// into a temporary, we request the temporary scope of the
|
||||||
// outer expression.
|
// outer expression.
|
||||||
visitor.scope_tree.record_rvalue_scope(expr.hir_id.local_id, blk_scope);
|
visitor.scope_tree.record_rvalue_scope(expr.hir_id.local_id, blk_scope);
|
||||||
|
|
|
@ -249,7 +249,7 @@ pub struct Allocation {
|
||||||
pub undef_mask: UndefMask,
|
pub undef_mask: UndefMask,
|
||||||
/// The alignment of the allocation to detect unaligned reads.
|
/// The alignment of the allocation to detect unaligned reads.
|
||||||
pub align: Align,
|
pub align: Align,
|
||||||
/// Whether the allocation (of a static) should be put into mutable memory when translating
|
/// Whether the allocation (of a static) should be put into mutable memory when codegenning
|
||||||
///
|
///
|
||||||
/// Only happens for `static mut` or `static` with interior mutability
|
/// Only happens for `static mut` or `static` with interior mutability
|
||||||
pub runtime_mutability: Mutability,
|
pub runtime_mutability: Mutability,
|
||||||
|
|
|
@ -75,7 +75,7 @@ impl<'tcx> ConstValue<'tcx> {
|
||||||
///
|
///
|
||||||
/// For optimization of a few very common cases, there is also a representation for a pair of
|
/// For optimization of a few very common cases, there is also a representation for a pair of
|
||||||
/// primitive values (`ByValPair`). It allows Miri to avoid making allocations for checked binary
|
/// primitive values (`ByValPair`). It allows Miri to avoid making allocations for checked binary
|
||||||
/// operations and fat pointers. This idea was taken from rustc's trans.
|
/// operations and fat pointers. This idea was taken from rustc's codegen.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
ByRef(Pointer, Align),
|
ByRef(Pointer, Align),
|
||||||
|
|
|
@ -696,7 +696,7 @@ pub struct BasicBlockData<'tcx> {
|
||||||
pub terminator: Option<Terminator<'tcx>>,
|
pub terminator: Option<Terminator<'tcx>>,
|
||||||
|
|
||||||
/// If true, this block lies on an unwind path. This is used
|
/// If true, this block lies on an unwind path. This is used
|
||||||
/// during trans where distinct kinds of basic blocks may be
|
/// during codegen where distinct kinds of basic blocks may be
|
||||||
/// generated (particularly for MSVC cleanup). Unwind blocks must
|
/// generated (particularly for MSVC cleanup). Unwind blocks must
|
||||||
/// only branch to other unwind blocks.
|
/// only branch to other unwind blocks.
|
||||||
pub is_cleanup: bool,
|
pub is_cleanup: bool,
|
||||||
|
@ -1614,7 +1614,7 @@ pub enum CastKind {
|
||||||
UnsafeFnPointer,
|
UnsafeFnPointer,
|
||||||
|
|
||||||
/// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
|
/// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
|
||||||
/// trans must figure out the details once full monomorphization
|
/// codegen must figure out the details once full monomorphization
|
||||||
/// is known. For example, this could be used to cast from a
|
/// is known. For example, this could be used to cast from a
|
||||||
/// `&[i32;N]` to a `&[i32]`, or a `Box<T>` to a `Box<Trait>`
|
/// `&[i32;N]` to a `&[i32]`, or a `Box<T>` to a `Box<Trait>`
|
||||||
/// (presuming `T: Trait`).
|
/// (presuming `T: Trait`).
|
||||||
|
|
|
@ -184,11 +184,11 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
|
||||||
|
|
||||||
name.hash_stable(hcx, hasher);
|
name.hash_stable(hcx, hasher);
|
||||||
|
|
||||||
let mut items: Vec<(Fingerprint, _)> = items.iter().map(|(trans_item, &attrs)| {
|
let mut items: Vec<(Fingerprint, _)> = items.iter().map(|(mono_item, &attrs)| {
|
||||||
let mut hasher = StableHasher::new();
|
let mut hasher = StableHasher::new();
|
||||||
trans_item.hash_stable(hcx, &mut hasher);
|
mono_item.hash_stable(hcx, &mut hasher);
|
||||||
let trans_item_fingerprint = hasher.finish();
|
let mono_item_fingerprint = hasher.finish();
|
||||||
(trans_item_fingerprint, attrs)
|
(mono_item_fingerprint, attrs)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
items.sort_unstable_by_key(|i| i.0);
|
items.sort_unstable_by_key(|i| i.0);
|
||||||
|
@ -238,4 +238,3 @@ impl Stats {
|
||||||
self.fn_stats.extend(stats.fn_stats);
|
self.fn_stats.extend(stats.fn_stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,7 @@ impl OutputTypes {
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if any of the output types require codegen or linking.
|
// True if any of the output types require codegen or linking.
|
||||||
pub fn should_trans(&self) -> bool {
|
pub fn should_codegen(&self) -> bool {
|
||||||
self.0.keys().any(|k| match *k {
|
self.0.keys().any(|k| match *k {
|
||||||
OutputType::Bitcode
|
OutputType::Bitcode
|
||||||
| OutputType::Assembly
|
| OutputType::Assembly
|
||||||
|
@ -1135,14 +1135,14 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
"count where LLVM instrs originate"),
|
"count where LLVM instrs originate"),
|
||||||
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
|
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
|
||||||
"The output of `-Z time-llvm-passes` will only reflect timings of \
|
"The output of `-Z time-llvm-passes` will only reflect timings of \
|
||||||
re-translated modules when used with incremental compilation" )],
|
re-codegened modules when used with incremental compilation" )],
|
||||||
"measure time of each LLVM pass"),
|
"measure time of each LLVM pass"),
|
||||||
input_stats: bool = (false, parse_bool, [UNTRACKED],
|
input_stats: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"gather statistics about the input"),
|
"gather statistics about the input"),
|
||||||
trans_stats: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
|
codegen_stats: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
|
||||||
"The output of `-Z trans-stats` might not be accurate when incremental \
|
"The output of `-Z codegen-stats` might not be accurate when incremental \
|
||||||
compilation is enabled")],
|
compilation is enabled")],
|
||||||
"gather trans statistics"),
|
"gather codegen statistics"),
|
||||||
asm_comments: bool = (false, parse_bool, [TRACKED],
|
asm_comments: bool = (false, parse_bool, [TRACKED],
|
||||||
"generate comments into the assembly (may change behavior)"),
|
"generate comments into the assembly (may change behavior)"),
|
||||||
no_verify: bool = (false, parse_bool, [TRACKED],
|
no_verify: bool = (false, parse_bool, [TRACKED],
|
||||||
|
@ -1183,8 +1183,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
Use with RUST_REGION_GRAPH=help for more info"),
|
Use with RUST_REGION_GRAPH=help for more info"),
|
||||||
parse_only: bool = (false, parse_bool, [UNTRACKED],
|
parse_only: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"parse only; do not compile, assemble, or link"),
|
"parse only; do not compile, assemble, or link"),
|
||||||
no_trans: bool = (false, parse_bool, [TRACKED],
|
no_codegen: bool = (false, parse_bool, [TRACKED],
|
||||||
"run all passes except translation; no output"),
|
"run all passes except codegen; no output"),
|
||||||
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
|
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
|
||||||
"treat all errors that occur as bugs"),
|
"treat all errors that occur as bugs"),
|
||||||
external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
|
external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
|
||||||
|
@ -1235,8 +1235,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
"show spans for compiler debugging (expr|pat|ty)"),
|
"show spans for compiler debugging (expr|pat|ty)"),
|
||||||
print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
|
print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"print layout information for each type encountered"),
|
"print layout information for each type encountered"),
|
||||||
print_trans_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
print_mono_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||||
"print the result of the translation item collection pass"),
|
"print the result of the monomorphization collection pass"),
|
||||||
mir_opt_level: usize = (1, parse_uint, [TRACKED],
|
mir_opt_level: usize = (1, parse_uint, [TRACKED],
|
||||||
"set the MIR optimization level (0-3, default: 1)"),
|
"set the MIR optimization level (0-3, default: 1)"),
|
||||||
mutable_noalias: bool = (false, parse_bool, [TRACKED],
|
mutable_noalias: bool = (false, parse_bool, [TRACKED],
|
||||||
|
@ -1244,7 +1244,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
arg_align_attributes: bool = (false, parse_bool, [TRACKED],
|
arg_align_attributes: bool = (false, parse_bool, [TRACKED],
|
||||||
"emit align metadata for reference arguments"),
|
"emit align metadata for reference arguments"),
|
||||||
dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||||
"dump MIR state at various points in translation"),
|
"dump MIR state at various points in transforms"),
|
||||||
dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED],
|
dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED],
|
||||||
"the directory the MIR is dumped into"),
|
"the directory the MIR is dumped into"),
|
||||||
dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
|
dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
|
||||||
|
@ -1296,8 +1296,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
"dump facts from NLL analysis into side files"),
|
"dump facts from NLL analysis into side files"),
|
||||||
disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
|
disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"disable user provided type assertion in NLL"),
|
"disable user provided type assertion in NLL"),
|
||||||
trans_time_graph: bool = (false, parse_bool, [UNTRACKED],
|
codegen_time_graph: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"generate a graphical HTML report of time spent in trans and LLVM"),
|
"generate a graphical HTML report of time spent in codegen and LLVM"),
|
||||||
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
"enable ThinLTO when possible"),
|
"enable ThinLTO when possible"),
|
||||||
inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
|
@ -1309,7 +1309,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
the max/min integer respectively, and NaN is mapped to 0"),
|
the max/min integer respectively, and NaN is mapped to 0"),
|
||||||
lower_128bit_ops: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
lower_128bit_ops: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||||
"rewrite operators on i128 and u128 into lang item calls (typically provided \
|
"rewrite operators on i128 and u128 into lang item calls (typically provided \
|
||||||
by compiler-builtins) so translation doesn't need to support them,
|
by compiler-builtins) so codegen doesn't need to support them,
|
||||||
overriding the default for the current target"),
|
overriding the default for the current target"),
|
||||||
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
|
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
|
||||||
"generate human-readable, predictable names for codegen units"),
|
"generate human-readable, predictable names for codegen units"),
|
||||||
|
@ -3047,7 +3047,7 @@ mod tests {
|
||||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||||
opts.debugging_opts.input_stats = true;
|
opts.debugging_opts.input_stats = true;
|
||||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||||
opts.debugging_opts.trans_stats = true;
|
opts.debugging_opts.codegen_stats = true;
|
||||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||||
opts.debugging_opts.borrowck_stats = true;
|
opts.debugging_opts.borrowck_stats = true;
|
||||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||||
|
@ -3093,7 +3093,7 @@ mod tests {
|
||||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||||
opts.debugging_opts.keep_ast = true;
|
opts.debugging_opts.keep_ast = true;
|
||||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||||
opts.debugging_opts.print_trans_items = Some(String::from("abc"));
|
opts.debugging_opts.print_mono_items = Some(String::from("abc"));
|
||||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||||
opts.debugging_opts.dump_mir = Some(String::from("abc"));
|
opts.debugging_opts.dump_mir = Some(String::from("abc"));
|
||||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||||
|
@ -3120,7 +3120,7 @@ mod tests {
|
||||||
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
||||||
|
|
||||||
opts = reference.clone();
|
opts = reference.clone();
|
||||||
opts.debugging_opts.no_trans = true;
|
opts.debugging_opts.no_codegen = true;
|
||||||
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
|
||||||
|
|
||||||
opts = reference.clone();
|
opts = reference.clone();
|
||||||
|
|
|
@ -98,7 +98,7 @@ pub struct Session {
|
||||||
/// arguments passed to the compiler. Its value together with the crate-name
|
/// arguments passed to the compiler. Its value together with the crate-name
|
||||||
/// forms a unique global identifier for the crate. It is used to allow
|
/// forms a unique global identifier for the crate. It is used to allow
|
||||||
/// multiple crates with the same name to coexist. See the
|
/// multiple crates with the same name to coexist. See the
|
||||||
/// trans::back::symbol_names module for more information.
|
/// rustc_codegen_llvm::back::symbol_names module for more information.
|
||||||
pub crate_disambiguator: Once<CrateDisambiguator>,
|
pub crate_disambiguator: Once<CrateDisambiguator>,
|
||||||
|
|
||||||
features: Once<feature_gate::Features>,
|
features: Once<feature_gate::Features>,
|
||||||
|
@ -504,8 +504,8 @@ impl Session {
|
||||||
pub fn time_llvm_passes(&self) -> bool {
|
pub fn time_llvm_passes(&self) -> bool {
|
||||||
self.opts.debugging_opts.time_llvm_passes
|
self.opts.debugging_opts.time_llvm_passes
|
||||||
}
|
}
|
||||||
pub fn trans_stats(&self) -> bool {
|
pub fn codegen_stats(&self) -> bool {
|
||||||
self.opts.debugging_opts.trans_stats
|
self.opts.debugging_opts.codegen_stats
|
||||||
}
|
}
|
||||||
pub fn meta_stats(&self) -> bool {
|
pub fn meta_stats(&self) -> bool {
|
||||||
self.opts.debugging_opts.meta_stats
|
self.opts.debugging_opts.meta_stats
|
||||||
|
@ -894,11 +894,11 @@ impl Session {
|
||||||
// Why is 16 codegen units the default all the time?
|
// Why is 16 codegen units the default all the time?
|
||||||
//
|
//
|
||||||
// The main reason for enabling multiple codegen units by default is to
|
// The main reason for enabling multiple codegen units by default is to
|
||||||
// leverage the ability for the trans backend to do translation and
|
// leverage the ability for the codegen backend to do codegen and
|
||||||
// codegen in parallel. This allows us, especially for large crates, to
|
// optimization in parallel. This allows us, especially for large crates, to
|
||||||
// make good use of all available resources on the machine once we've
|
// make good use of all available resources on the machine once we've
|
||||||
// hit that stage of compilation. Large crates especially then often
|
// hit that stage of compilation. Large crates especially then often
|
||||||
// take a long time in trans/codegen and this helps us amortize that
|
// take a long time in codegen/optimization and this helps us amortize that
|
||||||
// cost.
|
// cost.
|
||||||
//
|
//
|
||||||
// Note that a high number here doesn't mean that we'll be spawning a
|
// Note that a high number here doesn't mean that we'll be spawning a
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// This file contains various trait resolution methods used by trans.
|
// This file contains various trait resolution methods used by codegen.
|
||||||
// They all assume regions can be erased and monomorphic types. It
|
// They all assume regions can be erased and monomorphic types. It
|
||||||
// seems likely that they should eventually be merged into more
|
// seems likely that they should eventually be merged into more
|
||||||
// general routines.
|
// general routines.
|
||||||
|
@ -30,7 +30,7 @@ use ty::fold::TypeFoldable;
|
||||||
/// that type check should guarantee to us that all nested
|
/// that type check should guarantee to us that all nested
|
||||||
/// obligations *could be* resolved if we wanted to.
|
/// obligations *could be* resolved if we wanted to.
|
||||||
/// Assumes that this is run after the entire crate has been successfully type-checked.
|
/// Assumes that this is run after the entire crate has been successfully type-checked.
|
||||||
pub fn trans_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
(param_env, trait_ref):
|
(param_env, trait_ref):
|
||||||
(ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>))
|
(ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>))
|
||||||
-> Vtable<'tcx, ()>
|
-> Vtable<'tcx, ()>
|
||||||
|
@ -38,7 +38,7 @@ pub fn trans_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// Remove any references to regions; this helps improve caching.
|
// Remove any references to regions; this helps improve caching.
|
||||||
let trait_ref = ty.erase_regions(&trait_ref);
|
let trait_ref = ty.erase_regions(&trait_ref);
|
||||||
|
|
||||||
debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
|
debug!("codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
|
||||||
(param_env, trait_ref), trait_ref.def_id());
|
(param_env, trait_ref), trait_ref.def_id());
|
||||||
|
|
||||||
// Do the initial selection for the obligation. This yields the
|
// Do the initial selection for the obligation. This yields the
|
||||||
|
@ -60,12 +60,12 @@ pub fn trans_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// leading to an ambiguous result. So report this as an
|
// leading to an ambiguous result. So report this as an
|
||||||
// overflow bug, since I believe this is the only case
|
// overflow bug, since I believe this is the only case
|
||||||
// where ambiguity can result.
|
// where ambiguity can result.
|
||||||
bug!("Encountered ambiguity selecting `{:?}` during trans, \
|
bug!("Encountered ambiguity selecting `{:?}` during codegen, \
|
||||||
presuming due to overflow",
|
presuming due to overflow",
|
||||||
trait_ref)
|
trait_ref)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
bug!("Encountered error `{:?}` selecting `{:?}` during trans",
|
bug!("Encountered error `{:?}` selecting `{:?}` during codegen",
|
||||||
e, trait_ref)
|
e, trait_ref)
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -64,7 +64,7 @@ mod on_unimplemented;
|
||||||
mod select;
|
mod select;
|
||||||
mod specialize;
|
mod specialize;
|
||||||
mod structural_impls;
|
mod structural_impls;
|
||||||
pub mod trans;
|
pub mod codegen;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
pub mod query;
|
pub mod query;
|
||||||
|
@ -473,8 +473,8 @@ pub enum Vtable<'tcx, N> {
|
||||||
///
|
///
|
||||||
/// The type parameter `N` indicates the type used for "nested
|
/// The type parameter `N` indicates the type used for "nested
|
||||||
/// obligations" that are required by the impl. During type check, this
|
/// obligations" that are required by the impl. During type check, this
|
||||||
/// is `Obligation`, as one might expect. During trans, however, this
|
/// is `Obligation`, as one might expect. During codegen, however, this
|
||||||
/// is `()`, because trans only requires a shallow resolution of an
|
/// is `()`, because codegen only requires a shallow resolution of an
|
||||||
/// impl, and nested obligations are satisfied later.
|
/// impl, and nested obligations are satisfied later.
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub struct VtableImplData<'tcx, N> {
|
pub struct VtableImplData<'tcx, N> {
|
||||||
|
@ -856,7 +856,7 @@ fn vtable_methods<'a, 'tcx>(
|
||||||
// It's possible that the method relies on where clauses that
|
// It's possible that the method relies on where clauses that
|
||||||
// do not hold for this particular set of type parameters.
|
// do not hold for this particular set of type parameters.
|
||||||
// Note that this method could then never be called, so we
|
// Note that this method could then never be called, so we
|
||||||
// do not want to try and trans it, in that case (see #23435).
|
// do not want to try and codegen it, in that case (see #23435).
|
||||||
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
|
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
|
||||||
if !normalize_and_test_predicates(tcx, predicates.predicates) {
|
if !normalize_and_test_predicates(tcx, predicates.predicates) {
|
||||||
debug!("vtable_methods: predicates do not hold");
|
debug!("vtable_methods: predicates do not hold");
|
||||||
|
@ -992,7 +992,7 @@ pub fn provide(providers: &mut ty::maps::Providers) {
|
||||||
is_object_safe: object_safety::is_object_safe_provider,
|
is_object_safe: object_safety::is_object_safe_provider,
|
||||||
specialization_graph_of: specialize::specialization_graph_provider,
|
specialization_graph_of: specialize::specialization_graph_provider,
|
||||||
specializes: specialize::specializes,
|
specializes: specialize::specializes,
|
||||||
trans_fulfill_obligation: trans::trans_fulfill_obligation,
|
codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
|
||||||
vtable_methods,
|
vtable_methods,
|
||||||
substitute_normalize_and_test_predicates,
|
substitute_normalize_and_test_predicates,
|
||||||
..*providers
|
..*providers
|
||||||
|
|
|
@ -65,7 +65,7 @@ pub enum Reveal {
|
||||||
/// }
|
/// }
|
||||||
UserFacing,
|
UserFacing,
|
||||||
|
|
||||||
/// At trans time, all monomorphic projections will succeed.
|
/// At codegen time, all monomorphic projections will succeed.
|
||||||
/// Also, `impl Trait` is normalized to the concrete type,
|
/// Also, `impl Trait` is normalized to the concrete type,
|
||||||
/// which has to be already collected by type-checking.
|
/// which has to be already collected by type-checking.
|
||||||
///
|
///
|
||||||
|
@ -346,7 +346,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||||
let ty = ty.super_fold_with(self);
|
let ty = ty.super_fold_with(self);
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
|
ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
|
||||||
// Only normalize `impl Trait` after type-checking, usually in trans.
|
// Only normalize `impl Trait` after type-checking, usually in codegen.
|
||||||
match self.param_env.reveal {
|
match self.param_env.reveal {
|
||||||
Reveal::UserFacing => ty,
|
Reveal::UserFacing => ty,
|
||||||
|
|
||||||
|
@ -1054,7 +1054,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
|
||||||
super::VtableImpl(impl_data) => {
|
super::VtableImpl(impl_data) => {
|
||||||
// We have to be careful when projecting out of an
|
// We have to be careful when projecting out of an
|
||||||
// impl because of specialization. If we are not in
|
// impl because of specialization. If we are not in
|
||||||
// trans (i.e., projection mode is not "any"), and the
|
// codegen (i.e., projection mode is not "any"), and the
|
||||||
// impl's type is declared as default, then we disable
|
// impl's type is declared as default, then we disable
|
||||||
// projection (even if the trait ref is fully
|
// projection (even if the trait ref is fully
|
||||||
// monomorphic). In the case where trait ref is not
|
// monomorphic). In the case where trait ref is not
|
||||||
|
|
|
@ -104,7 +104,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => {
|
ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => {
|
||||||
// (*)
|
// (*)
|
||||||
// Only normalize `impl Trait` after type-checking, usually in trans.
|
// Only normalize `impl Trait` after type-checking, usually in codegen.
|
||||||
match self.param_env.reveal {
|
match self.param_env.reveal {
|
||||||
Reveal::UserFacing => ty,
|
Reveal::UserFacing => ty,
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl<'cx, 'tcx> TyCtxt<'cx, 'tcx, 'tcx> {
|
||||||
///
|
///
|
||||||
/// NB. Currently, higher-ranked type bounds inhibit
|
/// NB. Currently, higher-ranked type bounds inhibit
|
||||||
/// normalization. Therefore, each time we erase them in
|
/// normalization. Therefore, each time we erase them in
|
||||||
/// translation, we need to normalize the contents.
|
/// codegen, we need to normalize the contents.
|
||||||
pub fn normalize_erasing_late_bound_regions<T>(
|
pub fn normalize_erasing_late_bound_regions<T>(
|
||||||
self,
|
self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
|
@ -275,7 +275,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For trans only.
|
// For codegen only.
|
||||||
impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
|
impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
|
||||||
type Lifted = traits::Vtable<'tcx, ()>;
|
type Lifted = traits::Vtable<'tcx, ()>;
|
||||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||||
|
|
|
@ -91,8 +91,8 @@ pub enum Adjust<'tcx> {
|
||||||
/// pointers. We don't store the details of how the transform is
|
/// pointers. We don't store the details of how the transform is
|
||||||
/// done (in fact, we don't know that, because it might depend on
|
/// done (in fact, we don't know that, because it might depend on
|
||||||
/// the precise type parameters). We just store the target
|
/// the precise type parameters). We just store the target
|
||||||
/// type. Trans figures out what has to be done at monomorphization
|
/// type. Codegen backends and miri figure out what has to be done
|
||||||
/// time based on the precise source/target type at hand.
|
/// based on the precise source/target type at hand.
|
||||||
Unsize,
|
Unsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// Helpers for handling cast expressions, used in both
|
// Helpers for handling cast expressions, used in both
|
||||||
// typeck and trans.
|
// typeck and codegen.
|
||||||
|
|
||||||
use ty::{self, Ty};
|
use ty::{self, Ty};
|
||||||
|
|
||||||
|
|
|
@ -401,7 +401,7 @@ pub struct TypeckTables<'tcx> {
|
||||||
/// For each fn, records the "liberated" types of its arguments
|
/// For each fn, records the "liberated" types of its arguments
|
||||||
/// and return type. Liberated means that all bound regions
|
/// and return type. Liberated means that all bound regions
|
||||||
/// (including late-bound regions) are replaced with free
|
/// (including late-bound regions) are replaced with free
|
||||||
/// equivalents. This table is not used in trans (since regions
|
/// equivalents. This table is not used in codegen (since regions
|
||||||
/// are erased there) and hence is not serialized to metadata.
|
/// are erased there) and hence is not serialized to metadata.
|
||||||
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
|
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
|
||||||
|
|
||||||
|
@ -921,7 +921,7 @@ pub struct GlobalCtxt<'tcx> {
|
||||||
/// A general purpose channel to throw data out the back towards LLVM worker
|
/// A general purpose channel to throw data out the back towards LLVM worker
|
||||||
/// threads.
|
/// threads.
|
||||||
///
|
///
|
||||||
/// This is intended to only get used during the trans phase of the compiler
|
/// This is intended to only get used during the codegen phase of the compiler
|
||||||
/// when satisfying the query for a particular codegen unit. Internally in
|
/// when satisfying the query for a particular codegen unit. Internally in
|
||||||
/// the query it'll send data along this channel to get processed later.
|
/// the query it'll send data along this channel to get processed later.
|
||||||
pub tx_to_llvm_workers: Lock<mpsc::Sender<Box<dyn Any + Send>>>,
|
pub tx_to_llvm_workers: Lock<mpsc::Sender<Box<dyn Any + Send>>>,
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 't
|
||||||
//
|
//
|
||||||
// Note that we *CAN* replace early-bound regions -- the
|
// Note that we *CAN* replace early-bound regions -- the
|
||||||
// type system never "sees" those, they get substituted
|
// type system never "sees" those, they get substituted
|
||||||
// away. In trans, they will always be erased to 'erased
|
// away. In codegen, they will always be erased to 'erased
|
||||||
// whenever a substitution occurs.
|
// whenever a substitution occurs.
|
||||||
match *r {
|
match *r {
|
||||||
ty::ReLateBound(..) => r,
|
ty::ReLateBound(..) => r,
|
||||||
|
@ -76,4 +76,3 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 't
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -424,7 +424,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
collector.regions
|
collector.regions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace any late-bound regions bound in `value` with `'erased`. Useful in trans but also
|
/// Replace any late-bound regions bound in `value` with `'erased`. Useful in codegen but also
|
||||||
/// method lookup and a few other places where precise region relationships are not required.
|
/// method lookup and a few other places where precise region relationships are not required.
|
||||||
pub fn erase_late_bound_regions<T>(self, value: &Binder<T>) -> T
|
pub fn erase_late_bound_regions<T>(self, value: &Binder<T>) -> T
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
|
|
|
@ -104,13 +104,13 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if let ty::InstanceDef::DropGlue(..) = *self {
|
if let ty::InstanceDef::DropGlue(..) = *self {
|
||||||
// Drop glue wants to be instantiated at every translation
|
// Drop glue wants to be instantiated at every codegen
|
||||||
// unit, but without an #[inline] hint. We should make this
|
// unit, but without an #[inline] hint. We should make this
|
||||||
// available to normal end-users.
|
// available to normal end-users.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
let trans_fn_attrs = tcx.trans_fn_attrs(self.def_id());
|
let codegen_fn_attrs = tcx.codegen_fn_attrs(self.def_id());
|
||||||
trans_fn_attrs.requests_inline() || tcx.is_const_fn(self.def_id())
|
codegen_fn_attrs.requests_inline() || tcx.is_const_fn(self.def_id())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ impl<'a, 'b, 'tcx> Instance<'tcx> {
|
||||||
pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
|
pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
|
||||||
-> Instance<'tcx> {
|
-> Instance<'tcx> {
|
||||||
assert!(!substs.has_escaping_regions(),
|
assert!(!substs.has_escaping_regions(),
|
||||||
"substs of instance {:?} not normalized for trans: {:?}",
|
"substs of instance {:?} not normalized for codegen: {:?}",
|
||||||
def_id, substs);
|
def_id, substs);
|
||||||
Instance { def: InstanceDef::Item(def_id), substs: substs }
|
Instance { def: InstanceDef::Item(def_id), substs: substs }
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ impl<'a, 'b, 'tcx> Instance<'tcx> {
|
||||||
/// `RevealMode` in the parameter environment.)
|
/// `RevealMode` in the parameter environment.)
|
||||||
///
|
///
|
||||||
/// Presuming that coherence and type-check have succeeded, if this method is invoked
|
/// Presuming that coherence and type-check have succeeded, if this method is invoked
|
||||||
/// in a monomorphic context (i.e., like during trans), then it is guaranteed to return
|
/// in a monomorphic context (i.e., like during codegen), then it is guaranteed to return
|
||||||
/// `Some`.
|
/// `Some`.
|
||||||
pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
@ -259,7 +259,7 @@ fn resolve_associated_item<'a, 'tcx>(
|
||||||
def_id, trait_id, rcvr_substs);
|
def_id, trait_id, rcvr_substs);
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||||
let vtbl = tcx.trans_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
|
let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)));
|
||||||
|
|
||||||
// Now that we know which impl is being used, we can dispatch to
|
// Now that we know which impl is being used, we can dispatch to
|
||||||
// the actual function:
|
// the actual function:
|
||||||
|
@ -321,7 +321,7 @@ fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
|
||||||
}
|
}
|
||||||
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
|
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
|
||||||
// The closure fn `llfn` is a `fn(&self, ...)`. We want a
|
// The closure fn `llfn` is a `fn(&self, ...)`. We want a
|
||||||
// `fn(&mut self, ...)`. In fact, at trans time, these are
|
// `fn(&mut self, ...)`. In fact, at codegen time, these are
|
||||||
// basically the same thing, so we can just return llfn.
|
// basically the same thing, so we can just return llfn.
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
@ -334,7 +334,7 @@ fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
|
||||||
// fn call_once(self, ...) { call_mut(&self, ...) }
|
// fn call_once(self, ...) { call_mut(&self, ...) }
|
||||||
// fn call_once(mut self, ...) { call_mut(&mut self, ...) }
|
// fn call_once(mut self, ...) { call_mut(&mut self, ...) }
|
||||||
//
|
//
|
||||||
// These are both the same at trans time.
|
// These are both the same at codegen time.
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
(ty::ClosureKind::FnMut, _) |
|
(ty::ClosureKind::FnMut, _) |
|
||||||
|
|
|
@ -949,14 +949,14 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
||||||
// because this discriminant will be loaded, and then stored into variable of
|
// because this discriminant will be loaded, and then stored into variable of
|
||||||
// type calculated by typeck. Consider such case (a bug): typeck decided on
|
// type calculated by typeck. Consider such case (a bug): typeck decided on
|
||||||
// byte-sized discriminant, but layout thinks we need a 16-bit to store all
|
// byte-sized discriminant, but layout thinks we need a 16-bit to store all
|
||||||
// discriminant values. That would be a bug, because then, in trans, in order
|
// discriminant values. That would be a bug, because then, in codegen, in order
|
||||||
// to store this 16-bit discriminant into 8-bit sized temporary some of the
|
// to store this 16-bit discriminant into 8-bit sized temporary some of the
|
||||||
// space necessary to represent would have to be discarded (or layout is wrong
|
// space necessary to represent would have to be discarded (or layout is wrong
|
||||||
// on thinking it needs 16 bits)
|
// on thinking it needs 16 bits)
|
||||||
bug!("layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
|
bug!("layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
|
||||||
min_ity, typeck_ity);
|
min_ity, typeck_ity);
|
||||||
// However, it is fine to make discr type however large (as an optimisation)
|
// However, it is fine to make discr type however large (as an optimisation)
|
||||||
// after this point – we’ll just truncate the value we load in trans.
|
// after this point – we’ll just truncate the value we load in codegen.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if we should use a different type for the
|
// Check to see if we should use a different type for the
|
||||||
|
@ -1121,7 +1121,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
||||||
// If we are running with `-Zprint-type-sizes`, record layouts for
|
// If we are running with `-Zprint-type-sizes`, record layouts for
|
||||||
// dumping later. Ignore layouts that are done with non-empty
|
// dumping later. Ignore layouts that are done with non-empty
|
||||||
// environments or non-monomorphic layouts, as the user only wants
|
// environments or non-monomorphic layouts, as the user only wants
|
||||||
// to see the stuff resulting from the final trans session.
|
// to see the stuff resulting from the final codegen session.
|
||||||
if
|
if
|
||||||
!self.tcx.sess.opts.debugging_opts.print_type_sizes ||
|
!self.tcx.sess.opts.debugging_opts.print_type_sizes ||
|
||||||
layout.ty.has_param_types() ||
|
layout.ty.has_param_types() ||
|
||||||
|
|
|
@ -349,7 +349,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::is_mir_available<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> QueryDescription<'tcx> for queries::trans_fulfill_obligation<'tcx> {
|
impl<'tcx> QueryDescription<'tcx> for queries::codegen_fulfill_obligation<'tcx> {
|
||||||
fn describe(tcx: TyCtxt, key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String {
|
fn describe(tcx: TyCtxt, key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String {
|
||||||
format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id()))
|
format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id()))
|
||||||
}
|
}
|
||||||
|
@ -637,9 +637,9 @@ impl<'tcx> QueryDescription<'tcx> for queries::exported_symbols<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> QueryDescription<'tcx> for queries::collect_and_partition_translation_items<'tcx> {
|
impl<'tcx> QueryDescription<'tcx> for queries::collect_and_partition_mono_items<'tcx> {
|
||||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||||
format!("collect_and_partition_translation_items")
|
format!("collect_and_partition_mono_items")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,5 +795,5 @@ impl_disk_cacheable_query!(def_symbol_name, |_| true);
|
||||||
impl_disk_cacheable_query!(type_of, |def_id| def_id.is_local());
|
impl_disk_cacheable_query!(type_of, |def_id| def_id.is_local());
|
||||||
impl_disk_cacheable_query!(predicates_of, |def_id| def_id.is_local());
|
impl_disk_cacheable_query!(predicates_of, |def_id| def_id.is_local());
|
||||||
impl_disk_cacheable_query!(used_trait_imports, |def_id| def_id.is_local());
|
impl_disk_cacheable_query!(used_trait_imports, |def_id| def_id.is_local());
|
||||||
impl_disk_cacheable_query!(trans_fn_attrs, |_| true);
|
impl_disk_cacheable_query!(codegen_fn_attrs, |_| true);
|
||||||
impl_disk_cacheable_query!(specialization_graph_of, |_| true);
|
impl_disk_cacheable_query!(specialization_graph_of, |_| true);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use dep_graph::{DepConstructor, DepNode};
|
use dep_graph::{DepConstructor, DepNode};
|
||||||
use hir::def_id::{CrateNum, DefId, DefIndex};
|
use hir::def_id::{CrateNum, DefId, DefIndex};
|
||||||
use hir::def::{Def, Export};
|
use hir::def::{Def, Export};
|
||||||
use hir::{self, TraitCandidate, ItemLocalId, TransFnAttrs};
|
use hir::{self, TraitCandidate, ItemLocalId, CodegenFnAttrs};
|
||||||
use hir::svh::Svh;
|
use hir::svh::Svh;
|
||||||
use infer::canonical::{self, Canonical};
|
use infer::canonical::{self, Canonical};
|
||||||
use lint;
|
use lint;
|
||||||
|
@ -181,7 +181,7 @@ define_maps! { <'tcx>
|
||||||
[] fn mir_validated: MirValidated(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
|
[] fn mir_validated: MirValidated(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
|
||||||
|
|
||||||
/// MIR after our optimization passes have run. This is MIR that is ready
|
/// MIR after our optimization passes have run. This is MIR that is ready
|
||||||
/// for trans. This is also the only query that can fetch non-local MIR, at present.
|
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
|
||||||
[] fn optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>,
|
[] fn optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>,
|
||||||
|
|
||||||
/// The result of unsafety-checking this def-id.
|
/// The result of unsafety-checking this def-id.
|
||||||
|
@ -255,7 +255,7 @@ define_maps! { <'tcx>
|
||||||
[] fn lookup_stability: LookupStability(DefId) -> Option<&'tcx attr::Stability>,
|
[] fn lookup_stability: LookupStability(DefId) -> Option<&'tcx attr::Stability>,
|
||||||
[] fn lookup_deprecation_entry: LookupDeprecationEntry(DefId) -> Option<DeprecationEntry>,
|
[] fn lookup_deprecation_entry: LookupDeprecationEntry(DefId) -> Option<DeprecationEntry>,
|
||||||
[] fn item_attrs: ItemAttrs(DefId) -> Lrc<[ast::Attribute]>,
|
[] fn item_attrs: ItemAttrs(DefId) -> Lrc<[ast::Attribute]>,
|
||||||
[] fn trans_fn_attrs: trans_fn_attrs(DefId) -> TransFnAttrs,
|
[] fn codegen_fn_attrs: codegen_fn_attrs(DefId) -> CodegenFnAttrs,
|
||||||
[] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
|
[] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
|
||||||
/// Gets the rendered value of the specified constant or associated constant.
|
/// Gets the rendered value of the specified constant or associated constant.
|
||||||
/// Used by rustdoc.
|
/// Used by rustdoc.
|
||||||
|
@ -268,7 +268,7 @@ define_maps! { <'tcx>
|
||||||
[] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>)
|
[] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>)
|
||||||
-> Lrc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>>,
|
-> Lrc<Vec<Option<(DefId, &'tcx Substs<'tcx>)>>>,
|
||||||
|
|
||||||
[] fn trans_fulfill_obligation: fulfill_obligation_dep_node(
|
[] fn codegen_fulfill_obligation: fulfill_obligation_dep_node(
|
||||||
(ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Vtable<'tcx, ()>,
|
(ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Vtable<'tcx, ()>,
|
||||||
[] fn trait_impls_of: TraitImpls(DefId) -> Lrc<ty::trait_def::TraitImpls>,
|
[] fn trait_impls_of: TraitImpls(DefId) -> Lrc<ty::trait_def::TraitImpls>,
|
||||||
[] fn specialization_graph_of: SpecializationGraph(DefId) -> Lrc<specialization_graph::Graph>,
|
[] fn specialization_graph_of: SpecializationGraph(DefId) -> Lrc<specialization_graph::Graph>,
|
||||||
|
@ -402,10 +402,10 @@ define_maps! { <'tcx>
|
||||||
|
|
||||||
[] fn exported_symbols: ExportedSymbols(CrateNum)
|
[] fn exported_symbols: ExportedSymbols(CrateNum)
|
||||||
-> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>>,
|
-> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>>,
|
||||||
[] fn collect_and_partition_translation_items:
|
[] fn collect_and_partition_mono_items:
|
||||||
collect_and_partition_translation_items_node(CrateNum)
|
collect_and_partition_mono_items_node(CrateNum)
|
||||||
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
|
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
|
||||||
[] fn is_translated_item: IsTranslatedItem(DefId) -> bool,
|
[] fn is_codegened_item: IsCodegenedItem(DefId) -> bool,
|
||||||
[] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
|
[] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
|
||||||
[] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats,
|
[] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats,
|
||||||
[] fn output_filenames: output_filenames_node(CrateNum)
|
[] fn output_filenames: output_filenames_node(CrateNum)
|
||||||
|
@ -475,8 +475,8 @@ fn features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||||
DepConstructor::Features
|
DepConstructor::Features
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_fn_attrs<'tcx>(id: DefId) -> DepConstructor<'tcx> {
|
fn codegen_fn_attrs<'tcx>(id: DefId) -> DepConstructor<'tcx> {
|
||||||
DepConstructor::TransFnAttrs { 0: id }
|
DepConstructor::CodegenFnAttrs { 0: id }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
|
fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
|
||||||
|
@ -609,8 +609,8 @@ fn all_traits_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||||
DepConstructor::AllTraits
|
DepConstructor::AllTraits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_and_partition_translation_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
fn collect_and_partition_mono_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||||
DepConstructor::CollectAndPartitionTranslationItems
|
DepConstructor::CollectAndPartitionMonoItems
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_filenames_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
fn output_filenames_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||||
|
|
|
@ -224,7 +224,7 @@ impl<'sess> OnDiskCache<'sess> {
|
||||||
encode_query_results::<predicates_of, _>(tcx, enc, qri)?;
|
encode_query_results::<predicates_of, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<used_trait_imports, _>(tcx, enc, qri)?;
|
encode_query_results::<used_trait_imports, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
|
encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
|
encode_query_results::<codegen_fulfill_obligation, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
|
encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
|
encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<borrowck, _>(tcx, enc, qri)?;
|
encode_query_results::<borrowck, _>(tcx, enc, qri)?;
|
||||||
|
@ -234,7 +234,7 @@ impl<'sess> OnDiskCache<'sess> {
|
||||||
encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
|
encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
|
encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<check_match, _>(tcx, enc, qri)?;
|
encode_query_results::<check_match, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<trans_fn_attrs, _>(tcx, enc, qri)?;
|
encode_query_results::<codegen_fn_attrs, _>(tcx, enc, qri)?;
|
||||||
encode_query_results::<specialization_graph_of, _>(tcx, enc, qri)?;
|
encode_query_results::<specialization_graph_of, _>(tcx, enc, qri)?;
|
||||||
|
|
||||||
// const eval is special, it only encodes successfully evaluated constants
|
// const eval is special, it only encodes successfully evaluated constants
|
||||||
|
|
|
@ -871,7 +871,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||||
// Since we cannot reconstruct the query key of a DepNode::CodegenUnit, we
|
// Since we cannot reconstruct the query key of a DepNode::CodegenUnit, we
|
||||||
// would always end up having to evaluate the first caller of the
|
// would always end up having to evaluate the first caller of the
|
||||||
// `codegen_unit` query that *is* reconstructible. This might very well be
|
// `codegen_unit` query that *is* reconstructible. This might very well be
|
||||||
// the `compile_codegen_unit` query, thus re-translating the whole CGU just
|
// the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
|
||||||
// to re-trigger calling the `codegen_unit` query with the right key. At
|
// to re-trigger calling the `codegen_unit` query with the right key. At
|
||||||
// that point we would already have re-done all the work we are trying to
|
// that point we would already have re-done all the work we are trying to
|
||||||
// avoid doing in the first place.
|
// avoid doing in the first place.
|
||||||
|
@ -1046,7 +1046,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||||
}
|
}
|
||||||
DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
|
DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
|
||||||
DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
|
DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
|
||||||
DepKind::TransFnAttrs => { force!(trans_fn_attrs, def_id!()); }
|
DepKind::CodegenFnAttrs => { force!(codegen_fn_attrs, def_id!()); }
|
||||||
DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
|
DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
|
||||||
DepKind::RenderedConst => { force!(rendered_const, def_id!()); }
|
DepKind::RenderedConst => { force!(rendered_const, def_id!()); }
|
||||||
DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
|
DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
|
||||||
|
@ -1121,10 +1121,10 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||||
DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); }
|
DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); }
|
||||||
DepKind::AllCrateNums => { force!(all_crate_nums, LOCAL_CRATE); }
|
DepKind::AllCrateNums => { force!(all_crate_nums, LOCAL_CRATE); }
|
||||||
DepKind::ExportedSymbols => { force!(exported_symbols, krate!()); }
|
DepKind::ExportedSymbols => { force!(exported_symbols, krate!()); }
|
||||||
DepKind::CollectAndPartitionTranslationItems => {
|
DepKind::CollectAndPartitionMonoItems => {
|
||||||
force!(collect_and_partition_translation_items, LOCAL_CRATE);
|
force!(collect_and_partition_mono_items, LOCAL_CRATE);
|
||||||
}
|
}
|
||||||
DepKind::IsTranslatedItem => { force!(is_translated_item, def_id!()); }
|
DepKind::IsCodegenedItem => { force!(is_codegened_item, def_id!()); }
|
||||||
DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
|
DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
|
||||||
|
|
||||||
DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
|
DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
|
||||||
|
@ -1207,6 +1207,6 @@ impl_load_from_cache!(
|
||||||
GenericsOfItem => generics_of,
|
GenericsOfItem => generics_of,
|
||||||
PredicatesOfItem => predicates_of,
|
PredicatesOfItem => predicates_of,
|
||||||
UsedTraitImports => used_trait_imports,
|
UsedTraitImports => used_trait_imports,
|
||||||
TransFnAttrs => trans_fn_attrs,
|
CodegenFnAttrs => codegen_fn_attrs,
|
||||||
SpecializationGraph => specialization_graph_of,
|
SpecializationGraph => specialization_graph_of,
|
||||||
);
|
);
|
||||||
|
|
|
@ -118,7 +118,7 @@ mod sty;
|
||||||
// Data types
|
// Data types
|
||||||
|
|
||||||
/// The complete set of all analyses described in this module. This is
|
/// The complete set of all analyses described in this module. This is
|
||||||
/// produced by the driver and fed to trans and later passes.
|
/// produced by the driver and fed to codegen and later passes.
|
||||||
///
|
///
|
||||||
/// NB: These contents are being migrated into queries using the
|
/// NB: These contents are being migrated into queries using the
|
||||||
/// *on-demand* infrastructure.
|
/// *on-demand* infrastructure.
|
||||||
|
@ -1426,7 +1426,7 @@ pub struct ParamEnv<'tcx> {
|
||||||
/// into Obligations, and elaborated and normalized.
|
/// into Obligations, and elaborated and normalized.
|
||||||
pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
|
pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
|
||||||
|
|
||||||
/// Typically, this is `Reveal::UserFacing`, but during trans we
|
/// Typically, this is `Reveal::UserFacing`, but during codegen we
|
||||||
/// want `Reveal::All` -- note that this is always paired with an
|
/// want `Reveal::All` -- note that this is always paired with an
|
||||||
/// empty environment. To get that, use `ParamEnv::reveal()`.
|
/// empty environment. To get that, use `ParamEnv::reveal()`.
|
||||||
pub reveal: traits::Reveal,
|
pub reveal: traits::Reveal,
|
||||||
|
@ -1444,7 +1444,7 @@ impl<'tcx> ParamEnv<'tcx> {
|
||||||
/// Construct a trait environment with no where clauses in scope
|
/// Construct a trait environment with no where clauses in scope
|
||||||
/// where the values of all `impl Trait` and other hidden types
|
/// where the values of all `impl Trait` and other hidden types
|
||||||
/// are revealed. This is suitable for monomorphized, post-typeck
|
/// are revealed. This is suitable for monomorphized, post-typeck
|
||||||
/// environments like trans or doing optimizations.
|
/// environments like codegen or doing optimizations.
|
||||||
///
|
///
|
||||||
/// NB. If you want to have predicates in scope, use `ParamEnv::new`,
|
/// NB. If you want to have predicates in scope, use `ParamEnv::new`,
|
||||||
/// or invoke `param_env.with_reveal_all()`.
|
/// or invoke `param_env.with_reveal_all()`.
|
||||||
|
@ -1462,7 +1462,7 @@ impl<'tcx> ParamEnv<'tcx> {
|
||||||
/// Returns a new parameter environment with the same clauses, but
|
/// Returns a new parameter environment with the same clauses, but
|
||||||
/// which "reveals" the true results of projections in all cases
|
/// which "reveals" the true results of projections in all cases
|
||||||
/// (even for associated types that are specializable). This is
|
/// (even for associated types that are specializable). This is
|
||||||
/// the desired behavior during trans and certain other special
|
/// the desired behavior during codegen and certain other special
|
||||||
/// contexts; normally though we want to use `Reveal::UserFacing`,
|
/// contexts; normally though we want to use `Reveal::UserFacing`,
|
||||||
/// which is the default.
|
/// which is the default.
|
||||||
pub fn with_reveal_all(self) -> Self {
|
pub fn with_reveal_all(self) -> Self {
|
||||||
|
|
|
@ -243,7 +243,7 @@ pub enum TypeVariants<'tcx> {
|
||||||
/// out later.
|
/// out later.
|
||||||
///
|
///
|
||||||
/// All right, you say, but why include the type parameters from the
|
/// All right, you say, but why include the type parameters from the
|
||||||
/// original function then? The answer is that trans may need them
|
/// original function then? The answer is that codegen may need them
|
||||||
/// when monomorphizing, and they may not appear in the upvars. A
|
/// when monomorphizing, and they may not appear in the upvars. A
|
||||||
/// closure could capture no variables but still make use of some
|
/// closure could capture no variables but still make use of some
|
||||||
/// in-scope type parameter with a bound (e.g., if our example above
|
/// in-scope type parameter with a bound (e.g., if our example above
|
||||||
|
@ -273,7 +273,7 @@ pub struct ClosureSubsts<'tcx> {
|
||||||
/// Lifetime and type parameters from the enclosing function,
|
/// Lifetime and type parameters from the enclosing function,
|
||||||
/// concatenated with the types of the upvars.
|
/// concatenated with the types of the upvars.
|
||||||
///
|
///
|
||||||
/// These are separated out because trans wants to pass them around
|
/// These are separated out because codegen wants to pass them around
|
||||||
/// when monomorphizing.
|
/// when monomorphizing.
|
||||||
pub substs: &'tcx Substs<'tcx>,
|
pub substs: &'tcx Substs<'tcx>,
|
||||||
}
|
}
|
||||||
|
@ -1093,7 +1093,7 @@ pub enum RegionKind {
|
||||||
/// variable with no constraints.
|
/// variable with no constraints.
|
||||||
ReEmpty,
|
ReEmpty,
|
||||||
|
|
||||||
/// Erased region, used by trait selection, in MIR and during trans.
|
/// Erased region, used by trait selection, in MIR and during codegen.
|
||||||
ReErased,
|
ReErased,
|
||||||
|
|
||||||
/// These are regions bound in the "defining type" for a
|
/// These are regions bound in the "defining type" for a
|
||||||
|
|
|
@ -1135,7 +1135,7 @@ define_print! {
|
||||||
})?
|
})?
|
||||||
} else {
|
} else {
|
||||||
// cross-crate closure types should only be
|
// cross-crate closure types should only be
|
||||||
// visible in trans bug reports, I imagine.
|
// visible in codegen bug reports, I imagine.
|
||||||
write!(f, "@{:?}", did)?;
|
write!(f, "@{:?}", did)?;
|
||||||
let mut sep = " ";
|
let mut sep = " ";
|
||||||
for (index, upvar_ty) in upvar_tys.enumerate() {
|
for (index, upvar_ty) in upvar_tys.enumerate() {
|
||||||
|
@ -1175,7 +1175,7 @@ define_print! {
|
||||||
})?
|
})?
|
||||||
} else {
|
} else {
|
||||||
// cross-crate closure types should only be
|
// cross-crate closure types should only be
|
||||||
// visible in trans bug reports, I imagine.
|
// visible in codegen bug reports, I imagine.
|
||||||
write!(f, "@{:?}", did)?;
|
write!(f, "@{:?}", did)?;
|
||||||
let mut sep = " ";
|
let mut sep = " ";
|
||||||
for (index, upvar_ty) in upvar_tys.enumerate() {
|
for (index, upvar_ty) in upvar_tys.enumerate() {
|
||||||
|
|
|
@ -1126,7 +1126,7 @@ fn foo(a: [D; 10], b: [D; 10], i: i32, t: bool) -> D {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
There are a number of ways that the trans backend could choose to
|
There are a number of ways that the codegen backend could choose to
|
||||||
compile this (e.g. a `[bool; 10]` array for each such moved array;
|
compile this (e.g. a `[bool; 10]` array for each such moved array;
|
||||||
or an `Option<usize>` for each moved array). From the viewpoint of the
|
or an `Option<usize>` for each moved array). From the viewpoint of the
|
||||||
borrow-checker, the important thing is to record what kind of fragment
|
borrow-checker, the important thing is to record what kind of fragment
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
[package]
|
[package]
|
||||||
authors = ["The Rust Project Developers"]
|
authors = ["The Rust Project Developers"]
|
||||||
name = "rustc_trans"
|
name = "rustc_codegen_llvm"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "rustc_trans"
|
name = "rustc_codegen_llvm"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
crate-type = ["dylib"]
|
crate-type = ["dylib"]
|
||||||
test = false
|
test = false
|
||||||
|
@ -27,7 +27,7 @@ rustc_errors = { path = "../librustc_errors" }
|
||||||
rustc_incremental = { path = "../librustc_incremental" }
|
rustc_incremental = { path = "../librustc_incremental" }
|
||||||
rustc_llvm = { path = "../librustc_llvm" }
|
rustc_llvm = { path = "../librustc_llvm" }
|
||||||
rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
|
rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
|
||||||
rustc_trans_utils = { path = "../librustc_trans_utils" }
|
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
|
||||||
rustc_mir = { path = "../librustc_mir" }
|
rustc_mir = { path = "../librustc_mir" }
|
||||||
serialize = { path = "../libserialize" }
|
serialize = { path = "../libserialize" }
|
||||||
syntax = { path = "../libsyntax" }
|
syntax = { path = "../libsyntax" }
|
||||||
|
@ -43,7 +43,7 @@ env_logger = { version = "0.5", default-features = false }
|
||||||
# `rustc` driver script communicate this.
|
# `rustc` driver script communicate this.
|
||||||
jemalloc = ["rustc_target/jemalloc"]
|
jemalloc = ["rustc_target/jemalloc"]
|
||||||
|
|
||||||
# This is used to convince Cargo to separately cache builds of `rustc_trans`
|
# This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm`
|
||||||
# when this option is enabled or not. That way we can build two, cache two
|
# when this option is enabled or not. That way we can build two, cache two
|
||||||
# artifacts, and have nice speedy rebuilds.
|
# artifacts, and have nice speedy rebuilds.
|
||||||
emscripten = ["rustc_llvm/emscripten"]
|
emscripten = ["rustc_llvm/emscripten"]
|
7
src/librustc_codegen_llvm/README.md
Normal file
7
src/librustc_codegen_llvm/README.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
The `codegen` crate contains the code to convert from MIR into LLVM IR,
|
||||||
|
and then from LLVM IR into machine code. In general it contains code
|
||||||
|
that runs towards the end of the compilation process.
|
||||||
|
|
||||||
|
For more information about how codegen works, see the [rustc guide].
|
||||||
|
|
||||||
|
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/codegen.html
|
|
@ -20,7 +20,7 @@ use rustc_allocator::{ALLOCATOR_METHODS, AllocatorTy};
|
||||||
use ModuleLlvm;
|
use ModuleLlvm;
|
||||||
use llvm::{self, False, True};
|
use llvm::{self, False, True};
|
||||||
|
|
||||||
pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
|
pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
|
||||||
let llcx = mods.llcx;
|
let llcx = mods.llcx;
|
||||||
let llmod = mods.llmod;
|
let llmod = mods.llmod;
|
||||||
let usize = match &tcx.sess.target.target.target_pointer_width[..] {
|
let usize = match &tcx.sess.target.target.target_pointer_width[..] {
|
|
@ -8,8 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//! # Translation of inline assembly.
|
|
||||||
|
|
||||||
use llvm::{self, ValueRef};
|
use llvm::{self, ValueRef};
|
||||||
use common::*;
|
use common::*;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
|
@ -26,7 +24,7 @@ use syntax::ast::AsmDialect;
|
||||||
use libc::{c_uint, c_char};
|
use libc::{c_uint, c_char};
|
||||||
|
|
||||||
// Take an inline assembly expression and splat it out via LLVM
|
// Take an inline assembly expression and splat it out via LLVM
|
||||||
pub fn trans_inline_asm<'a, 'tcx>(
|
pub fn codegen_inline_asm<'a, 'tcx>(
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
ia: &hir::InlineAsm,
|
ia: &hir::InlineAsm,
|
||||||
outputs: Vec<PlaceRef<'tcx>>,
|
outputs: Vec<PlaceRef<'tcx>>,
|
||||||
|
@ -120,7 +118,7 @@ pub fn trans_inline_asm<'a, 'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
pub fn codegen_global_asm<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
ga: &hir::GlobalAsm) {
|
ga: &hir::GlobalAsm) {
|
||||||
let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
|
let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
|
||||||
unsafe {
|
unsafe {
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
use rustc::hir::{self, TransFnAttrFlags};
|
use rustc::hir::{self, CodegenFnAttrFlags};
|
||||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
|
@ -118,34 +118,34 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
|
||||||
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
|
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
|
||||||
/// attributes.
|
/// attributes.
|
||||||
pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
|
pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
|
||||||
let trans_fn_attrs = cx.tcx.trans_fn_attrs(id);
|
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(id);
|
||||||
|
|
||||||
inline(llfn, trans_fn_attrs.inline);
|
inline(llfn, codegen_fn_attrs.inline);
|
||||||
|
|
||||||
set_frame_pointer_elimination(cx, llfn);
|
set_frame_pointer_elimination(cx, llfn);
|
||||||
set_probestack(cx, llfn);
|
set_probestack(cx, llfn);
|
||||||
|
|
||||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::COLD) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
|
||||||
Attribute::Cold.apply_llfn(Function, llfn);
|
Attribute::Cold.apply_llfn(Function, llfn);
|
||||||
}
|
}
|
||||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::NAKED) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||||
naked(llfn, true);
|
naked(llfn, true);
|
||||||
}
|
}
|
||||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::ALLOCATOR) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
|
||||||
Attribute::NoAlias.apply_llfn(
|
Attribute::NoAlias.apply_llfn(
|
||||||
llvm::AttributePlace::ReturnValue, llfn);
|
llvm::AttributePlace::ReturnValue, llfn);
|
||||||
}
|
}
|
||||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::UNWIND) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
|
||||||
unwind(llfn, true);
|
unwind(llfn, true);
|
||||||
}
|
}
|
||||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
|
||||||
unwind(llfn, false);
|
unwind(llfn, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let features = llvm_target_features(cx.tcx.sess)
|
let features = llvm_target_features(cx.tcx.sess)
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.chain(
|
.chain(
|
||||||
trans_fn_attrs.target_features
|
codegen_fn_attrs.target_features
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| {
|
.map(|f| {
|
||||||
let feature = &*f.as_str();
|
let feature = &*f.as_str();
|
|
@ -24,7 +24,7 @@ use rustc::session::search_paths::PathKind;
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::middle::cstore::{NativeLibrary, LibSource, NativeLibraryKind};
|
use rustc::middle::cstore::{NativeLibrary, LibSource, NativeLibraryKind};
|
||||||
use rustc::middle::dependency_format::Linkage;
|
use rustc::middle::dependency_format::Linkage;
|
||||||
use {CrateTranslation, CrateInfo};
|
use {CodegenResults, CrateInfo};
|
||||||
use rustc::util::common::time;
|
use rustc::util::common::time;
|
||||||
use rustc::util::fs::fix_windows_verbatim_for_gcc;
|
use rustc::util::fs::fix_windows_verbatim_for_gcc;
|
||||||
use rustc::hir::def_id::CrateNum;
|
use rustc::hir::def_id::CrateNum;
|
||||||
|
@ -52,7 +52,7 @@ pub const METADATA_MODULE_NAME: &'static str = "crate.metadata";
|
||||||
// same as for metadata above, but for allocator shim
|
// same as for metadata above, but for allocator shim
|
||||||
pub const ALLOCATOR_MODULE_NAME: &'static str = "crate.allocator";
|
pub const ALLOCATOR_MODULE_NAME: &'static str = "crate.allocator";
|
||||||
|
|
||||||
pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
|
pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
|
||||||
invalid_output_for_target, build_link_meta, out_filename,
|
invalid_output_for_target, build_link_meta, out_filename,
|
||||||
check_file_is_writeable};
|
check_file_is_writeable};
|
||||||
|
|
||||||
|
@ -141,14 +141,14 @@ pub fn remove(sess: &Session, path: &Path) {
|
||||||
/// Perform the linkage portion of the compilation phase. This will generate all
|
/// Perform the linkage portion of the compilation phase. This will generate all
|
||||||
/// of the requested outputs for this compilation session.
|
/// of the requested outputs for this compilation session.
|
||||||
pub(crate) fn link_binary(sess: &Session,
|
pub(crate) fn link_binary(sess: &Session,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
crate_name: &str) -> Vec<PathBuf> {
|
crate_name: &str) -> Vec<PathBuf> {
|
||||||
let mut out_filenames = Vec::new();
|
let mut out_filenames = Vec::new();
|
||||||
for &crate_type in sess.crate_types.borrow().iter() {
|
for &crate_type in sess.crate_types.borrow().iter() {
|
||||||
// Ignore executable crates if we have -Z no-trans, as they will error.
|
// Ignore executable crates if we have -Z no-codegen, as they will error.
|
||||||
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
|
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
|
||||||
if (sess.opts.debugging_opts.no_trans || !sess.opts.output_types.should_trans()) &&
|
if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen()) &&
|
||||||
!output_metadata &&
|
!output_metadata &&
|
||||||
crate_type == config::CrateTypeExecutable {
|
crate_type == config::CrateTypeExecutable {
|
||||||
continue;
|
continue;
|
||||||
|
@ -159,7 +159,7 @@ pub(crate) fn link_binary(sess: &Session,
|
||||||
crate_type, sess.opts.target_triple);
|
crate_type, sess.opts.target_triple);
|
||||||
}
|
}
|
||||||
let mut out_files = link_binary_output(sess,
|
let mut out_files = link_binary_output(sess,
|
||||||
trans,
|
codegen_results,
|
||||||
crate_type,
|
crate_type,
|
||||||
outputs,
|
outputs,
|
||||||
crate_name);
|
crate_name);
|
||||||
|
@ -168,20 +168,20 @@ pub(crate) fn link_binary(sess: &Session,
|
||||||
|
|
||||||
// Remove the temporary object file and metadata if we aren't saving temps
|
// Remove the temporary object file and metadata if we aren't saving temps
|
||||||
if !sess.opts.cg.save_temps {
|
if !sess.opts.cg.save_temps {
|
||||||
if sess.opts.output_types.should_trans() &&
|
if sess.opts.output_types.should_codegen() &&
|
||||||
!preserve_objects_for_their_debuginfo(sess)
|
!preserve_objects_for_their_debuginfo(sess)
|
||||||
{
|
{
|
||||||
for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) {
|
for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
|
||||||
remove(sess, obj);
|
remove(sess, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for obj in trans.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
|
for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
|
||||||
remove(sess, obj);
|
remove(sess, obj);
|
||||||
}
|
}
|
||||||
if let Some(ref obj) = trans.metadata_module.object {
|
if let Some(ref obj) = codegen_results.metadata_module.object {
|
||||||
remove(sess, obj);
|
remove(sess, obj);
|
||||||
}
|
}
|
||||||
if let Some(ref allocator) = trans.allocator_module {
|
if let Some(ref allocator) = codegen_results.allocator_module {
|
||||||
if let Some(ref obj) = allocator.object {
|
if let Some(ref obj) = allocator.object {
|
||||||
remove(sess, obj);
|
remove(sess, obj);
|
||||||
}
|
}
|
||||||
|
@ -304,11 +304,11 @@ pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link_binary_output(sess: &Session,
|
fn link_binary_output(sess: &Session,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
crate_type: config::CrateType,
|
crate_type: config::CrateType,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
crate_name: &str) -> Vec<PathBuf> {
|
crate_name: &str) -> Vec<PathBuf> {
|
||||||
for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) {
|
for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
|
||||||
check_file_is_writeable(obj, sess);
|
check_file_is_writeable(obj, sess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ fn link_binary_output(sess: &Session,
|
||||||
Ok(tmpdir) => tmpdir,
|
Ok(tmpdir) => tmpdir,
|
||||||
Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
|
Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
|
||||||
};
|
};
|
||||||
let metadata = emit_metadata(sess, trans, &metadata_tmpdir);
|
let metadata = emit_metadata(sess, codegen_results, &metadata_tmpdir);
|
||||||
if let Err(e) = fs::rename(metadata, &out_filename) {
|
if let Err(e) = fs::rename(metadata, &out_filename) {
|
||||||
sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
|
sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
|
||||||
}
|
}
|
||||||
|
@ -337,21 +337,21 @@ fn link_binary_output(sess: &Session,
|
||||||
Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
|
Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if outputs.outputs.should_trans() {
|
if outputs.outputs.should_codegen() {
|
||||||
let out_filename = out_filename(sess, crate_type, outputs, crate_name);
|
let out_filename = out_filename(sess, crate_type, outputs, crate_name);
|
||||||
match crate_type {
|
match crate_type {
|
||||||
config::CrateTypeRlib => {
|
config::CrateTypeRlib => {
|
||||||
link_rlib(sess,
|
link_rlib(sess,
|
||||||
trans,
|
codegen_results,
|
||||||
RlibFlavor::Normal,
|
RlibFlavor::Normal,
|
||||||
&out_filename,
|
&out_filename,
|
||||||
&tmpdir).build();
|
&tmpdir).build();
|
||||||
}
|
}
|
||||||
config::CrateTypeStaticlib => {
|
config::CrateTypeStaticlib => {
|
||||||
link_staticlib(sess, trans, &out_filename, &tmpdir);
|
link_staticlib(sess, codegen_results, &out_filename, &tmpdir);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
link_natively(sess, crate_type, &out_filename, trans, tmpdir.path());
|
link_natively(sess, crate_type, &out_filename, codegen_results, tmpdir.path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out_filenames.push(out_filename);
|
out_filenames.push(out_filename);
|
||||||
|
@ -388,10 +388,10 @@ fn archive_config<'a>(sess: &'a Session,
|
||||||
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
|
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
|
||||||
/// directory being searched for `extern crate` (observing an incomplete file).
|
/// directory being searched for `extern crate` (observing an incomplete file).
|
||||||
/// The returned path is the temporary file containing the complete metadata.
|
/// The returned path is the temporary file containing the complete metadata.
|
||||||
fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, tmpdir: &TempDir)
|
fn emit_metadata<'a>(sess: &'a Session, codegen_results: &CodegenResults, tmpdir: &TempDir)
|
||||||
-> PathBuf {
|
-> PathBuf {
|
||||||
let out_filename = tmpdir.path().join(METADATA_FILENAME);
|
let out_filename = tmpdir.path().join(METADATA_FILENAME);
|
||||||
let result = fs::write(&out_filename, &trans.metadata.raw_data);
|
let result = fs::write(&out_filename, &codegen_results.metadata.raw_data);
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
|
sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
|
||||||
|
@ -412,14 +412,14 @@ enum RlibFlavor {
|
||||||
// all of the object files from native libraries. This is done by unzipping
|
// all of the object files from native libraries. This is done by unzipping
|
||||||
// native libraries and inserting all of the contents into this archive.
|
// native libraries and inserting all of the contents into this archive.
|
||||||
fn link_rlib<'a>(sess: &'a Session,
|
fn link_rlib<'a>(sess: &'a Session,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
flavor: RlibFlavor,
|
flavor: RlibFlavor,
|
||||||
out_filename: &Path,
|
out_filename: &Path,
|
||||||
tmpdir: &TempDir) -> ArchiveBuilder<'a> {
|
tmpdir: &TempDir) -> ArchiveBuilder<'a> {
|
||||||
info!("preparing rlib to {:?}", out_filename);
|
info!("preparing rlib to {:?}", out_filename);
|
||||||
let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None));
|
let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None));
|
||||||
|
|
||||||
for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) {
|
for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
|
||||||
ab.add_file(obj);
|
ab.add_file(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +439,7 @@ fn link_rlib<'a>(sess: &'a Session,
|
||||||
// feature then we'll need to figure out how to record what objects were
|
// feature then we'll need to figure out how to record what objects were
|
||||||
// loaded from the libraries found here and then encode that into the
|
// loaded from the libraries found here and then encode that into the
|
||||||
// metadata of the rlib we're generating somehow.
|
// metadata of the rlib we're generating somehow.
|
||||||
for lib in trans.crate_info.used_libraries.iter() {
|
for lib in codegen_results.crate_info.used_libraries.iter() {
|
||||||
match lib.kind {
|
match lib.kind {
|
||||||
NativeLibraryKind::NativeStatic => {}
|
NativeLibraryKind::NativeStatic => {}
|
||||||
NativeLibraryKind::NativeStaticNobundle |
|
NativeLibraryKind::NativeStaticNobundle |
|
||||||
|
@ -478,11 +478,15 @@ fn link_rlib<'a>(sess: &'a Session,
|
||||||
RlibFlavor::Normal => {
|
RlibFlavor::Normal => {
|
||||||
// Instead of putting the metadata in an object file section, rlibs
|
// Instead of putting the metadata in an object file section, rlibs
|
||||||
// contain the metadata in a separate file.
|
// contain the metadata in a separate file.
|
||||||
ab.add_file(&emit_metadata(sess, trans, tmpdir));
|
ab.add_file(&emit_metadata(sess, codegen_results, tmpdir));
|
||||||
|
|
||||||
// For LTO purposes, the bytecode of this library is also inserted
|
// For LTO purposes, the bytecode of this library is also inserted
|
||||||
// into the archive.
|
// into the archive.
|
||||||
for bytecode in trans.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) {
|
for bytecode in codegen_results
|
||||||
|
.modules
|
||||||
|
.iter()
|
||||||
|
.filter_map(|m| m.bytecode_compressed.as_ref())
|
||||||
|
{
|
||||||
ab.add_file(bytecode);
|
ab.add_file(bytecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +499,7 @@ fn link_rlib<'a>(sess: &'a Session,
|
||||||
}
|
}
|
||||||
|
|
||||||
RlibFlavor::StaticlibBase => {
|
RlibFlavor::StaticlibBase => {
|
||||||
let obj = trans.allocator_module
|
let obj = codegen_results.allocator_module
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|m| m.object.as_ref());
|
.and_then(|m| m.object.as_ref());
|
||||||
if let Some(obj) = obj {
|
if let Some(obj) = obj {
|
||||||
|
@ -520,19 +524,19 @@ fn link_rlib<'a>(sess: &'a Session,
|
||||||
// link in the metadata object file (and also don't prepare the archive with a
|
// link in the metadata object file (and also don't prepare the archive with a
|
||||||
// metadata file).
|
// metadata file).
|
||||||
fn link_staticlib(sess: &Session,
|
fn link_staticlib(sess: &Session,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
out_filename: &Path,
|
out_filename: &Path,
|
||||||
tempdir: &TempDir) {
|
tempdir: &TempDir) {
|
||||||
let mut ab = link_rlib(sess,
|
let mut ab = link_rlib(sess,
|
||||||
trans,
|
codegen_results,
|
||||||
RlibFlavor::StaticlibBase,
|
RlibFlavor::StaticlibBase,
|
||||||
out_filename,
|
out_filename,
|
||||||
tempdir);
|
tempdir);
|
||||||
let mut all_native_libs = vec![];
|
let mut all_native_libs = vec![];
|
||||||
|
|
||||||
let res = each_linked_rlib(sess, &trans.crate_info, &mut |cnum, path| {
|
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
|
||||||
let name = &trans.crate_info.crate_name[&cnum];
|
let name = &codegen_results.crate_info.crate_name[&cnum];
|
||||||
let native_libs = &trans.crate_info.native_libraries[&cnum];
|
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||||
|
|
||||||
// Here when we include the rlib into our staticlib we need to make a
|
// Here when we include the rlib into our staticlib we need to make a
|
||||||
// decision whether to include the extra object files along the way.
|
// decision whether to include the extra object files along the way.
|
||||||
|
@ -554,10 +558,10 @@ fn link_staticlib(sess: &Session,
|
||||||
ab.add_rlib(path,
|
ab.add_rlib(path,
|
||||||
&name.as_str(),
|
&name.as_str(),
|
||||||
is_full_lto_enabled(sess) &&
|
is_full_lto_enabled(sess) &&
|
||||||
!ignored_for_lto(sess, &trans.crate_info, cnum),
|
!ignored_for_lto(sess, &codegen_results.crate_info, cnum),
|
||||||
skip_object_files).unwrap();
|
skip_object_files).unwrap();
|
||||||
|
|
||||||
all_native_libs.extend(trans.crate_info.native_libraries[&cnum].iter().cloned());
|
all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
|
||||||
});
|
});
|
||||||
if let Err(e) = res {
|
if let Err(e) = res {
|
||||||
sess.fatal(&e);
|
sess.fatal(&e);
|
||||||
|
@ -609,7 +613,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) {
|
||||||
fn link_natively(sess: &Session,
|
fn link_natively(sess: &Session,
|
||||||
crate_type: config::CrateType,
|
crate_type: config::CrateType,
|
||||||
out_filename: &Path,
|
out_filename: &Path,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
tmpdir: &Path) {
|
tmpdir: &Path) {
|
||||||
info!("preparing {:?} to {:?}", crate_type, out_filename);
|
info!("preparing {:?} to {:?}", crate_type, out_filename);
|
||||||
let flavor = sess.linker_flavor();
|
let flavor = sess.linker_flavor();
|
||||||
|
@ -662,9 +666,9 @@ fn link_natively(sess: &Session,
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut linker = trans.linker_info.to_linker(cmd, &sess);
|
let mut linker = codegen_results.linker_info.to_linker(cmd, &sess);
|
||||||
link_args(&mut *linker, sess, crate_type, tmpdir,
|
link_args(&mut *linker, sess, crate_type, tmpdir,
|
||||||
out_filename, trans);
|
out_filename, codegen_results);
|
||||||
cmd = linker.finalize();
|
cmd = linker.finalize();
|
||||||
}
|
}
|
||||||
if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
|
if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
|
||||||
|
@ -842,9 +846,9 @@ fn link_natively(sess: &Session,
|
||||||
}
|
}
|
||||||
|
|
||||||
if sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown") {
|
if sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown") {
|
||||||
wasm::rewrite_imports(&out_filename, &trans.crate_info.wasm_imports);
|
wasm::rewrite_imports(&out_filename, &codegen_results.crate_info.wasm_imports);
|
||||||
wasm::add_custom_sections(&out_filename,
|
wasm::add_custom_sections(&out_filename,
|
||||||
&trans.crate_info.wasm_custom_sections);
|
&codegen_results.crate_info.wasm_custom_sections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,7 +999,7 @@ fn link_args(cmd: &mut Linker,
|
||||||
crate_type: config::CrateType,
|
crate_type: config::CrateType,
|
||||||
tmpdir: &Path,
|
tmpdir: &Path,
|
||||||
out_filename: &Path,
|
out_filename: &Path,
|
||||||
trans: &CrateTranslation) {
|
codegen_results: &CodegenResults) {
|
||||||
|
|
||||||
// Linker plugins should be specified early in the list of arguments
|
// Linker plugins should be specified early in the list of arguments
|
||||||
cmd.cross_lang_lto();
|
cmd.cross_lang_lto();
|
||||||
|
@ -1008,14 +1012,14 @@ fn link_args(cmd: &mut Linker,
|
||||||
let t = &sess.target.target;
|
let t = &sess.target.target;
|
||||||
|
|
||||||
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
|
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
|
||||||
for obj in trans.modules.iter().filter_map(|m| m.object.as_ref()) {
|
for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
|
||||||
cmd.add_object(obj);
|
cmd.add_object(obj);
|
||||||
}
|
}
|
||||||
cmd.output_filename(out_filename);
|
cmd.output_filename(out_filename);
|
||||||
|
|
||||||
if crate_type == config::CrateTypeExecutable &&
|
if crate_type == config::CrateTypeExecutable &&
|
||||||
sess.target.target.options.is_like_windows {
|
sess.target.target.options.is_like_windows {
|
||||||
if let Some(ref s) = trans.windows_subsystem {
|
if let Some(ref s) = codegen_results.windows_subsystem {
|
||||||
cmd.subsystem(s);
|
cmd.subsystem(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1032,12 +1036,12 @@ fn link_args(cmd: &mut Linker,
|
||||||
// object file, so we link that in here.
|
// object file, so we link that in here.
|
||||||
if crate_type == config::CrateTypeDylib ||
|
if crate_type == config::CrateTypeDylib ||
|
||||||
crate_type == config::CrateTypeProcMacro {
|
crate_type == config::CrateTypeProcMacro {
|
||||||
if let Some(obj) = trans.metadata_module.object.as_ref() {
|
if let Some(obj) = codegen_results.metadata_module.object.as_ref() {
|
||||||
cmd.add_object(obj);
|
cmd.add_object(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let obj = trans.allocator_module
|
let obj = codegen_results.allocator_module
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|m| m.object.as_ref());
|
.and_then(|m| m.object.as_ref());
|
||||||
if let Some(obj) = obj {
|
if let Some(obj) = obj {
|
||||||
|
@ -1051,7 +1055,7 @@ fn link_args(cmd: &mut Linker,
|
||||||
cmd.gc_sections(keep_metadata);
|
cmd.gc_sections(keep_metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
let used_link_args = &trans.crate_info.link_args;
|
let used_link_args = &codegen_results.crate_info.link_args;
|
||||||
|
|
||||||
if crate_type == config::CrateTypeExecutable {
|
if crate_type == config::CrateTypeExecutable {
|
||||||
let mut position_independent_executable = false;
|
let mut position_independent_executable = false;
|
||||||
|
@ -1140,9 +1144,9 @@ fn link_args(cmd: &mut Linker,
|
||||||
// link line. And finally upstream native libraries can't depend on anything
|
// link line. And finally upstream native libraries can't depend on anything
|
||||||
// in this DAG so far because they're only dylibs and dylibs can only depend
|
// in this DAG so far because they're only dylibs and dylibs can only depend
|
||||||
// on other dylibs (e.g. other native deps).
|
// on other dylibs (e.g. other native deps).
|
||||||
add_local_native_libraries(cmd, sess, trans);
|
add_local_native_libraries(cmd, sess, codegen_results);
|
||||||
add_upstream_rust_crates(cmd, sess, trans, crate_type, tmpdir);
|
add_upstream_rust_crates(cmd, sess, codegen_results, crate_type, tmpdir);
|
||||||
add_upstream_native_libraries(cmd, sess, trans, crate_type);
|
add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
|
||||||
|
|
||||||
// Tell the linker what we're doing.
|
// Tell the linker what we're doing.
|
||||||
if crate_type != config::CrateTypeExecutable {
|
if crate_type != config::CrateTypeExecutable {
|
||||||
|
@ -1171,7 +1175,7 @@ fn link_args(cmd: &mut Linker,
|
||||||
path
|
path
|
||||||
};
|
};
|
||||||
let mut rpath_config = RPathConfig {
|
let mut rpath_config = RPathConfig {
|
||||||
used_crates: &trans.crate_info.used_crates_dynamic,
|
used_crates: &codegen_results.crate_info.used_crates_dynamic,
|
||||||
out_filename: out_filename.to_path_buf(),
|
out_filename: out_filename.to_path_buf(),
|
||||||
has_rpath: sess.target.target.options.has_rpath,
|
has_rpath: sess.target.target.options.has_rpath,
|
||||||
is_like_osx: sess.target.target.options.is_like_osx,
|
is_like_osx: sess.target.target.options.is_like_osx,
|
||||||
|
@ -1203,7 +1207,7 @@ fn link_args(cmd: &mut Linker,
|
||||||
// may have their native library pulled in above.
|
// may have their native library pulled in above.
|
||||||
fn add_local_native_libraries(cmd: &mut Linker,
|
fn add_local_native_libraries(cmd: &mut Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
trans: &CrateTranslation) {
|
codegen_results: &CodegenResults) {
|
||||||
sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| {
|
sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| {
|
||||||
match k {
|
match k {
|
||||||
PathKind::Framework => { cmd.framework_path(path); }
|
PathKind::Framework => { cmd.framework_path(path); }
|
||||||
|
@ -1211,7 +1215,7 @@ fn add_local_native_libraries(cmd: &mut Linker,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let relevant_libs = trans.crate_info.used_libraries.iter().filter(|l| {
|
let relevant_libs = codegen_results.crate_info.used_libraries.iter().filter(|l| {
|
||||||
relevant_lib(sess, l)
|
relevant_lib(sess, l)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1234,7 +1238,7 @@ fn add_local_native_libraries(cmd: &mut Linker,
|
||||||
// the intermediate rlib version)
|
// the intermediate rlib version)
|
||||||
fn add_upstream_rust_crates(cmd: &mut Linker,
|
fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
crate_type: config::CrateType,
|
crate_type: config::CrateType,
|
||||||
tmpdir: &Path) {
|
tmpdir: &Path) {
|
||||||
// All of the heavy lifting has previously been accomplished by the
|
// All of the heavy lifting has previously been accomplished by the
|
||||||
|
@ -1250,7 +1254,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
|
|
||||||
// Invoke get_used_crates to ensure that we get a topological sorting of
|
// Invoke get_used_crates to ensure that we get a topological sorting of
|
||||||
// crates.
|
// crates.
|
||||||
let deps = &trans.crate_info.used_crates_dynamic;
|
let deps = &codegen_results.crate_info.used_crates_dynamic;
|
||||||
|
|
||||||
// There's a few internal crates in the standard library (aka libcore and
|
// There's a few internal crates in the standard library (aka libcore and
|
||||||
// libstd) which actually have a circular dependence upon one another. This
|
// libstd) which actually have a circular dependence upon one another. This
|
||||||
|
@ -1273,7 +1277,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
let mut group_end = None;
|
let mut group_end = None;
|
||||||
let mut group_start = None;
|
let mut group_start = None;
|
||||||
let mut end_with = FxHashSet();
|
let mut end_with = FxHashSet();
|
||||||
let info = &trans.crate_info;
|
let info = &codegen_results.crate_info;
|
||||||
for &(cnum, _) in deps.iter().rev() {
|
for &(cnum, _) in deps.iter().rev() {
|
||||||
if let Some(missing) = info.missing_lang_items.get(&cnum) {
|
if let Some(missing) = info.missing_lang_items.get(&cnum) {
|
||||||
end_with.extend(missing.iter().cloned());
|
end_with.extend(missing.iter().cloned());
|
||||||
|
@ -1305,24 +1309,24 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
// We may not pass all crates through to the linker. Some crates may
|
// We may not pass all crates through to the linker. Some crates may
|
||||||
// appear statically in an existing dylib, meaning we'll pick up all the
|
// appear statically in an existing dylib, meaning we'll pick up all the
|
||||||
// symbols from the dylib.
|
// symbols from the dylib.
|
||||||
let src = &trans.crate_info.used_crate_source[&cnum];
|
let src = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||||
match data[cnum.as_usize() - 1] {
|
match data[cnum.as_usize() - 1] {
|
||||||
_ if trans.crate_info.profiler_runtime == Some(cnum) => {
|
_ if codegen_results.crate_info.profiler_runtime == Some(cnum) => {
|
||||||
add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
|
add_static_crate(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
|
||||||
}
|
}
|
||||||
_ if trans.crate_info.sanitizer_runtime == Some(cnum) => {
|
_ if codegen_results.crate_info.sanitizer_runtime == Some(cnum) => {
|
||||||
link_sanitizer_runtime(cmd, sess, trans, tmpdir, cnum);
|
link_sanitizer_runtime(cmd, sess, codegen_results, tmpdir, cnum);
|
||||||
}
|
}
|
||||||
// compiler-builtins are always placed last to ensure that they're
|
// compiler-builtins are always placed last to ensure that they're
|
||||||
// linked correctly.
|
// linked correctly.
|
||||||
_ if trans.crate_info.compiler_builtins == Some(cnum) => {
|
_ if codegen_results.crate_info.compiler_builtins == Some(cnum) => {
|
||||||
assert!(compiler_builtins.is_none());
|
assert!(compiler_builtins.is_none());
|
||||||
compiler_builtins = Some(cnum);
|
compiler_builtins = Some(cnum);
|
||||||
}
|
}
|
||||||
Linkage::NotLinked |
|
Linkage::NotLinked |
|
||||||
Linkage::IncludedFromDylib => {}
|
Linkage::IncludedFromDylib => {}
|
||||||
Linkage::Static => {
|
Linkage::Static => {
|
||||||
add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
|
add_static_crate(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
|
||||||
}
|
}
|
||||||
Linkage::Dynamic => {
|
Linkage::Dynamic => {
|
||||||
add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0)
|
add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0)
|
||||||
|
@ -1340,7 +1344,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
// was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic`
|
// was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic`
|
||||||
// is used)
|
// is used)
|
||||||
if let Some(cnum) = compiler_builtins {
|
if let Some(cnum) = compiler_builtins {
|
||||||
add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
|
add_static_crate(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a library file-stem into a cc -l argument
|
// Converts a library file-stem into a cc -l argument
|
||||||
|
@ -1358,10 +1362,10 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
// linking it.
|
// linking it.
|
||||||
fn link_sanitizer_runtime(cmd: &mut Linker,
|
fn link_sanitizer_runtime(cmd: &mut Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
tmpdir: &Path,
|
tmpdir: &Path,
|
||||||
cnum: CrateNum) {
|
cnum: CrateNum) {
|
||||||
let src = &trans.crate_info.used_crate_source[&cnum];
|
let src = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||||
let cratepath = &src.rlib.as_ref().unwrap().0;
|
let cratepath = &src.rlib.as_ref().unwrap().0;
|
||||||
|
|
||||||
if sess.target.target.options.is_like_osx {
|
if sess.target.target.options.is_like_osx {
|
||||||
|
@ -1427,23 +1431,23 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
// we're at the end of the dependency chain.
|
// we're at the end of the dependency chain.
|
||||||
fn add_static_crate(cmd: &mut Linker,
|
fn add_static_crate(cmd: &mut Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
tmpdir: &Path,
|
tmpdir: &Path,
|
||||||
crate_type: config::CrateType,
|
crate_type: config::CrateType,
|
||||||
cnum: CrateNum) {
|
cnum: CrateNum) {
|
||||||
let src = &trans.crate_info.used_crate_source[&cnum];
|
let src = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||||
let cratepath = &src.rlib.as_ref().unwrap().0;
|
let cratepath = &src.rlib.as_ref().unwrap().0;
|
||||||
|
|
||||||
// See the comment above in `link_staticlib` and `link_rlib` for why if
|
// See the comment above in `link_staticlib` and `link_rlib` for why if
|
||||||
// there's a static library that's not relevant we skip all object
|
// there's a static library that's not relevant we skip all object
|
||||||
// files.
|
// files.
|
||||||
let native_libs = &trans.crate_info.native_libraries[&cnum];
|
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
|
||||||
let skip_native = native_libs.iter().any(|lib| {
|
let skip_native = native_libs.iter().any(|lib| {
|
||||||
lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib)
|
lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!is_full_lto_enabled(sess) ||
|
if (!is_full_lto_enabled(sess) ||
|
||||||
ignored_for_lto(sess, &trans.crate_info, cnum)) &&
|
ignored_for_lto(sess, &codegen_results.crate_info, cnum)) &&
|
||||||
crate_type != config::CrateTypeDylib &&
|
crate_type != config::CrateTypeDylib &&
|
||||||
!skip_native {
|
!skip_native {
|
||||||
cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
|
cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
|
||||||
|
@ -1499,7 +1503,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
let skip_because_lto = is_full_lto_enabled(sess) &&
|
let skip_because_lto = is_full_lto_enabled(sess) &&
|
||||||
is_rust_object &&
|
is_rust_object &&
|
||||||
(sess.target.target.options.no_builtins ||
|
(sess.target.target.options.no_builtins ||
|
||||||
!trans.crate_info.is_no_builtins.contains(&cnum));
|
!codegen_results.crate_info.is_no_builtins.contains(&cnum));
|
||||||
|
|
||||||
if skip_because_cfg_say_so || skip_because_lto {
|
if skip_because_cfg_say_so || skip_because_lto {
|
||||||
archive.remove_file(&f);
|
archive.remove_file(&f);
|
||||||
|
@ -1521,7 +1525,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
// compiler-builtins crate (e.g. compiler-rt) because it'll get
|
// compiler-builtins crate (e.g. compiler-rt) because it'll get
|
||||||
// repeatedly linked anyway.
|
// repeatedly linked anyway.
|
||||||
if crate_type == config::CrateTypeDylib &&
|
if crate_type == config::CrateTypeDylib &&
|
||||||
trans.crate_info.compiler_builtins != Some(cnum) {
|
codegen_results.crate_info.compiler_builtins != Some(cnum) {
|
||||||
cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
|
cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
|
||||||
} else {
|
} else {
|
||||||
cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst));
|
cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst));
|
||||||
|
@ -1567,7 +1571,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
|
||||||
// also be resolved in the target crate.
|
// also be resolved in the target crate.
|
||||||
fn add_upstream_native_libraries(cmd: &mut Linker,
|
fn add_upstream_native_libraries(cmd: &mut Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
trans: &CrateTranslation,
|
codegen_results: &CodegenResults,
|
||||||
crate_type: config::CrateType) {
|
crate_type: config::CrateType) {
|
||||||
// Be sure to use a topological sorting of crates because there may be
|
// Be sure to use a topological sorting of crates because there may be
|
||||||
// interdependencies between native libraries. When passing -nodefaultlibs,
|
// interdependencies between native libraries. When passing -nodefaultlibs,
|
||||||
|
@ -1581,9 +1585,9 @@ fn add_upstream_native_libraries(cmd: &mut Linker,
|
||||||
let formats = sess.dependency_formats.borrow();
|
let formats = sess.dependency_formats.borrow();
|
||||||
let data = formats.get(&crate_type).unwrap();
|
let data = formats.get(&crate_type).unwrap();
|
||||||
|
|
||||||
let crates = &trans.crate_info.used_crates_static;
|
let crates = &codegen_results.crate_info.used_crates_static;
|
||||||
for &(cnum, _) in crates {
|
for &(cnum, _) in crates {
|
||||||
for lib in trans.crate_info.native_libraries[&cnum].iter() {
|
for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
|
||||||
if !relevant_lib(sess, &lib) {
|
if !relevant_lib(sess, &lib) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
|
@ -641,7 +641,7 @@ impl<'a> Linker for MsvcLinker<'a> {
|
||||||
//
|
//
|
||||||
// The linker will read this `*.def` file and export all the symbols from
|
// The linker will read this `*.def` file and export all the symbols from
|
||||||
// the dynamic library. Note that this is not as simple as just exporting
|
// the dynamic library. Note that this is not as simple as just exporting
|
||||||
// all the symbols in the current crate (as specified by `trans.reachable`)
|
// all the symbols in the current crate (as specified by `codegen.reachable`)
|
||||||
// but rather we also need to possibly export the symbols of upstream
|
// but rather we also need to possibly export the symbols of upstream
|
||||||
// crates. Upstream rlibs may be linked statically to this dynamic library,
|
// crates. Upstream rlibs may be linked statically to this dynamic library,
|
||||||
// in which case they may continue to transitively be used and hence need
|
// in which case they may continue to transitively be used and hence need
|
|
@ -21,7 +21,7 @@ use rustc::middle::exported_symbols::SymbolExportLevel;
|
||||||
use rustc::session::config::{self, Lto};
|
use rustc::session::config::{self, Lto};
|
||||||
use rustc::util::common::time_ext;
|
use rustc::util::common::time_ext;
|
||||||
use time_graph::Timeline;
|
use time_graph::Timeline;
|
||||||
use {ModuleTranslation, ModuleLlvm, ModuleKind, ModuleSource};
|
use {ModuleCodegen, ModuleLlvm, ModuleKind, ModuleSource};
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
|
|
||||||
|
@ -42,45 +42,45 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum LtoModuleTranslation {
|
pub(crate) enum LtoModuleCodegen {
|
||||||
Fat {
|
Fat {
|
||||||
module: Option<ModuleTranslation>,
|
module: Option<ModuleCodegen>,
|
||||||
_serialized_bitcode: Vec<SerializedModule>,
|
_serialized_bitcode: Vec<SerializedModule>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Thin(ThinModule),
|
Thin(ThinModule),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LtoModuleTranslation {
|
impl LtoModuleCodegen {
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
LtoModuleTranslation::Fat { .. } => "everything",
|
LtoModuleCodegen::Fat { .. } => "everything",
|
||||||
LtoModuleTranslation::Thin(ref m) => m.name(),
|
LtoModuleCodegen::Thin(ref m) => m.name(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optimize this module within the given codegen context.
|
/// Optimize this module within the given codegen context.
|
||||||
///
|
///
|
||||||
/// This function is unsafe as it'll return a `ModuleTranslation` still
|
/// This function is unsafe as it'll return a `ModuleCodegen` still
|
||||||
/// points to LLVM data structures owned by this `LtoModuleTranslation`.
|
/// points to LLVM data structures owned by this `LtoModuleCodegen`.
|
||||||
/// It's intended that the module returned is immediately code generated and
|
/// It's intended that the module returned is immediately code generated and
|
||||||
/// dropped, and then this LTO module is dropped.
|
/// dropped, and then this LTO module is dropped.
|
||||||
pub(crate) unsafe fn optimize(&mut self,
|
pub(crate) unsafe fn optimize(&mut self,
|
||||||
cgcx: &CodegenContext,
|
cgcx: &CodegenContext,
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<ModuleTranslation, FatalError>
|
-> Result<ModuleCodegen, FatalError>
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
LtoModuleTranslation::Fat { ref mut module, .. } => {
|
LtoModuleCodegen::Fat { ref mut module, .. } => {
|
||||||
let trans = module.take().unwrap();
|
let module = module.take().unwrap();
|
||||||
let config = cgcx.config(trans.kind);
|
let config = cgcx.config(module.kind);
|
||||||
let llmod = trans.llvm().unwrap().llmod;
|
let llmod = module.llvm().unwrap().llmod;
|
||||||
let tm = trans.llvm().unwrap().tm;
|
let tm = module.llvm().unwrap().tm;
|
||||||
run_pass_manager(cgcx, tm, llmod, config, false);
|
run_pass_manager(cgcx, tm, llmod, config, false);
|
||||||
timeline.record("fat-done");
|
timeline.record("fat-done");
|
||||||
Ok(trans)
|
Ok(module)
|
||||||
}
|
}
|
||||||
LtoModuleTranslation::Thin(ref mut thin) => thin.optimize(cgcx, timeline),
|
LtoModuleCodegen::Thin(ref mut thin) => thin.optimize(cgcx, timeline),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,16 +89,16 @@ impl LtoModuleTranslation {
|
||||||
pub fn cost(&self) -> u64 {
|
pub fn cost(&self) -> u64 {
|
||||||
match *self {
|
match *self {
|
||||||
// Only one module with fat LTO, so the cost doesn't matter.
|
// Only one module with fat LTO, so the cost doesn't matter.
|
||||||
LtoModuleTranslation::Fat { .. } => 0,
|
LtoModuleCodegen::Fat { .. } => 0,
|
||||||
LtoModuleTranslation::Thin(ref m) => m.cost(),
|
LtoModuleCodegen::Thin(ref m) => m.cost(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run(cgcx: &CodegenContext,
|
pub(crate) fn run(cgcx: &CodegenContext,
|
||||||
modules: Vec<ModuleTranslation>,
|
modules: Vec<ModuleCodegen>,
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<Vec<LtoModuleTranslation>, FatalError>
|
-> Result<Vec<LtoModuleCodegen>, FatalError>
|
||||||
{
|
{
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
let export_threshold = match cgcx.lto {
|
let export_threshold = match cgcx.lto {
|
||||||
|
@ -201,11 +201,11 @@ pub(crate) fn run(cgcx: &CodegenContext,
|
||||||
|
|
||||||
fn fat_lto(cgcx: &CodegenContext,
|
fn fat_lto(cgcx: &CodegenContext,
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
mut modules: Vec<ModuleTranslation>,
|
mut modules: Vec<ModuleCodegen>,
|
||||||
mut serialized_modules: Vec<(SerializedModule, CString)>,
|
mut serialized_modules: Vec<(SerializedModule, CString)>,
|
||||||
symbol_white_list: &[*const libc::c_char],
|
symbol_white_list: &[*const libc::c_char],
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<Vec<LtoModuleTranslation>, FatalError>
|
-> Result<Vec<LtoModuleCodegen>, FatalError>
|
||||||
{
|
{
|
||||||
info!("going for a fat lto");
|
info!("going for a fat lto");
|
||||||
|
|
||||||
|
@ -228,18 +228,18 @@ fn fat_lto(cgcx: &CodegenContext,
|
||||||
(cost, i)
|
(cost, i)
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.expect("must be trans'ing at least one module");
|
.expect("must be codegen'ing at least one module");
|
||||||
let module = modules.remove(costliest_module);
|
let module = modules.remove(costliest_module);
|
||||||
let llmod = module.llvm().expect("can't lto pre-translated modules").llmod;
|
let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod;
|
||||||
info!("using {:?} as a base module", module.llmod_id);
|
info!("using {:?} as a base module", module.llmod_id);
|
||||||
|
|
||||||
// For all other modules we translated we'll need to link them into our own
|
// For all other modules we codegened we'll need to link them into our own
|
||||||
// bitcode. All modules were translated in their own LLVM context, however,
|
// bitcode. All modules were codegened in their own LLVM context, however,
|
||||||
// and we want to move everything to the same LLVM context. Currently the
|
// and we want to move everything to the same LLVM context. Currently the
|
||||||
// way we know of to do that is to serialize them to a string and them parse
|
// way we know of to do that is to serialize them to a string and them parse
|
||||||
// them later. Not great but hey, that's why it's "fat" LTO, right?
|
// them later. Not great but hey, that's why it's "fat" LTO, right?
|
||||||
for module in modules {
|
for module in modules {
|
||||||
let llvm = module.llvm().expect("can't lto pre-translated modules");
|
let llvm = module.llvm().expect("can't lto pre-codegened modules");
|
||||||
let buffer = ModuleBuffer::new(llvm.llmod);
|
let buffer = ModuleBuffer::new(llvm.llmod);
|
||||||
let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
|
let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
|
||||||
serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
|
serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
|
||||||
|
@ -284,7 +284,7 @@ fn fat_lto(cgcx: &CodegenContext,
|
||||||
}
|
}
|
||||||
timeline.record("passes");
|
timeline.record("passes");
|
||||||
|
|
||||||
Ok(vec![LtoModuleTranslation::Fat {
|
Ok(vec![LtoModuleCodegen::Fat {
|
||||||
module: Some(module),
|
module: Some(module),
|
||||||
_serialized_bitcode: serialized_bitcode,
|
_serialized_bitcode: serialized_bitcode,
|
||||||
}])
|
}])
|
||||||
|
@ -344,14 +344,14 @@ impl Drop for Linker {
|
||||||
///
|
///
|
||||||
/// With all that in mind, the function here is designed at specifically just
|
/// With all that in mind, the function here is designed at specifically just
|
||||||
/// calculating the *index* for ThinLTO. This index will then be shared amongst
|
/// calculating the *index* for ThinLTO. This index will then be shared amongst
|
||||||
/// all of the `LtoModuleTranslation` units returned below and destroyed once
|
/// all of the `LtoModuleCodegen` units returned below and destroyed once
|
||||||
/// they all go out of scope.
|
/// they all go out of scope.
|
||||||
fn thin_lto(diag_handler: &Handler,
|
fn thin_lto(diag_handler: &Handler,
|
||||||
modules: Vec<ModuleTranslation>,
|
modules: Vec<ModuleCodegen>,
|
||||||
serialized_modules: Vec<(SerializedModule, CString)>,
|
serialized_modules: Vec<(SerializedModule, CString)>,
|
||||||
symbol_white_list: &[*const libc::c_char],
|
symbol_white_list: &[*const libc::c_char],
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<Vec<LtoModuleTranslation>, FatalError>
|
-> Result<Vec<LtoModuleCodegen>, FatalError>
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
info!("going for that thin, thin LTO");
|
info!("going for that thin, thin LTO");
|
||||||
|
@ -369,7 +369,7 @@ fn thin_lto(diag_handler: &Handler,
|
||||||
// analysis!
|
// analysis!
|
||||||
for (i, module) in modules.iter().enumerate() {
|
for (i, module) in modules.iter().enumerate() {
|
||||||
info!("local module: {} - {}", i, module.llmod_id);
|
info!("local module: {} - {}", i, module.llmod_id);
|
||||||
let llvm = module.llvm().expect("can't lto pretranslated module");
|
let llvm = module.llvm().expect("can't lto precodegened module");
|
||||||
let name = CString::new(module.llmod_id.clone()).unwrap();
|
let name = CString::new(module.llmod_id.clone()).unwrap();
|
||||||
let buffer = ThinBuffer::new(llvm.llmod);
|
let buffer = ThinBuffer::new(llvm.llmod);
|
||||||
thin_modules.push(llvm::ThinLTOModule {
|
thin_modules.push(llvm::ThinLTOModule {
|
||||||
|
@ -431,7 +431,7 @@ fn thin_lto(diag_handler: &Handler,
|
||||||
// Throw our data in an `Arc` as we'll be sharing it across threads. We
|
// Throw our data in an `Arc` as we'll be sharing it across threads. We
|
||||||
// also put all memory referenced by the C++ data (buffers, ids, etc)
|
// also put all memory referenced by the C++ data (buffers, ids, etc)
|
||||||
// into the arc as well. After this we'll create a thin module
|
// into the arc as well. After this we'll create a thin module
|
||||||
// translation per module in this data.
|
// codegen per module in this data.
|
||||||
let shared = Arc::new(ThinShared {
|
let shared = Arc::new(ThinShared {
|
||||||
data,
|
data,
|
||||||
thin_buffers,
|
thin_buffers,
|
||||||
|
@ -439,7 +439,7 @@ fn thin_lto(diag_handler: &Handler,
|
||||||
module_names,
|
module_names,
|
||||||
});
|
});
|
||||||
Ok((0..shared.module_names.len()).map(|i| {
|
Ok((0..shared.module_names.len()).map(|i| {
|
||||||
LtoModuleTranslation::Thin(ThinModule {
|
LtoModuleCodegen::Thin(ThinModule {
|
||||||
shared: shared.clone(),
|
shared: shared.clone(),
|
||||||
idx: i,
|
idx: i,
|
||||||
})
|
})
|
||||||
|
@ -622,7 +622,7 @@ impl ThinModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
|
unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
|
||||||
-> Result<ModuleTranslation, FatalError>
|
-> Result<ModuleCodegen, FatalError>
|
||||||
{
|
{
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
let tm = (cgcx.tm_factory)().map_err(|e| {
|
let tm = (cgcx.tm_factory)().map_err(|e| {
|
||||||
|
@ -632,7 +632,7 @@ impl ThinModule {
|
||||||
// Right now the implementation we've got only works over serialized
|
// Right now the implementation we've got only works over serialized
|
||||||
// modules, so we create a fresh new LLVM context and parse the module
|
// modules, so we create a fresh new LLVM context and parse the module
|
||||||
// into that context. One day, however, we may do this for upstream
|
// into that context. One day, however, we may do this for upstream
|
||||||
// crates but for locally translated modules we may be able to reuse
|
// crates but for locally codegened modules we may be able to reuse
|
||||||
// that LLVM Context and Module.
|
// that LLVM Context and Module.
|
||||||
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
||||||
let llmod = llvm::LLVMRustParseBitcodeForThinLTO(
|
let llmod = llvm::LLVMRustParseBitcodeForThinLTO(
|
||||||
|
@ -645,8 +645,8 @@ impl ThinModule {
|
||||||
let msg = format!("failed to parse bitcode for thin LTO module");
|
let msg = format!("failed to parse bitcode for thin LTO module");
|
||||||
return Err(write::llvm_err(&diag_handler, msg));
|
return Err(write::llvm_err(&diag_handler, msg));
|
||||||
}
|
}
|
||||||
let mtrans = ModuleTranslation {
|
let module = ModuleCodegen {
|
||||||
source: ModuleSource::Translated(ModuleLlvm {
|
source: ModuleSource::Codegened(ModuleLlvm {
|
||||||
llmod,
|
llmod,
|
||||||
llcx,
|
llcx,
|
||||||
tm,
|
tm,
|
||||||
|
@ -655,7 +655,7 @@ impl ThinModule {
|
||||||
name: self.name().to_string(),
|
name: self.name().to_string(),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
};
|
};
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-input");
|
cgcx.save_temp_bitcode(&module, "thin-lto-input");
|
||||||
|
|
||||||
// Before we do much else find the "main" `DICompileUnit` that we'll be
|
// Before we do much else find the "main" `DICompileUnit` that we'll be
|
||||||
// using below. If we find more than one though then rustc has changed
|
// using below. If we find more than one though then rustc has changed
|
||||||
|
@ -673,7 +673,7 @@ impl ThinModule {
|
||||||
// are disabled by removing all landing pads.
|
// are disabled by removing all landing pads.
|
||||||
if cgcx.no_landing_pads {
|
if cgcx.no_landing_pads {
|
||||||
llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
|
llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-nounwind");
|
cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind");
|
||||||
timeline.record("nounwind");
|
timeline.record("nounwind");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,25 +689,25 @@ impl ThinModule {
|
||||||
let msg = format!("failed to prepare thin LTO module");
|
let msg = format!("failed to prepare thin LTO module");
|
||||||
return Err(write::llvm_err(&diag_handler, msg))
|
return Err(write::llvm_err(&diag_handler, msg))
|
||||||
}
|
}
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-rename");
|
cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
|
||||||
timeline.record("rename");
|
timeline.record("rename");
|
||||||
if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
|
if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
|
||||||
let msg = format!("failed to prepare thin LTO module");
|
let msg = format!("failed to prepare thin LTO module");
|
||||||
return Err(write::llvm_err(&diag_handler, msg))
|
return Err(write::llvm_err(&diag_handler, msg))
|
||||||
}
|
}
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-resolve");
|
cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
|
||||||
timeline.record("resolve");
|
timeline.record("resolve");
|
||||||
if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
|
if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
|
||||||
let msg = format!("failed to prepare thin LTO module");
|
let msg = format!("failed to prepare thin LTO module");
|
||||||
return Err(write::llvm_err(&diag_handler, msg))
|
return Err(write::llvm_err(&diag_handler, msg))
|
||||||
}
|
}
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-internalize");
|
cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
|
||||||
timeline.record("internalize");
|
timeline.record("internalize");
|
||||||
if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
|
if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
|
||||||
let msg = format!("failed to prepare thin LTO module");
|
let msg = format!("failed to prepare thin LTO module");
|
||||||
return Err(write::llvm_err(&diag_handler, msg))
|
return Err(write::llvm_err(&diag_handler, msg))
|
||||||
}
|
}
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-import");
|
cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
|
||||||
timeline.record("import");
|
timeline.record("import");
|
||||||
|
|
||||||
// Ok now this is a bit unfortunate. This is also something you won't
|
// Ok now this is a bit unfortunate. This is also something you won't
|
||||||
|
@ -740,7 +740,7 @@ impl ThinModule {
|
||||||
// so it appears). Hopefully we can remove this once upstream bugs are
|
// so it appears). Hopefully we can remove this once upstream bugs are
|
||||||
// fixed in LLVM.
|
// fixed in LLVM.
|
||||||
llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
|
llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-patch");
|
cgcx.save_temp_bitcode(&module, "thin-lto-after-patch");
|
||||||
timeline.record("patch");
|
timeline.record("patch");
|
||||||
|
|
||||||
// Alright now that we've done everything related to the ThinLTO
|
// Alright now that we've done everything related to the ThinLTO
|
||||||
|
@ -748,10 +748,10 @@ impl ThinModule {
|
||||||
// `run_pass_manager` as the "fat" LTO above except that we tell it to
|
// `run_pass_manager` as the "fat" LTO above except that we tell it to
|
||||||
// populate a thin-specific pass manager, which presumably LLVM treats a
|
// populate a thin-specific pass manager, which presumably LLVM treats a
|
||||||
// little differently.
|
// little differently.
|
||||||
info!("running thin lto passes over {}", mtrans.name);
|
info!("running thin lto passes over {}", module.name);
|
||||||
let config = cgcx.config(mtrans.kind);
|
let config = cgcx.config(module.kind);
|
||||||
run_pass_manager(cgcx, tm, llmod, config, true);
|
run_pass_manager(cgcx, tm, llmod, config, true);
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-pm");
|
cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
|
||||||
timeline.record("thin-done");
|
timeline.record("thin-done");
|
||||||
|
|
||||||
// FIXME: this is a hack around a bug in LLVM right now. Discovered in
|
// FIXME: this is a hack around a bug in LLVM right now. Discovered in
|
||||||
|
@ -765,9 +765,9 @@ impl ThinModule {
|
||||||
// shouldn't be necessary eventually and we can safetly delete these few
|
// shouldn't be necessary eventually and we can safetly delete these few
|
||||||
// lines.
|
// lines.
|
||||||
llvm::LLVMRustThinLTORemoveAvailableExternally(llmod);
|
llvm::LLVMRustThinLTORemoveAvailableExternally(llmod);
|
||||||
cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-rm-ae");
|
cgcx.save_temp_bitcode(&module, "thin-lto-after-rm-ae");
|
||||||
timeline.record("no-ae");
|
timeline.record("no-ae");
|
||||||
|
|
||||||
Ok(mtrans)
|
Ok(module)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use monomorphize::Instance;
|
use monomorphize::Instance;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::TransFnAttrFlags;
|
use rustc::hir::CodegenFnAttrFlags;
|
||||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
|
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
|
||||||
use rustc::ich::Fingerprint;
|
use rustc::ich::Fingerprint;
|
||||||
use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name};
|
use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name};
|
||||||
|
@ -63,7 +63,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
{
|
{
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
|
|
||||||
if !tcx.sess.opts.output_types.should_trans() {
|
if !tcx.sess.opts.output_types.should_codegen() {
|
||||||
return Lrc::new(DefIdMap())
|
return Lrc::new(DefIdMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let def_id = tcx.hir.local_def_id(node_id);
|
let def_id = tcx.hir.local_def_id(node_id);
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
if !generics.requires_monomorphization(tcx) &&
|
if !generics.requires_monomorphization(tcx) &&
|
||||||
// Functions marked with #[inline] are only ever translated
|
// Functions marked with #[inline] are only ever codegened
|
||||||
// with "internal" linkage and are never exported.
|
// with "internal" linkage and are never exported.
|
||||||
!Instance::mono(tcx, def_id).def.requires_local(tcx) {
|
!Instance::mono(tcx, def_id).def.requires_local(tcx) {
|
||||||
Some(def_id)
|
Some(def_id)
|
||||||
|
@ -195,7 +195,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
{
|
{
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
|
|
||||||
if !tcx.sess.opts.output_types.should_trans() {
|
if !tcx.sess.opts.output_types.should_codegen() {
|
||||||
return Arc::new(vec![])
|
return Arc::new(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let need_visibility = tcx.sess.target.target.options.dynamic_linking &&
|
let need_visibility = tcx.sess.target.target.options.dynamic_linking &&
|
||||||
!tcx.sess.target.target.options.only_cdylib;
|
!tcx.sess.target.target.options.only_cdylib;
|
||||||
|
|
||||||
let (_, cgus) = tcx.collect_and_partition_translation_items(LOCAL_CRATE);
|
let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
|
||||||
|
|
||||||
for (mono_item, &(linkage, visibility)) in cgus.iter()
|
for (mono_item, &(linkage, visibility)) in cgus.iter()
|
||||||
.flat_map(|cgu| cgu.items().iter()) {
|
.flat_map(|cgu| cgu.items().iter()) {
|
||||||
|
@ -383,9 +383,10 @@ fn symbol_export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
|
||||||
// special symbols in the standard library for various plumbing between
|
// special symbols in the standard library for various plumbing between
|
||||||
// core/std/allocators/etc. For example symbols used to hook up allocation
|
// core/std/allocators/etc. For example symbols used to hook up allocation
|
||||||
// are not considered for export
|
// are not considered for export
|
||||||
let trans_fn_attrs = tcx.trans_fn_attrs(sym_def_id);
|
let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
|
||||||
let is_extern = trans_fn_attrs.contains_extern_indicator();
|
let is_extern = codegen_fn_attrs.contains_extern_indicator();
|
||||||
let std_internal = trans_fn_attrs.flags.contains(TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
let std_internal =
|
||||||
|
codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
||||||
|
|
||||||
if is_extern && !std_internal {
|
if is_extern && !std_internal {
|
||||||
SymbolExportLevel::C
|
SymbolExportLevel::C
|
|
@ -28,7 +28,7 @@ use time_graph::{self, TimeGraph, Timeline};
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
|
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
|
||||||
use llvm::{SMDiagnosticRef, ContextRef};
|
use llvm::{SMDiagnosticRef, ContextRef};
|
||||||
use {CrateTranslation, ModuleSource, ModuleTranslation, CompiledModule, ModuleKind};
|
use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind};
|
||||||
use CrateInfo;
|
use CrateInfo;
|
||||||
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
|
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
|
@ -383,16 +383,16 @@ impl CodegenContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) {
|
pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen, name: &str) {
|
||||||
if !self.save_temps {
|
if !self.save_temps {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
let ext = format!("{}.bc", name);
|
let ext = format!("{}.bc", name);
|
||||||
let cgu = Some(&trans.name[..]);
|
let cgu = Some(&module.name[..]);
|
||||||
let path = self.output_filenames.temp_path_ext(&ext, cgu);
|
let path = self.output_filenames.temp_path_ext(&ext, cgu);
|
||||||
let cstr = path2cstr(&path);
|
let cstr = path2cstr(&path);
|
||||||
let llmod = trans.llvm().unwrap().llmod;
|
let llmod = module.llvm().unwrap().llmod;
|
||||||
llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
|
llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,13 +491,13 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo
|
||||||
// Unsafe due to LLVM calls.
|
// Unsafe due to LLVM calls.
|
||||||
unsafe fn optimize(cgcx: &CodegenContext,
|
unsafe fn optimize(cgcx: &CodegenContext,
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
mtrans: &ModuleTranslation,
|
module: &ModuleCodegen,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<(), FatalError>
|
-> Result<(), FatalError>
|
||||||
{
|
{
|
||||||
let (llmod, llcx, tm) = match mtrans.source {
|
let (llmod, llcx, tm) = match module.source {
|
||||||
ModuleSource::Translated(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
|
ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
|
||||||
ModuleSource::Preexisting(_) => {
|
ModuleSource::Preexisting(_) => {
|
||||||
bug!("optimize_and_codegen: called with ModuleSource::Preexisting")
|
bug!("optimize_and_codegen: called with ModuleSource::Preexisting")
|
||||||
}
|
}
|
||||||
|
@ -505,7 +505,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
|
||||||
|
|
||||||
let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
|
let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
|
||||||
|
|
||||||
let module_name = mtrans.name.clone();
|
let module_name = module.name.clone();
|
||||||
let module_name = Some(&module_name[..]);
|
let module_name = Some(&module_name[..]);
|
||||||
|
|
||||||
if config.emit_no_opt_bc {
|
if config.emit_no_opt_bc {
|
||||||
|
@ -594,12 +594,12 @@ unsafe fn optimize(cgcx: &CodegenContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_lto_work(cgcx: &CodegenContext,
|
fn generate_lto_work(cgcx: &CodegenContext,
|
||||||
modules: Vec<ModuleTranslation>)
|
modules: Vec<ModuleCodegen>)
|
||||||
-> Vec<(WorkItem, u64)>
|
-> Vec<(WorkItem, u64)>
|
||||||
{
|
{
|
||||||
let mut timeline = cgcx.time_graph.as_ref().map(|tg| {
|
let mut timeline = cgcx.time_graph.as_ref().map(|tg| {
|
||||||
tg.start(TRANS_WORKER_TIMELINE,
|
tg.start(CODEGEN_WORKER_TIMELINE,
|
||||||
TRANS_WORK_PACKAGE_KIND,
|
CODEGEN_WORK_PACKAGE_KIND,
|
||||||
"generate lto")
|
"generate lto")
|
||||||
}).unwrap_or(Timeline::noop());
|
}).unwrap_or(Timeline::noop());
|
||||||
let lto_modules = lto::run(cgcx, modules, &mut timeline)
|
let lto_modules = lto::run(cgcx, modules, &mut timeline)
|
||||||
|
@ -613,19 +613,19 @@ fn generate_lto_work(cgcx: &CodegenContext,
|
||||||
|
|
||||||
unsafe fn codegen(cgcx: &CodegenContext,
|
unsafe fn codegen(cgcx: &CodegenContext,
|
||||||
diag_handler: &Handler,
|
diag_handler: &Handler,
|
||||||
mtrans: ModuleTranslation,
|
module: ModuleCodegen,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<CompiledModule, FatalError>
|
-> Result<CompiledModule, FatalError>
|
||||||
{
|
{
|
||||||
timeline.record("codegen");
|
timeline.record("codegen");
|
||||||
let (llmod, llcx, tm) = match mtrans.source {
|
let (llmod, llcx, tm) = match module.source {
|
||||||
ModuleSource::Translated(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
|
ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm),
|
||||||
ModuleSource::Preexisting(_) => {
|
ModuleSource::Preexisting(_) => {
|
||||||
bug!("codegen: called with ModuleSource::Preexisting")
|
bug!("codegen: called with ModuleSource::Preexisting")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let module_name = mtrans.name.clone();
|
let module_name = module.name.clone();
|
||||||
let module_name = Some(&module_name[..]);
|
let module_name = Some(&module_name[..]);
|
||||||
let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
|
let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
|
||||||
|
|
||||||
|
@ -696,7 +696,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
||||||
|
|
||||||
if config.emit_bc_compressed {
|
if config.emit_bc_compressed {
|
||||||
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
|
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
|
||||||
let data = bytecode::encode(&mtrans.llmod_id, data);
|
let data = bytecode::encode(&module.llmod_id, data);
|
||||||
if let Err(e) = fs::write(&dst, data) {
|
if let Err(e) = fs::write(&dst, data) {
|
||||||
diag_handler.err(&format!("failed to write bytecode: {}", e));
|
diag_handler.err(&format!("failed to write bytecode: {}", e));
|
||||||
}
|
}
|
||||||
|
@ -805,7 +805,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(handlers);
|
drop(handlers);
|
||||||
Ok(mtrans.into_compiled_module(config.emit_obj,
|
Ok(module.into_compiled_module(config.emit_obj,
|
||||||
config.emit_bc,
|
config.emit_bc,
|
||||||
config.emit_bc_compressed,
|
config.emit_bc_compressed,
|
||||||
&cgcx.output_filenames))
|
&cgcx.output_filenames))
|
||||||
|
@ -880,13 +880,13 @@ fn need_crate_bitcode_for_rlib(sess: &Session) -> bool {
|
||||||
sess.opts.output_types.contains_key(&OutputType::Exe)
|
sess.opts.output_types.contains_key(&OutputType::Exe)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_async_translation(tcx: TyCtxt,
|
pub fn start_async_codegen(tcx: TyCtxt,
|
||||||
time_graph: Option<TimeGraph>,
|
time_graph: Option<TimeGraph>,
|
||||||
link: LinkMeta,
|
link: LinkMeta,
|
||||||
metadata: EncodedMetadata,
|
metadata: EncodedMetadata,
|
||||||
coordinator_receive: Receiver<Box<Any + Send>>,
|
coordinator_receive: Receiver<Box<Any + Send>>,
|
||||||
total_cgus: usize)
|
total_cgus: usize)
|
||||||
-> OngoingCrateTranslation {
|
-> OngoingCodegen {
|
||||||
let sess = tcx.sess;
|
let sess = tcx.sess;
|
||||||
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
let crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||||
let no_builtins = attr::contains_name(&tcx.hir.krate().attrs, "no_builtins");
|
let no_builtins = attr::contains_name(&tcx.hir.krate().attrs, "no_builtins");
|
||||||
|
@ -991,12 +991,12 @@ pub fn start_async_translation(tcx: TyCtxt,
|
||||||
allocator_config.time_passes = false;
|
allocator_config.time_passes = false;
|
||||||
|
|
||||||
let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
|
let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
|
||||||
let (trans_worker_send, trans_worker_receive) = channel();
|
let (codegen_worker_send, codegen_worker_receive) = channel();
|
||||||
|
|
||||||
let coordinator_thread = start_executing_work(tcx,
|
let coordinator_thread = start_executing_work(tcx,
|
||||||
&crate_info,
|
&crate_info,
|
||||||
shared_emitter,
|
shared_emitter,
|
||||||
trans_worker_send,
|
codegen_worker_send,
|
||||||
coordinator_receive,
|
coordinator_receive,
|
||||||
total_cgus,
|
total_cgus,
|
||||||
sess.jobserver.clone(),
|
sess.jobserver.clone(),
|
||||||
|
@ -1005,7 +1005,7 @@ pub fn start_async_translation(tcx: TyCtxt,
|
||||||
Arc::new(metadata_config),
|
Arc::new(metadata_config),
|
||||||
Arc::new(allocator_config));
|
Arc::new(allocator_config));
|
||||||
|
|
||||||
OngoingCrateTranslation {
|
OngoingCodegen {
|
||||||
crate_name,
|
crate_name,
|
||||||
link,
|
link,
|
||||||
metadata,
|
metadata,
|
||||||
|
@ -1015,7 +1015,7 @@ pub fn start_async_translation(tcx: TyCtxt,
|
||||||
|
|
||||||
time_graph,
|
time_graph,
|
||||||
coordinator_send: tcx.tx_to_llvm_workers.lock().clone(),
|
coordinator_send: tcx.tx_to_llvm_workers.lock().clone(),
|
||||||
trans_worker_receive,
|
codegen_worker_receive,
|
||||||
shared_emitter_main,
|
shared_emitter_main,
|
||||||
future: coordinator_thread,
|
future: coordinator_thread,
|
||||||
output_filenames: tcx.output_filenames(LOCAL_CRATE),
|
output_filenames: tcx.output_filenames(LOCAL_CRATE),
|
||||||
|
@ -1204,15 +1204,15 @@ fn produce_final_output_artifacts(sess: &Session,
|
||||||
// These are used in linking steps and will be cleaned up afterward.
|
// These are used in linking steps and will be cleaned up afterward.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn dump_incremental_data(trans: &CrateTranslation) {
|
pub(crate) fn dump_incremental_data(codegen_results: &CodegenResults) {
|
||||||
println!("[incremental] Re-using {} out of {} modules",
|
println!("[incremental] Re-using {} out of {} modules",
|
||||||
trans.modules.iter().filter(|m| m.pre_existing).count(),
|
codegen_results.modules.iter().filter(|m| m.pre_existing).count(),
|
||||||
trans.modules.len());
|
codegen_results.modules.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
enum WorkItem {
|
enum WorkItem {
|
||||||
Optimize(ModuleTranslation),
|
Optimize(ModuleCodegen),
|
||||||
LTO(lto::LtoModuleTranslation),
|
LTO(lto::LtoModuleCodegen),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkItem {
|
impl WorkItem {
|
||||||
|
@ -1233,7 +1233,7 @@ impl WorkItem {
|
||||||
|
|
||||||
enum WorkItemResult {
|
enum WorkItemResult {
|
||||||
Compiled(CompiledModule),
|
Compiled(CompiledModule),
|
||||||
NeedsLTO(ModuleTranslation),
|
NeedsLTO(ModuleCodegen),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_work_item(cgcx: &CodegenContext,
|
fn execute_work_item(cgcx: &CodegenContext,
|
||||||
|
@ -1243,8 +1243,8 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
{
|
{
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
let config = cgcx.config(work_item.kind());
|
let config = cgcx.config(work_item.kind());
|
||||||
let mtrans = match work_item {
|
let module = match work_item {
|
||||||
WorkItem::Optimize(mtrans) => mtrans,
|
WorkItem::Optimize(module) => module,
|
||||||
WorkItem::LTO(mut lto) => {
|
WorkItem::LTO(mut lto) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
let module = lto.optimize(cgcx, timeline)?;
|
let module = lto.optimize(cgcx, timeline)?;
|
||||||
|
@ -1253,10 +1253,10 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let module_name = mtrans.name.clone();
|
let module_name = module.name.clone();
|
||||||
|
|
||||||
let pre_existing = match mtrans.source {
|
let pre_existing = match module.source {
|
||||||
ModuleSource::Translated(_) => None,
|
ModuleSource::Codegened(_) => None,
|
||||||
ModuleSource::Preexisting(ref wp) => Some(wp.clone()),
|
ModuleSource::Preexisting(ref wp) => Some(wp.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1264,7 +1264,7 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
let incr_comp_session_dir = cgcx.incr_comp_session_dir
|
let incr_comp_session_dir = cgcx.incr_comp_session_dir
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let name = &mtrans.name;
|
let name = &module.name;
|
||||||
let mut object = None;
|
let mut object = None;
|
||||||
let mut bytecode = None;
|
let mut bytecode = None;
|
||||||
let mut bytecode_compressed = None;
|
let mut bytecode_compressed = None;
|
||||||
|
@ -1290,7 +1290,7 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
let source_file = in_incr_comp_dir(&incr_comp_session_dir,
|
let source_file = in_incr_comp_dir(&incr_comp_session_dir,
|
||||||
&saved_file);
|
&saved_file);
|
||||||
debug!("copying pre-existing module `{}` from {:?} to {}",
|
debug!("copying pre-existing module `{}` from {:?} to {}",
|
||||||
mtrans.name,
|
module.name,
|
||||||
source_file,
|
source_file,
|
||||||
obj_out.display());
|
obj_out.display());
|
||||||
match link_or_copy(&source_file, &obj_out) {
|
match link_or_copy(&source_file, &obj_out) {
|
||||||
|
@ -1308,7 +1308,7 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed);
|
assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed);
|
||||||
|
|
||||||
Ok(WorkItemResult::Compiled(CompiledModule {
|
Ok(WorkItemResult::Compiled(CompiledModule {
|
||||||
llmod_id: mtrans.llmod_id.clone(),
|
llmod_id: module.llmod_id.clone(),
|
||||||
name: module_name,
|
name: module_name,
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
pre_existing: true,
|
pre_existing: true,
|
||||||
|
@ -1320,7 +1320,7 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
debug!("llvm-optimizing {:?}", module_name);
|
debug!("llvm-optimizing {:?}", module_name);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
optimize(cgcx, &diag_handler, &mtrans, config, timeline)?;
|
optimize(cgcx, &diag_handler, &module, config, timeline)?;
|
||||||
|
|
||||||
// After we've done the initial round of optimizations we need to
|
// After we've done the initial round of optimizations we need to
|
||||||
// decide whether to synchronously codegen this module or ship it
|
// decide whether to synchronously codegen this module or ship it
|
||||||
|
@ -1328,7 +1328,7 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
// has to wait for all the initial modules to be optimized).
|
// has to wait for all the initial modules to be optimized).
|
||||||
//
|
//
|
||||||
// Here we dispatch based on the `cgcx.lto` and kind of module we're
|
// Here we dispatch based on the `cgcx.lto` and kind of module we're
|
||||||
// translating...
|
// codegenning...
|
||||||
let needs_lto = match cgcx.lto {
|
let needs_lto = match cgcx.lto {
|
||||||
Lto::No => false,
|
Lto::No => false,
|
||||||
|
|
||||||
|
@ -1353,14 +1353,14 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
// Additionally here's where we also factor in the current LLVM
|
// Additionally here's where we also factor in the current LLVM
|
||||||
// version. If it doesn't support ThinLTO we skip this.
|
// version. If it doesn't support ThinLTO we skip this.
|
||||||
Lto::ThinLocal => {
|
Lto::ThinLocal => {
|
||||||
mtrans.kind != ModuleKind::Allocator &&
|
module.kind != ModuleKind::Allocator &&
|
||||||
llvm::LLVMRustThinLTOAvailable()
|
llvm::LLVMRustThinLTOAvailable()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Metadata modules never participate in LTO regardless of the lto
|
// Metadata modules never participate in LTO regardless of the lto
|
||||||
// settings.
|
// settings.
|
||||||
let needs_lto = needs_lto && mtrans.kind != ModuleKind::Metadata;
|
let needs_lto = needs_lto && module.kind != ModuleKind::Metadata;
|
||||||
|
|
||||||
// Don't run LTO passes when cross-lang LTO is enabled. The linker
|
// Don't run LTO passes when cross-lang LTO is enabled. The linker
|
||||||
// will do that for us in this case.
|
// will do that for us in this case.
|
||||||
|
@ -1368,9 +1368,9 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
!cgcx.opts.debugging_opts.cross_lang_lto.embed_bitcode();
|
!cgcx.opts.debugging_opts.cross_lang_lto.embed_bitcode();
|
||||||
|
|
||||||
if needs_lto {
|
if needs_lto {
|
||||||
Ok(WorkItemResult::NeedsLTO(mtrans))
|
Ok(WorkItemResult::NeedsLTO(module))
|
||||||
} else {
|
} else {
|
||||||
let module = codegen(cgcx, &diag_handler, mtrans, config, timeline)?;
|
let module = codegen(cgcx, &diag_handler, module, config, timeline)?;
|
||||||
Ok(WorkItemResult::Compiled(module))
|
Ok(WorkItemResult::Compiled(module))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1380,19 +1380,19 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
enum Message {
|
enum Message {
|
||||||
Token(io::Result<Acquired>),
|
Token(io::Result<Acquired>),
|
||||||
NeedsLTO {
|
NeedsLTO {
|
||||||
result: ModuleTranslation,
|
result: ModuleCodegen,
|
||||||
worker_id: usize,
|
worker_id: usize,
|
||||||
},
|
},
|
||||||
Done {
|
Done {
|
||||||
result: Result<CompiledModule, ()>,
|
result: Result<CompiledModule, ()>,
|
||||||
worker_id: usize,
|
worker_id: usize,
|
||||||
},
|
},
|
||||||
TranslationDone {
|
CodegenDone {
|
||||||
llvm_work_item: WorkItem,
|
llvm_work_item: WorkItem,
|
||||||
cost: u64,
|
cost: u64,
|
||||||
},
|
},
|
||||||
TranslationComplete,
|
CodegenComplete,
|
||||||
TranslateItem,
|
CodegenItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Diagnostic {
|
struct Diagnostic {
|
||||||
|
@ -1404,14 +1404,14 @@ struct Diagnostic {
|
||||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||||
enum MainThreadWorkerState {
|
enum MainThreadWorkerState {
|
||||||
Idle,
|
Idle,
|
||||||
Translating,
|
Codegenning,
|
||||||
LLVMing,
|
LLVMing,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_executing_work(tcx: TyCtxt,
|
fn start_executing_work(tcx: TyCtxt,
|
||||||
crate_info: &CrateInfo,
|
crate_info: &CrateInfo,
|
||||||
shared_emitter: SharedEmitter,
|
shared_emitter: SharedEmitter,
|
||||||
trans_worker_send: Sender<Message>,
|
codegen_worker_send: Sender<Message>,
|
||||||
coordinator_receive: Receiver<Box<Any + Send>>,
|
coordinator_receive: Receiver<Box<Any + Send>>,
|
||||||
total_cgus: usize,
|
total_cgus: usize,
|
||||||
jobserver: Client,
|
jobserver: Client,
|
||||||
|
@ -1520,7 +1520,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
// - Error reporting only can happen on the main thread because that's the
|
// - Error reporting only can happen on the main thread because that's the
|
||||||
// only place where we have access to the compiler `Session`.
|
// only place where we have access to the compiler `Session`.
|
||||||
// - LLVM work can be done on any thread.
|
// - LLVM work can be done on any thread.
|
||||||
// - Translation can only happen on the main thread.
|
// - Codegen can only happen on the main thread.
|
||||||
// - Each thread doing substantial work most be in possession of a `Token`
|
// - Each thread doing substantial work most be in possession of a `Token`
|
||||||
// from the `Jobserver`.
|
// from the `Jobserver`.
|
||||||
// - The compiler process always holds one `Token`. Any additional `Tokens`
|
// - The compiler process always holds one `Token`. Any additional `Tokens`
|
||||||
|
@ -1536,7 +1536,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
// any error messages it has received. It might even abort compilation if
|
// any error messages it has received. It might even abort compilation if
|
||||||
// has received a fatal error. In this case we rely on all other threads
|
// has received a fatal error. In this case we rely on all other threads
|
||||||
// being torn down automatically with the main thread.
|
// being torn down automatically with the main thread.
|
||||||
// Since the main thread will often be busy doing translation work, error
|
// Since the main thread will often be busy doing codegen work, error
|
||||||
// reporting will be somewhat delayed, since the message queue can only be
|
// reporting will be somewhat delayed, since the message queue can only be
|
||||||
// checked in between to work packages.
|
// checked in between to work packages.
|
||||||
//
|
//
|
||||||
|
@ -1552,10 +1552,10 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
// thread about what work to do when, and it will spawn off LLVM worker
|
// thread about what work to do when, and it will spawn off LLVM worker
|
||||||
// threads as open LLVM WorkItems become available.
|
// threads as open LLVM WorkItems become available.
|
||||||
//
|
//
|
||||||
// The job of the main thread is to translate CGUs into LLVM work package
|
// The job of the main thread is to codegen CGUs into LLVM work package
|
||||||
// (since the main thread is the only thread that can do this). The main
|
// (since the main thread is the only thread that can do this). The main
|
||||||
// thread will block until it receives a message from the coordinator, upon
|
// thread will block until it receives a message from the coordinator, upon
|
||||||
// which it will translate one CGU, send it to the coordinator and block
|
// which it will codegen one CGU, send it to the coordinator and block
|
||||||
// again. This way the coordinator can control what the main thread is
|
// again. This way the coordinator can control what the main thread is
|
||||||
// doing.
|
// doing.
|
||||||
//
|
//
|
||||||
|
@ -1573,7 +1573,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
// if possible. These two goals are at odds with each other: If memory
|
// if possible. These two goals are at odds with each other: If memory
|
||||||
// consumption were not an issue, we could just let the main thread produce
|
// consumption were not an issue, we could just let the main thread produce
|
||||||
// LLVM WorkItems at full speed, assuring maximal utilization of
|
// LLVM WorkItems at full speed, assuring maximal utilization of
|
||||||
// Tokens/LLVM worker threads. However, since translation usual is faster
|
// Tokens/LLVM worker threads. However, since codegen usual is faster
|
||||||
// than LLVM processing, the queue of LLVM WorkItems would fill up and each
|
// than LLVM processing, the queue of LLVM WorkItems would fill up and each
|
||||||
// WorkItem potentially holds on to a substantial amount of memory.
|
// WorkItem potentially holds on to a substantial amount of memory.
|
||||||
//
|
//
|
||||||
|
@ -1637,7 +1637,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
// The final job the coordinator thread is responsible for is managing LTO
|
// The final job the coordinator thread is responsible for is managing LTO
|
||||||
// and how that works. When LTO is requested what we'll to is collect all
|
// and how that works. When LTO is requested what we'll to is collect all
|
||||||
// optimized LLVM modules into a local vector on the coordinator. Once all
|
// optimized LLVM modules into a local vector on the coordinator. Once all
|
||||||
// modules have been translated and optimized we hand this to the `lto`
|
// modules have been codegened and optimized we hand this to the `lto`
|
||||||
// module for further optimization. The `lto` module will return back a list
|
// module for further optimization. The `lto` module will return back a list
|
||||||
// of more modules to work on, which the coordinator will continue to spawn
|
// of more modules to work on, which the coordinator will continue to spawn
|
||||||
// work for.
|
// work for.
|
||||||
|
@ -1663,15 +1663,15 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is where we collect codegen units that have gone all the way
|
// This is where we collect codegen units that have gone all the way
|
||||||
// through translation and LLVM.
|
// through codegen and LLVM.
|
||||||
let mut compiled_modules = vec![];
|
let mut compiled_modules = vec![];
|
||||||
let mut compiled_metadata_module = None;
|
let mut compiled_metadata_module = None;
|
||||||
let mut compiled_allocator_module = None;
|
let mut compiled_allocator_module = None;
|
||||||
let mut needs_lto = Vec::new();
|
let mut needs_lto = Vec::new();
|
||||||
let mut started_lto = false;
|
let mut started_lto = false;
|
||||||
|
|
||||||
// This flag tracks whether all items have gone through translations
|
// This flag tracks whether all items have gone through codegens
|
||||||
let mut translation_done = false;
|
let mut codegen_done = false;
|
||||||
|
|
||||||
// This is the queue of LLVM work items that still need processing.
|
// This is the queue of LLVM work items that still need processing.
|
||||||
let mut work_items = Vec::<(WorkItem, u64)>::new();
|
let mut work_items = Vec::<(WorkItem, u64)>::new();
|
||||||
|
@ -1687,23 +1687,23 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
|
|
||||||
// Run the message loop while there's still anything that needs message
|
// Run the message loop while there's still anything that needs message
|
||||||
// processing:
|
// processing:
|
||||||
while !translation_done ||
|
while !codegen_done ||
|
||||||
work_items.len() > 0 ||
|
work_items.len() > 0 ||
|
||||||
running > 0 ||
|
running > 0 ||
|
||||||
needs_lto.len() > 0 ||
|
needs_lto.len() > 0 ||
|
||||||
main_thread_worker_state != MainThreadWorkerState::Idle {
|
main_thread_worker_state != MainThreadWorkerState::Idle {
|
||||||
|
|
||||||
// While there are still CGUs to be translated, the coordinator has
|
// While there are still CGUs to be codegened, the coordinator has
|
||||||
// to decide how to utilize the compiler processes implicit Token:
|
// to decide how to utilize the compiler processes implicit Token:
|
||||||
// For translating more CGU or for running them through LLVM.
|
// For codegenning more CGU or for running them through LLVM.
|
||||||
if !translation_done {
|
if !codegen_done {
|
||||||
if main_thread_worker_state == MainThreadWorkerState::Idle {
|
if main_thread_worker_state == MainThreadWorkerState::Idle {
|
||||||
if !queue_full_enough(work_items.len(), running, max_workers) {
|
if !queue_full_enough(work_items.len(), running, max_workers) {
|
||||||
// The queue is not full enough, translate more items:
|
// The queue is not full enough, codegen more items:
|
||||||
if let Err(_) = trans_worker_send.send(Message::TranslateItem) {
|
if let Err(_) = codegen_worker_send.send(Message::CodegenItem) {
|
||||||
panic!("Could not send Message::TranslateItem to main thread")
|
panic!("Could not send Message::CodegenItem to main thread")
|
||||||
}
|
}
|
||||||
main_thread_worker_state = MainThreadWorkerState::Translating;
|
main_thread_worker_state = MainThreadWorkerState::Codegenning;
|
||||||
} else {
|
} else {
|
||||||
// The queue is full enough to not let the worker
|
// The queue is full enough to not let the worker
|
||||||
// threads starve. Use the implicit Token to do some
|
// threads starve. Use the implicit Token to do some
|
||||||
|
@ -1721,7 +1721,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If we've finished everything related to normal translation
|
// If we've finished everything related to normal codegen
|
||||||
// then it must be the case that we've got some LTO work to do.
|
// then it must be the case that we've got some LTO work to do.
|
||||||
// Perform the serial work here of figuring out what we're
|
// Perform the serial work here of figuring out what we're
|
||||||
// going to LTO and then push a bunch of work items onto our
|
// going to LTO and then push a bunch of work items onto our
|
||||||
|
@ -1742,7 +1742,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this branch, we know that everything has been translated,
|
// In this branch, we know that everything has been codegened,
|
||||||
// so it's just a matter of determining whether the implicit
|
// so it's just a matter of determining whether the implicit
|
||||||
// Token is free to use for LLVM work.
|
// Token is free to use for LLVM work.
|
||||||
match main_thread_worker_state {
|
match main_thread_worker_state {
|
||||||
|
@ -1768,9 +1768,9 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
main_thread_worker_state = MainThreadWorkerState::LLVMing;
|
main_thread_worker_state = MainThreadWorkerState::LLVMing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MainThreadWorkerState::Translating => {
|
MainThreadWorkerState::Codegenning => {
|
||||||
bug!("trans worker should not be translating after \
|
bug!("codegen worker should not be codegenning after \
|
||||||
translation was already completed")
|
codegen was already completed")
|
||||||
}
|
}
|
||||||
MainThreadWorkerState::LLVMing => {
|
MainThreadWorkerState::LLVMing => {
|
||||||
// Already making good use of that token
|
// Already making good use of that token
|
||||||
|
@ -1812,7 +1812,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
// If the main thread token is used for LLVM work
|
// If the main thread token is used for LLVM work
|
||||||
// at the moment, we turn that thread into a regular
|
// at the moment, we turn that thread into a regular
|
||||||
// LLVM worker thread, so the main thread is free
|
// LLVM worker thread, so the main thread is free
|
||||||
// to react to translation demand.
|
// to react to codegen demand.
|
||||||
main_thread_worker_state = MainThreadWorkerState::Idle;
|
main_thread_worker_state = MainThreadWorkerState::Idle;
|
||||||
running += 1;
|
running += 1;
|
||||||
}
|
}
|
||||||
|
@ -1826,7 +1826,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::TranslationDone { llvm_work_item, cost } => {
|
Message::CodegenDone { llvm_work_item, cost } => {
|
||||||
// We keep the queue sorted by estimated processing cost,
|
// We keep the queue sorted by estimated processing cost,
|
||||||
// so that more expensive items are processed earlier. This
|
// so that more expensive items are processed earlier. This
|
||||||
// is good for throughput as it gives the main thread more
|
// is good for throughput as it gives the main thread more
|
||||||
|
@ -1844,14 +1844,14 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
|
|
||||||
helper.request_token();
|
helper.request_token();
|
||||||
assert_eq!(main_thread_worker_state,
|
assert_eq!(main_thread_worker_state,
|
||||||
MainThreadWorkerState::Translating);
|
MainThreadWorkerState::Codegenning);
|
||||||
main_thread_worker_state = MainThreadWorkerState::Idle;
|
main_thread_worker_state = MainThreadWorkerState::Idle;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::TranslationComplete => {
|
Message::CodegenComplete => {
|
||||||
translation_done = true;
|
codegen_done = true;
|
||||||
assert_eq!(main_thread_worker_state,
|
assert_eq!(main_thread_worker_state,
|
||||||
MainThreadWorkerState::Translating);
|
MainThreadWorkerState::Codegenning);
|
||||||
main_thread_worker_state = MainThreadWorkerState::Idle;
|
main_thread_worker_state = MainThreadWorkerState::Idle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1902,8 +1902,8 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
// Exit the coordinator thread
|
// Exit the coordinator thread
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
Message::TranslateItem => {
|
Message::CodegenItem => {
|
||||||
bug!("the coordinator should not receive translation requests")
|
bug!("the coordinator should not receive codegen requests")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1934,7 +1934,7 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
});
|
});
|
||||||
|
|
||||||
// A heuristic that determines if we have enough LLVM WorkItems in the
|
// A heuristic that determines if we have enough LLVM WorkItems in the
|
||||||
// queue so that the main thread can do LLVM work instead of translation
|
// queue so that the main thread can do LLVM work instead of codegen
|
||||||
fn queue_full_enough(items_in_queue: usize,
|
fn queue_full_enough(items_in_queue: usize,
|
||||||
workers_running: usize,
|
workers_running: usize,
|
||||||
max_workers: usize) -> bool {
|
max_workers: usize) -> bool {
|
||||||
|
@ -1955,10 +1955,10 @@ fn start_executing_work(tcx: TyCtxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const TRANS_WORKER_ID: usize = ::std::usize::MAX;
|
pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
|
||||||
pub const TRANS_WORKER_TIMELINE: time_graph::TimelineId =
|
pub const CODEGEN_WORKER_TIMELINE: time_graph::TimelineId =
|
||||||
time_graph::TimelineId(TRANS_WORKER_ID);
|
time_graph::TimelineId(CODEGEN_WORKER_ID);
|
||||||
pub const TRANS_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
pub const CODEGEN_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
||||||
time_graph::WorkPackageKind(&["#DE9597", "#FED1D3", "#FDC5C7", "#B46668", "#88494B"]);
|
time_graph::WorkPackageKind(&["#DE9597", "#FED1D3", "#FDC5C7", "#B46668", "#88494B"]);
|
||||||
const LLVM_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
const LLVM_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
|
||||||
time_graph::WorkPackageKind(&["#7DB67A", "#C6EEC4", "#ACDAAA", "#579354", "#3E6F3C"]);
|
time_graph::WorkPackageKind(&["#7DB67A", "#C6EEC4", "#ACDAAA", "#579354", "#3E6F3C"]);
|
||||||
|
@ -2231,7 +2231,7 @@ impl SharedEmitterMain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OngoingCrateTranslation {
|
pub struct OngoingCodegen {
|
||||||
crate_name: Symbol,
|
crate_name: Symbol,
|
||||||
link: LinkMeta,
|
link: LinkMeta,
|
||||||
metadata: EncodedMetadata,
|
metadata: EncodedMetadata,
|
||||||
|
@ -2240,17 +2240,17 @@ pub struct OngoingCrateTranslation {
|
||||||
crate_info: CrateInfo,
|
crate_info: CrateInfo,
|
||||||
time_graph: Option<TimeGraph>,
|
time_graph: Option<TimeGraph>,
|
||||||
coordinator_send: Sender<Box<Any + Send>>,
|
coordinator_send: Sender<Box<Any + Send>>,
|
||||||
trans_worker_receive: Receiver<Message>,
|
codegen_worker_receive: Receiver<Message>,
|
||||||
shared_emitter_main: SharedEmitterMain,
|
shared_emitter_main: SharedEmitterMain,
|
||||||
future: thread::JoinHandle<Result<CompiledModules, ()>>,
|
future: thread::JoinHandle<Result<CompiledModules, ()>>,
|
||||||
output_filenames: Arc<OutputFilenames>,
|
output_filenames: Arc<OutputFilenames>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OngoingCrateTranslation {
|
impl OngoingCodegen {
|
||||||
pub(crate) fn join(
|
pub(crate) fn join(
|
||||||
self,
|
self,
|
||||||
sess: &Session
|
sess: &Session
|
||||||
) -> (CrateTranslation, FxHashMap<WorkProductId, WorkProduct>) {
|
) -> (CodegenResults, FxHashMap<WorkProductId, WorkProduct>) {
|
||||||
self.shared_emitter_main.check(sess, true);
|
self.shared_emitter_main.check(sess, true);
|
||||||
let compiled_modules = match self.future.join() {
|
let compiled_modules = match self.future.join() {
|
||||||
Ok(Ok(compiled_modules)) => compiled_modules,
|
Ok(Ok(compiled_modules)) => compiled_modules,
|
||||||
|
@ -2259,7 +2259,7 @@ impl OngoingCrateTranslation {
|
||||||
panic!("expected abort due to worker thread errors")
|
panic!("expected abort due to worker thread errors")
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
sess.fatal("Error during translation/LLVM phase.");
|
sess.fatal("Error during codegen/LLVM phase.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2282,7 +2282,7 @@ impl OngoingCrateTranslation {
|
||||||
unsafe { llvm::LLVMRustPrintPassTimings(); }
|
unsafe { llvm::LLVMRustPrintPassTimings(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
let trans = CrateTranslation {
|
(CodegenResults {
|
||||||
crate_name: self.crate_name,
|
crate_name: self.crate_name,
|
||||||
link: self.link,
|
link: self.link,
|
||||||
metadata: self.metadata,
|
metadata: self.metadata,
|
||||||
|
@ -2293,35 +2293,33 @@ impl OngoingCrateTranslation {
|
||||||
modules: compiled_modules.modules,
|
modules: compiled_modules.modules,
|
||||||
allocator_module: compiled_modules.allocator_module,
|
allocator_module: compiled_modules.allocator_module,
|
||||||
metadata_module: compiled_modules.metadata_module,
|
metadata_module: compiled_modules.metadata_module,
|
||||||
};
|
}, work_products)
|
||||||
|
|
||||||
(trans, work_products)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn submit_pre_translated_module_to_llvm(&self,
|
pub(crate) fn submit_pre_codegened_module_to_llvm(&self,
|
||||||
tcx: TyCtxt,
|
tcx: TyCtxt,
|
||||||
mtrans: ModuleTranslation) {
|
module: ModuleCodegen) {
|
||||||
self.wait_for_signal_to_translate_item();
|
self.wait_for_signal_to_codegen_item();
|
||||||
self.check_for_errors(tcx.sess);
|
self.check_for_errors(tcx.sess);
|
||||||
|
|
||||||
// These are generally cheap and won't through off scheduling.
|
// These are generally cheap and won't through off scheduling.
|
||||||
let cost = 0;
|
let cost = 0;
|
||||||
submit_translated_module_to_llvm(tcx, mtrans, cost);
|
submit_codegened_module_to_llvm(tcx, module, cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn translation_finished(&self, tcx: TyCtxt) {
|
pub fn codegen_finished(&self, tcx: TyCtxt) {
|
||||||
self.wait_for_signal_to_translate_item();
|
self.wait_for_signal_to_codegen_item();
|
||||||
self.check_for_errors(tcx.sess);
|
self.check_for_errors(tcx.sess);
|
||||||
drop(self.coordinator_send.send(Box::new(Message::TranslationComplete)));
|
drop(self.coordinator_send.send(Box::new(Message::CodegenComplete)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_for_errors(&self, sess: &Session) {
|
pub fn check_for_errors(&self, sess: &Session) {
|
||||||
self.shared_emitter_main.check(sess, false);
|
self.shared_emitter_main.check(sess, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_for_signal_to_translate_item(&self) {
|
pub fn wait_for_signal_to_codegen_item(&self) {
|
||||||
match self.trans_worker_receive.recv() {
|
match self.codegen_worker_receive.recv() {
|
||||||
Ok(Message::TranslateItem) => {
|
Ok(Message::CodegenItem) => {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
Ok(_) => panic!("unexpected message"),
|
Ok(_) => panic!("unexpected message"),
|
||||||
|
@ -2333,11 +2331,11 @@ impl OngoingCrateTranslation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn submit_translated_module_to_llvm(tcx: TyCtxt,
|
pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt,
|
||||||
mtrans: ModuleTranslation,
|
module: ModuleCodegen,
|
||||||
cost: u64) {
|
cost: u64) {
|
||||||
let llvm_work_item = WorkItem::Optimize(mtrans);
|
let llvm_work_item = WorkItem::Optimize(module);
|
||||||
drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::TranslationDone {
|
drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone {
|
||||||
llvm_work_item,
|
llvm_work_item,
|
||||||
cost,
|
cost,
|
||||||
})));
|
})));
|
|
@ -8,14 +8,14 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//! Translate the completed AST to the LLVM IR.
|
//! Codegen the completed AST to the LLVM IR.
|
||||||
//!
|
//!
|
||||||
//! Some functions here, such as trans_block and trans_expr, return a value --
|
//! Some functions here, such as codegen_block and codegen_expr, return a value --
|
||||||
//! the result of the translation to LLVM -- while others, such as trans_fn
|
//! the result of the codegen to LLVM -- while others, such as codegen_fn
|
||||||
//! and trans_item, are called only for the side effect of adding a
|
//! and mono_item, are called only for the side effect of adding a
|
||||||
//! particular definition to the LLVM IR output we're producing.
|
//! particular definition to the LLVM IR output we're producing.
|
||||||
//!
|
//!
|
||||||
//! Hopefully useful general knowledge about trans:
|
//! Hopefully useful general knowledge about codegen:
|
||||||
//!
|
//!
|
||||||
//! * There's no way to find out the Ty type of a ValueRef. Doing so
|
//! * There's no way to find out the Ty type of a ValueRef. Doing so
|
||||||
//! would be "trying to get the eggs out of an omelette" (credit:
|
//! would be "trying to get the eggs out of an omelette" (credit:
|
||||||
|
@ -25,12 +25,12 @@
|
||||||
|
|
||||||
use super::ModuleLlvm;
|
use super::ModuleLlvm;
|
||||||
use super::ModuleSource;
|
use super::ModuleSource;
|
||||||
use super::ModuleTranslation;
|
use super::ModuleCodegen;
|
||||||
use super::ModuleKind;
|
use super::ModuleKind;
|
||||||
|
|
||||||
use abi;
|
use abi;
|
||||||
use back::link;
|
use back::link;
|
||||||
use back::write::{self, OngoingCrateTranslation, create_target_machine};
|
use back::write::{self, OngoingCodegen, create_target_machine};
|
||||||
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
|
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
|
||||||
use llvm;
|
use llvm;
|
||||||
use metadata;
|
use metadata;
|
||||||
|
@ -66,9 +66,9 @@ use meth;
|
||||||
use mir;
|
use mir;
|
||||||
use monomorphize::Instance;
|
use monomorphize::Instance;
|
||||||
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
|
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
|
||||||
use rustc_trans_utils::symbol_names_test;
|
use rustc_codegen_utils::symbol_names_test;
|
||||||
use time_graph;
|
use time_graph;
|
||||||
use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
|
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
|
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
|
||||||
|
@ -93,7 +93,7 @@ use syntax::ast;
|
||||||
|
|
||||||
use mir::operand::OperandValue;
|
use mir::operand::OperandValue;
|
||||||
|
|
||||||
pub use rustc_trans_utils::check_for_rustc_errors_attr;
|
pub use rustc_codegen_utils::check_for_rustc_errors_attr;
|
||||||
|
|
||||||
pub struct StatRecorder<'a, 'tcx: 'a> {
|
pub struct StatRecorder<'a, 'tcx: 'a> {
|
||||||
cx: &'a CodegenCx<'a, 'tcx>,
|
cx: &'a CodegenCx<'a, 'tcx>,
|
||||||
|
@ -114,7 +114,7 @@ impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
|
||||||
|
|
||||||
impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
|
impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.cx.sess().trans_stats() {
|
if self.cx.sess().codegen_stats() {
|
||||||
let mut stats = self.cx.stats.borrow_mut();
|
let mut stats = self.cx.stats.borrow_mut();
|
||||||
let iend = stats.n_llvm_insns;
|
let iend = stats.n_llvm_insns;
|
||||||
stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart));
|
stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart));
|
||||||
|
@ -458,8 +458,8 @@ pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
||||||
bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
|
bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>) {
|
pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>) {
|
||||||
let _s = if cx.sess().trans_stats() {
|
let _s = if cx.sess().codegen_stats() {
|
||||||
let mut instance_name = String::new();
|
let mut instance_name = String::new();
|
||||||
DefPathBasedNames::new(cx.tcx, true, true)
|
DefPathBasedNames::new(cx.tcx, true, true)
|
||||||
.push_def_path(instance.def_id(), &mut instance_name);
|
.push_def_path(instance.def_id(), &mut instance_name);
|
||||||
|
@ -471,7 +471,7 @@ pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tc
|
||||||
// this is an info! to allow collecting monomorphization statistics
|
// this is an info! to allow collecting monomorphization statistics
|
||||||
// and to allow finding the last function before LLVM aborts from
|
// and to allow finding the last function before LLVM aborts from
|
||||||
// release builds.
|
// release builds.
|
||||||
info!("trans_instance({})", instance);
|
info!("codegen_instance({})", instance);
|
||||||
|
|
||||||
let fn_ty = instance.ty(cx.tcx);
|
let fn_ty = instance.ty(cx.tcx);
|
||||||
let sig = common::ty_fn_sig(cx, fn_ty);
|
let sig = common::ty_fn_sig(cx, fn_ty);
|
||||||
|
@ -506,7 +506,7 @@ pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tc
|
||||||
}
|
}
|
||||||
|
|
||||||
let mir = cx.tcx.instance_mir(instance.def);
|
let mir = cx.tcx.instance_mir(instance.def);
|
||||||
mir::trans_mir(cx, lldecl, &mir, instance, sig);
|
mir::codegen_mir(cx, lldecl, &mir, instance, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_link_section(cx: &CodegenCx,
|
pub fn set_link_section(cx: &CodegenCx,
|
||||||
|
@ -712,9 +712,9 @@ pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
rx: mpsc::Receiver<Box<Any + Send>>)
|
rx: mpsc::Receiver<Box<Any + Send>>)
|
||||||
-> OngoingCrateTranslation {
|
-> OngoingCodegen {
|
||||||
|
|
||||||
check_for_rustc_errors_attr(tcx);
|
check_for_rustc_errors_attr(tcx);
|
||||||
|
|
||||||
|
@ -734,17 +734,17 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let crate_hash = tcx.crate_hash(LOCAL_CRATE);
|
let crate_hash = tcx.crate_hash(LOCAL_CRATE);
|
||||||
let link_meta = link::build_link_meta(crate_hash);
|
let link_meta = link::build_link_meta(crate_hash);
|
||||||
|
|
||||||
// Translate the metadata.
|
// Codegen the metadata.
|
||||||
let llmod_id = "metadata";
|
let llmod_id = "metadata";
|
||||||
let (metadata_llcx, metadata_llmod, metadata) =
|
let (metadata_llcx, metadata_llmod, metadata) =
|
||||||
time(tcx.sess, "write metadata", || {
|
time(tcx.sess, "write metadata", || {
|
||||||
write_metadata(tcx, llmod_id, &link_meta)
|
write_metadata(tcx, llmod_id, &link_meta)
|
||||||
});
|
});
|
||||||
|
|
||||||
let metadata_module = ModuleTranslation {
|
let metadata_module = ModuleCodegen {
|
||||||
name: link::METADATA_MODULE_NAME.to_string(),
|
name: link::METADATA_MODULE_NAME.to_string(),
|
||||||
llmod_id: llmod_id.to_string(),
|
llmod_id: llmod_id.to_string(),
|
||||||
source: ModuleSource::Translated(ModuleLlvm {
|
source: ModuleSource::Codegened(ModuleLlvm {
|
||||||
llcx: metadata_llcx,
|
llcx: metadata_llcx,
|
||||||
llmod: metadata_llmod,
|
llmod: metadata_llmod,
|
||||||
tm: create_target_machine(tcx.sess, false),
|
tm: create_target_machine(tcx.sess, false),
|
||||||
|
@ -752,16 +752,16 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
kind: ModuleKind::Metadata,
|
kind: ModuleKind::Metadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
let time_graph = if tcx.sess.opts.debugging_opts.trans_time_graph {
|
let time_graph = if tcx.sess.opts.debugging_opts.codegen_time_graph {
|
||||||
Some(time_graph::TimeGraph::new())
|
Some(time_graph::TimeGraph::new())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Skip crate items and just output metadata in -Z no-trans mode.
|
// Skip crate items and just output metadata in -Z no-codegen mode.
|
||||||
if tcx.sess.opts.debugging_opts.no_trans ||
|
if tcx.sess.opts.debugging_opts.no_codegen ||
|
||||||
!tcx.sess.opts.output_types.should_trans() {
|
!tcx.sess.opts.output_types.should_codegen() {
|
||||||
let ongoing_translation = write::start_async_translation(
|
let ongoing_codegen = write::start_async_codegen(
|
||||||
tcx,
|
tcx,
|
||||||
time_graph.clone(),
|
time_graph.clone(),
|
||||||
link_meta,
|
link_meta,
|
||||||
|
@ -769,20 +769,20 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
rx,
|
rx,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
ongoing_translation.submit_pre_translated_module_to_llvm(tcx, metadata_module);
|
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
|
||||||
ongoing_translation.translation_finished(tcx);
|
ongoing_codegen.codegen_finished(tcx);
|
||||||
|
|
||||||
assert_and_save_dep_graph(tcx);
|
assert_and_save_dep_graph(tcx);
|
||||||
|
|
||||||
ongoing_translation.check_for_errors(tcx.sess);
|
ongoing_codegen.check_for_errors(tcx.sess);
|
||||||
|
|
||||||
return ongoing_translation;
|
return ongoing_codegen;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the translation item collector and partition the collected items into
|
// Run the monomorphization collector and partition the collected items into
|
||||||
// codegen units.
|
// codegen units.
|
||||||
let codegen_units =
|
let codegen_units =
|
||||||
tcx.collect_and_partition_translation_items(LOCAL_CRATE).1;
|
tcx.collect_and_partition_mono_items(LOCAL_CRATE).1;
|
||||||
let codegen_units = (*codegen_units).clone();
|
let codegen_units = (*codegen_units).clone();
|
||||||
|
|
||||||
// Force all codegen_unit queries so they are already either red or green
|
// Force all codegen_unit queries so they are already either red or green
|
||||||
|
@ -796,7 +796,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ongoing_translation = write::start_async_translation(
|
let ongoing_codegen = write::start_async_codegen(
|
||||||
tcx,
|
tcx,
|
||||||
time_graph.clone(),
|
time_graph.clone(),
|
||||||
link_meta,
|
link_meta,
|
||||||
|
@ -804,7 +804,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
rx,
|
rx,
|
||||||
codegen_units.len());
|
codegen_units.len());
|
||||||
|
|
||||||
// Translate an allocator shim, if any
|
// Codegen an allocator shim, if any
|
||||||
let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
|
let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let llmod_id = "allocator";
|
let llmod_id = "allocator";
|
||||||
|
@ -816,13 +816,13 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
tm: create_target_machine(tcx.sess, false),
|
tm: create_target_machine(tcx.sess, false),
|
||||||
};
|
};
|
||||||
time(tcx.sess, "write allocator module", || {
|
time(tcx.sess, "write allocator module", || {
|
||||||
allocator::trans(tcx, &modules, kind)
|
allocator::codegen(tcx, &modules, kind)
|
||||||
});
|
});
|
||||||
|
|
||||||
Some(ModuleTranslation {
|
Some(ModuleCodegen {
|
||||||
name: link::ALLOCATOR_MODULE_NAME.to_string(),
|
name: link::ALLOCATOR_MODULE_NAME.to_string(),
|
||||||
llmod_id: llmod_id.to_string(),
|
llmod_id: llmod_id.to_string(),
|
||||||
source: ModuleSource::Translated(modules),
|
source: ModuleSource::Codegened(modules),
|
||||||
kind: ModuleKind::Allocator,
|
kind: ModuleKind::Allocator,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -831,10 +831,10 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(allocator_module) = allocator_module {
|
if let Some(allocator_module) = allocator_module {
|
||||||
ongoing_translation.submit_pre_translated_module_to_llvm(tcx, allocator_module);
|
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
ongoing_translation.submit_pre_translated_module_to_llvm(tcx, metadata_module);
|
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module);
|
||||||
|
|
||||||
// We sort the codegen units by size. This way we can schedule work for LLVM
|
// We sort the codegen units by size. This way we can schedule work for LLVM
|
||||||
// a bit more efficiently.
|
// a bit more efficiently.
|
||||||
|
@ -844,12 +844,12 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
codegen_units
|
codegen_units
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut total_trans_time = Duration::new(0, 0);
|
let mut total_codegen_time = Duration::new(0, 0);
|
||||||
let mut all_stats = Stats::default();
|
let mut all_stats = Stats::default();
|
||||||
|
|
||||||
for cgu in codegen_units.into_iter() {
|
for cgu in codegen_units.into_iter() {
|
||||||
ongoing_translation.wait_for_signal_to_translate_item();
|
ongoing_codegen.wait_for_signal_to_codegen_item();
|
||||||
ongoing_translation.check_for_errors(tcx.sess);
|
ongoing_codegen.check_for_errors(tcx.sess);
|
||||||
|
|
||||||
// First, if incremental compilation is enabled, we try to re-use the
|
// First, if incremental compilation is enabled, we try to re-use the
|
||||||
// codegen unit from the cache.
|
// codegen unit from the cache.
|
||||||
|
@ -878,14 +878,14 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
|
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
|
||||||
let llmod_id = format!("{}.rs", cgu.name());
|
let llmod_id = format!("{}.rs", cgu.name());
|
||||||
|
|
||||||
let module = ModuleTranslation {
|
let module = ModuleCodegen {
|
||||||
name: cgu.name().to_string(),
|
name: cgu.name().to_string(),
|
||||||
source: ModuleSource::Preexisting(buf),
|
source: ModuleSource::Preexisting(buf),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
llmod_id,
|
llmod_id,
|
||||||
};
|
};
|
||||||
tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
|
tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
|
||||||
write::submit_translated_module_to_llvm(tcx, module, 0);
|
write::submit_codegened_module_to_llvm(tcx, module, 0);
|
||||||
// Continue to next cgu, this one is done.
|
// Continue to next cgu, this one is done.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -896,23 +896,23 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let _timing_guard = time_graph.as_ref().map(|time_graph| {
|
let _timing_guard = time_graph.as_ref().map(|time_graph| {
|
||||||
time_graph.start(write::TRANS_WORKER_TIMELINE,
|
time_graph.start(write::CODEGEN_WORKER_TIMELINE,
|
||||||
write::TRANS_WORK_PACKAGE_KIND,
|
write::CODEGEN_WORK_PACKAGE_KIND,
|
||||||
&format!("codegen {}", cgu.name()))
|
&format!("codegen {}", cgu.name()))
|
||||||
});
|
});
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
all_stats.extend(tcx.compile_codegen_unit(*cgu.name()));
|
all_stats.extend(tcx.compile_codegen_unit(*cgu.name()));
|
||||||
total_trans_time += start_time.elapsed();
|
total_codegen_time += start_time.elapsed();
|
||||||
ongoing_translation.check_for_errors(tcx.sess);
|
ongoing_codegen.check_for_errors(tcx.sess);
|
||||||
}
|
}
|
||||||
|
|
||||||
ongoing_translation.translation_finished(tcx);
|
ongoing_codegen.codegen_finished(tcx);
|
||||||
|
|
||||||
// Since the main thread is sometimes blocked during trans, we keep track
|
// Since the main thread is sometimes blocked during codegen, we keep track
|
||||||
// -Ztime-passes output manually.
|
// -Ztime-passes output manually.
|
||||||
print_time_passes_entry(tcx.sess.time_passes(),
|
print_time_passes_entry(tcx.sess.time_passes(),
|
||||||
"translate to LLVM IR",
|
"codegen to LLVM IR",
|
||||||
total_trans_time);
|
total_codegen_time);
|
||||||
|
|
||||||
if tcx.sess.opts.incremental.is_some() {
|
if tcx.sess.opts.incremental.is_some() {
|
||||||
::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
|
::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
|
||||||
|
@ -920,8 +920,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
symbol_names_test::report_symbol_names(tcx);
|
symbol_names_test::report_symbol_names(tcx);
|
||||||
|
|
||||||
if tcx.sess.trans_stats() {
|
if tcx.sess.codegen_stats() {
|
||||||
println!("--- trans stats ---");
|
println!("--- codegen stats ---");
|
||||||
println!("n_glues_created: {}", all_stats.n_glues_created);
|
println!("n_glues_created: {}", all_stats.n_glues_created);
|
||||||
println!("n_null_glues: {}", all_stats.n_null_glues);
|
println!("n_null_glues: {}", all_stats.n_null_glues);
|
||||||
println!("n_real_glues: {}", all_stats.n_real_glues);
|
println!("n_real_glues: {}", all_stats.n_real_glues);
|
||||||
|
@ -942,10 +942,10 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ongoing_translation.check_for_errors(tcx.sess);
|
ongoing_codegen.check_for_errors(tcx.sess);
|
||||||
|
|
||||||
assert_and_save_dep_graph(tcx);
|
assert_and_save_dep_graph(tcx);
|
||||||
ongoing_translation
|
ongoing_codegen
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||||
|
@ -958,14 +958,14 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||||
|| rustc_incremental::save_dep_graph(tcx));
|
|| rustc_incremental::save_dep_graph(tcx));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_and_partition_translation_items<'a, 'tcx>(
|
fn collect_and_partition_mono_items<'a, 'tcx>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
cnum: CrateNum,
|
cnum: CrateNum,
|
||||||
) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
|
) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
|
||||||
{
|
{
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
assert_eq!(cnum, LOCAL_CRATE);
|
||||||
|
|
||||||
let collection_mode = match tcx.sess.opts.debugging_opts.print_trans_items {
|
let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
|
||||||
Some(ref s) => {
|
Some(ref s) => {
|
||||||
let mode_string = s.to_lowercase();
|
let mode_string = s.to_lowercase();
|
||||||
let mode_string = mode_string.trim();
|
let mode_string = mode_string.trim();
|
||||||
|
@ -992,7 +992,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let (items, inlining_map) =
|
let (items, inlining_map) =
|
||||||
time(tcx.sess, "translation item collection", || {
|
time(tcx.sess, "monomorphization collection", || {
|
||||||
collector::collect_crate_mono_items(tcx, collection_mode)
|
collector::collect_crate_mono_items(tcx, collection_mode)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1016,20 +1016,20 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
});
|
});
|
||||||
|
|
||||||
let translation_items: DefIdSet = items.iter().filter_map(|trans_item| {
|
let mono_items: DefIdSet = items.iter().filter_map(|mono_item| {
|
||||||
match *trans_item {
|
match *mono_item {
|
||||||
MonoItem::Fn(ref instance) => Some(instance.def_id()),
|
MonoItem::Fn(ref instance) => Some(instance.def_id()),
|
||||||
MonoItem::Static(def_id) => Some(def_id),
|
MonoItem::Static(def_id) => Some(def_id),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
if tcx.sess.opts.debugging_opts.print_trans_items.is_some() {
|
if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
|
||||||
let mut item_to_cgus = FxHashMap();
|
let mut item_to_cgus = FxHashMap();
|
||||||
|
|
||||||
for cgu in &codegen_units {
|
for cgu in &codegen_units {
|
||||||
for (&trans_item, &linkage) in cgu.items() {
|
for (&mono_item, &linkage) in cgu.items() {
|
||||||
item_to_cgus.entry(trans_item)
|
item_to_cgus.entry(mono_item)
|
||||||
.or_insert(Vec::new())
|
.or_insert(Vec::new())
|
||||||
.push((cgu.name().clone(), linkage));
|
.push((cgu.name().clone(), linkage));
|
||||||
}
|
}
|
||||||
|
@ -1073,11 +1073,11 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
|
||||||
item_keys.sort();
|
item_keys.sort();
|
||||||
|
|
||||||
for item in item_keys {
|
for item in item_keys {
|
||||||
println!("TRANS_ITEM {}", item);
|
println!("MONO_ITEM {}", item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Arc::new(translation_items), Arc::new(codegen_units))
|
(Arc::new(mono_items), Arc::new(codegen_units))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateInfo {
|
impl CrateInfo {
|
||||||
|
@ -1174,10 +1174,10 @@ impl CrateInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_translated_item(tcx: TyCtxt, id: DefId) -> bool {
|
fn is_codegened_item(tcx: TyCtxt, id: DefId) -> bool {
|
||||||
let (all_trans_items, _) =
|
let (all_mono_items, _) =
|
||||||
tcx.collect_and_partition_translation_items(LOCAL_CRATE);
|
tcx.collect_and_partition_mono_items(LOCAL_CRATE);
|
||||||
all_trans_items.contains(&id)
|
all_mono_items.contains(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
@ -1185,23 +1185,23 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let cgu = tcx.codegen_unit(cgu);
|
let cgu = tcx.codegen_unit(cgu);
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let (stats, module) = module_translation(tcx, cgu);
|
let (stats, module) = module_codegen(tcx, cgu);
|
||||||
let time_to_translate = start_time.elapsed();
|
let time_to_codegen = start_time.elapsed();
|
||||||
|
|
||||||
// We assume that the cost to run LLVM on a CGU is proportional to
|
// We assume that the cost to run LLVM on a CGU is proportional to
|
||||||
// the time we needed for translating it.
|
// the time we needed for codegenning it.
|
||||||
let cost = time_to_translate.as_secs() * 1_000_000_000 +
|
let cost = time_to_codegen.as_secs() * 1_000_000_000 +
|
||||||
time_to_translate.subsec_nanos() as u64;
|
time_to_codegen.subsec_nanos() as u64;
|
||||||
|
|
||||||
write::submit_translated_module_to_llvm(tcx,
|
write::submit_codegened_module_to_llvm(tcx,
|
||||||
module,
|
module,
|
||||||
cost);
|
cost);
|
||||||
return stats;
|
return stats;
|
||||||
|
|
||||||
fn module_translation<'a, 'tcx>(
|
fn module_codegen<'a, 'tcx>(
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
cgu: Arc<CodegenUnit<'tcx>>)
|
cgu: Arc<CodegenUnit<'tcx>>)
|
||||||
-> (Stats, ModuleTranslation)
|
-> (Stats, ModuleCodegen)
|
||||||
{
|
{
|
||||||
let cgu_name = cgu.name().to_string();
|
let cgu_name = cgu.name().to_string();
|
||||||
|
|
||||||
|
@ -1218,18 +1218,18 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
tcx.crate_disambiguator(LOCAL_CRATE)
|
tcx.crate_disambiguator(LOCAL_CRATE)
|
||||||
.to_fingerprint().to_hex());
|
.to_fingerprint().to_hex());
|
||||||
|
|
||||||
// Instantiate translation items without filling out definitions yet...
|
// Instantiate monomorphizations without filling out definitions yet...
|
||||||
let cx = CodegenCx::new(tcx, cgu, &llmod_id);
|
let cx = CodegenCx::new(tcx, cgu, &llmod_id);
|
||||||
let module = {
|
let module = {
|
||||||
let trans_items = cx.codegen_unit
|
let mono_items = cx.codegen_unit
|
||||||
.items_in_deterministic_order(cx.tcx);
|
.items_in_deterministic_order(cx.tcx);
|
||||||
for &(trans_item, (linkage, visibility)) in &trans_items {
|
for &(mono_item, (linkage, visibility)) in &mono_items {
|
||||||
trans_item.predefine(&cx, linkage, visibility);
|
mono_item.predefine(&cx, linkage, visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... and now that we have everything pre-defined, fill out those definitions.
|
// ... and now that we have everything pre-defined, fill out those definitions.
|
||||||
for &(trans_item, _) in &trans_items {
|
for &(mono_item, _) in &mono_items {
|
||||||
trans_item.define(&cx);
|
mono_item.define(&cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this codegen unit contains the main function, also create the
|
// If this codegen unit contains the main function, also create the
|
||||||
|
@ -1273,9 +1273,9 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
tm: create_target_machine(cx.sess(), false),
|
tm: create_target_machine(cx.sess(), false),
|
||||||
};
|
};
|
||||||
|
|
||||||
ModuleTranslation {
|
ModuleCodegen {
|
||||||
name: cgu_name,
|
name: cgu_name,
|
||||||
source: ModuleSource::Translated(llvm_module),
|
source: ModuleSource::Codegened(llvm_module),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
llmod_id,
|
llmod_id,
|
||||||
}
|
}
|
||||||
|
@ -1286,13 +1286,13 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
providers.collect_and_partition_translation_items =
|
providers.collect_and_partition_mono_items =
|
||||||
collect_and_partition_translation_items;
|
collect_and_partition_mono_items;
|
||||||
|
|
||||||
providers.is_translated_item = is_translated_item;
|
providers.is_codegened_item = is_codegened_item;
|
||||||
|
|
||||||
providers.codegen_unit = |tcx, name| {
|
providers.codegen_unit = |tcx, name| {
|
||||||
let (_, all) = tcx.collect_and_partition_translation_items(LOCAL_CRATE);
|
let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
|
||||||
all.iter()
|
all.iter()
|
||||||
.find(|cgu| *cgu.name() == name)
|
.find(|cgu| *cgu.name() == name)
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -1369,9 +1369,9 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
|
||||||
mod temp_stable_hash_impls {
|
mod temp_stable_hash_impls {
|
||||||
use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
|
use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
|
||||||
HashStable};
|
HashStable};
|
||||||
use ModuleTranslation;
|
use ModuleCodegen;
|
||||||
|
|
||||||
impl<HCX> HashStable<HCX> for ModuleTranslation {
|
impl<HCX> HashStable<HCX> for ModuleCodegen {
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
_: &mut HCX,
|
_: &mut HCX,
|
||||||
_: &mut StableHasher<W>) {
|
_: &mut StableHasher<W>) {
|
|
@ -108,7 +108,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_insn(&self, category: &str) {
|
fn count_insn(&self, category: &str) {
|
||||||
if self.cx.sess().trans_stats() {
|
if self.cx.sess().codegen_stats() {
|
||||||
self.cx.stats.borrow_mut().n_llvm_insns += 1;
|
self.cx.stats.borrow_mut().n_llvm_insns += 1;
|
||||||
}
|
}
|
||||||
if self.cx.sess().count_llvm_insns() {
|
if self.cx.sess().count_llvm_insns() {
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//! Handles translation of callees as well as other call-related
|
//! Handles codegen of callees as well as other call-related
|
||||||
//! things. Callees are a superset of normal rust values and sometimes
|
//! things. Callees are a superset of normal rust values and sometimes
|
||||||
//! have different representations. In particular, top-level fn items
|
//! have different representations. In particular, top-level fn items
|
||||||
//! and methods are represented as just a fn ptr and not a full
|
//! and methods are represented as just a fn ptr and not a full
|
||||||
|
@ -28,7 +28,7 @@ use rustc::ty::layout::LayoutOf;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc_target::spec::PanicStrategy;
|
use rustc_target::spec::PanicStrategy;
|
||||||
|
|
||||||
/// Translates a reference to a fn/method item, monomorphizing and
|
/// Codegens a reference to a fn/method item, monomorphizing and
|
||||||
/// inlining as it goes.
|
/// inlining as it goes.
|
||||||
///
|
///
|
||||||
/// # Parameters
|
/// # Parameters
|
||||||
|
@ -116,9 +116,9 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
// just declared.
|
// just declared.
|
||||||
//
|
//
|
||||||
// This is sort of subtle. Inside our codegen unit we started off
|
// This is sort of subtle. Inside our codegen unit we started off
|
||||||
// compilation by predefining all our own `TransItem` instances. That
|
// compilation by predefining all our own `MonoItem` instances. That
|
||||||
// is, everything we're translating ourselves is already defined. That
|
// is, everything we're codegenning ourselves is already defined. That
|
||||||
// means that anything we're actually translating in this codegen unit
|
// means that anything we're actually codegenning in this codegen unit
|
||||||
// will have hit the above branch in `get_declared_value`. As a result,
|
// will have hit the above branch in `get_declared_value`. As a result,
|
||||||
// we're guaranteed here that we're declaring a symbol that won't get
|
// we're guaranteed here that we're declaring a symbol that won't get
|
||||||
// defined, or in other words we're referencing a value from another
|
// defined, or in other words we're referencing a value from another
|
||||||
|
@ -181,7 +181,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a non-generic function
|
// This is a non-generic function
|
||||||
if cx.tcx.is_translated_item(instance_def_id) {
|
if cx.tcx.is_codegened_item(instance_def_id) {
|
||||||
// This is a function that is instantiated in the local crate
|
// This is a function that is instantiated in the local crate
|
||||||
|
|
||||||
if instance_def_id.is_local() {
|
if instance_def_id.is_local() {
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#![allow(non_camel_case_types, non_snake_case)]
|
#![allow(non_camel_case_types, non_snake_case)]
|
||||||
|
|
||||||
//! Code that is useful in various trans modules.
|
//! Code that is useful in various codegen modules.
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::{ValueRef, ContextRef, TypeKind};
|
use llvm::{ValueRef, ContextRef, TypeKind};
|
||||||
|
@ -446,4 +446,3 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
_ => bug!("unexpected type {:?} to ty_fn_sig", ty)
|
_ => bug!("unexpected type {:?} to ty_fn_sig", ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
|
||||||
ref attrs, span, node: hir::ItemStatic(..), ..
|
ref attrs, span, node: hir::ItemStatic(..), ..
|
||||||
}) => {
|
}) => {
|
||||||
if declare::get_declared_value(cx, &sym[..]).is_some() {
|
if declare::get_declared_value(cx, &sym[..]).is_some() {
|
||||||
span_bug!(span, "trans: Conflicting symbol names for static?");
|
span_bug!(span, "Conflicting symbol names for static?");
|
||||||
}
|
}
|
||||||
|
|
||||||
let g = declare::define_global(cx, &sym[..], llty).unwrap();
|
let g = declare::define_global(cx, &sym[..], llty).unwrap();
|
||||||
|
@ -145,7 +145,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
|
||||||
hir_map::NodeForeignItem(&hir::ForeignItem {
|
hir_map::NodeForeignItem(&hir::ForeignItem {
|
||||||
ref attrs, span, node: hir::ForeignItemStatic(..), ..
|
ref attrs, span, node: hir::ForeignItemStatic(..), ..
|
||||||
}) => {
|
}) => {
|
||||||
let g = if let Some(linkage) = cx.tcx.trans_fn_attrs(def_id).linkage {
|
let g = if let Some(linkage) = cx.tcx.codegen_fn_attrs(def_id).linkage {
|
||||||
// If this is a static with a linkage specified, then we need to handle
|
// If this is a static with a linkage specified, then we need to handle
|
||||||
// it a little specially. The typesystem prevents things like &T and
|
// it a little specially. The typesystem prevents things like &T and
|
||||||
// extern "C" fn() from being non-null, so we can't just declare a
|
// extern "C" fn() from being non-null, so we can't just declare a
|
||||||
|
@ -221,8 +221,8 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
|
||||||
// However, in some scenarios we defer emission of statics to downstream
|
// However, in some scenarios we defer emission of statics to downstream
|
||||||
// crates, so there are cases where a static with an upstream DefId
|
// crates, so there are cases where a static with an upstream DefId
|
||||||
// is actually present in the current crate. We can find out via the
|
// is actually present in the current crate. We can find out via the
|
||||||
// is_translated_item query.
|
// is_codegened_item query.
|
||||||
if !cx.tcx.is_translated_item(def_id) {
|
if !cx.tcx.is_codegened_item(def_id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
|
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
|
||||||
}
|
}
|
||||||
|
@ -243,14 +243,14 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
|
||||||
g
|
g
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
pub fn codegen_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
is_mutable: bool,
|
is_mutable: bool,
|
||||||
attrs: &[ast::Attribute]) {
|
attrs: &[ast::Attribute]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let g = get_static(cx, def_id);
|
let g = get_static(cx, def_id);
|
||||||
|
|
||||||
let v = match ::mir::trans_static_initializer(cx, def_id) {
|
let v = match ::mir::codegen_static_initializer(cx, def_id) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
// Error has already been reported
|
// Error has already been reported
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
|
@ -290,7 +290,7 @@ pub fn trans_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
|
|
||||||
// To avoid breaking any invariants, we leave around the old
|
// To avoid breaking any invariants, we leave around the old
|
||||||
// global for the moment; we'll replace all references to it
|
// global for the moment; we'll replace all references to it
|
||||||
// with the new global later. (See base::trans_crate.)
|
// with the new global later. (See base::codegen_backend.)
|
||||||
cx.statics_to_rauw.borrow_mut().push((g, new_g));
|
cx.statics_to_rauw.borrow_mut().push((g, new_g));
|
||||||
new_g
|
new_g
|
||||||
};
|
};
|
|
@ -69,7 +69,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
|
||||||
/// Val is a ValueRef holding a *[T].
|
/// Val is a ValueRef holding a *[T].
|
||||||
///
|
///
|
||||||
/// Needed because LLVM loses pointer->pointee association
|
/// Needed because LLVM loses pointer->pointee association
|
||||||
/// when we ptrcast, and we have to ptrcast during translation
|
/// when we ptrcast, and we have to ptrcast during codegen
|
||||||
/// of a [T] const because we form a slice, a (*T,usize) pair, not
|
/// of a [T] const because we form a slice, a (*T,usize) pair, not
|
||||||
/// a pointer to an LLVM array type. Similar for trait objects.
|
/// a pointer to an LLVM array type. Similar for trait objects.
|
||||||
pub const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
|
pub const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
|
||||||
|
@ -81,7 +81,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
|
||||||
pub statics: RefCell<FxHashMap<ValueRef, DefId>>,
|
pub statics: RefCell<FxHashMap<ValueRef, DefId>>,
|
||||||
|
|
||||||
/// List of globals for static variables which need to be passed to the
|
/// List of globals for static variables which need to be passed to the
|
||||||
/// LLVM function ReplaceAllUsesWith (RAUW) when translation is complete.
|
/// LLVM function ReplaceAllUsesWith (RAUW) when codegen is complete.
|
||||||
/// (We have to make sure we don't invalidate any ValueRefs referring
|
/// (We have to make sure we don't invalidate any ValueRefs referring
|
||||||
/// to constants.)
|
/// to constants.)
|
||||||
pub statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
|
pub statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
|
||||||
|
@ -351,7 +351,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
|
||||||
// The exception handling personality function.
|
// The exception handling personality function.
|
||||||
//
|
//
|
||||||
// If our compilation unit has the `eh_personality` lang item somewhere
|
// If our compilation unit has the `eh_personality` lang item somewhere
|
||||||
// within it, then we just need to translate that. Otherwise, we're
|
// within it, then we just need to codegen that. Otherwise, we're
|
||||||
// building an rlib which will depend on some upstream implementation of
|
// building an rlib which will depend on some upstream implementation of
|
||||||
// this function, so we just codegen a generic reference to it. We don't
|
// this function, so we just codegen a generic reference to it. We don't
|
||||||
// specify any of the types for the function, we just make it a symbol
|
// specify any of the types for the function, we just make it a symbol
|
|
@ -131,9 +131,9 @@
|
||||||
//! when generating prologue instructions we have to make sure that we don't
|
//! when generating prologue instructions we have to make sure that we don't
|
||||||
//! emit source location information until the 'real' function body begins. For
|
//! emit source location information until the 'real' function body begins. For
|
||||||
//! this reason, source location emission is disabled by default for any new
|
//! this reason, source location emission is disabled by default for any new
|
||||||
//! function being translated and is only activated after a call to the third
|
//! function being codegened and is only activated after a call to the third
|
||||||
//! function from the list above, `start_emitting_source_locations()`. This
|
//! function from the list above, `start_emitting_source_locations()`. This
|
||||||
//! function should be called right before regularly starting to translate the
|
//! function should be called right before regularly starting to codegen the
|
||||||
//! top-level block of the given function.
|
//! top-level block of the given function.
|
||||||
//!
|
//!
|
||||||
//! There is one exception to the above rule: `llvm.dbg.declare` instruction
|
//! There is one exception to the above rule: `llvm.dbg.declare` instruction
|
|
@ -23,7 +23,7 @@ use llvm::{self, ValueRef};
|
||||||
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
|
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
|
||||||
DICompositeType, DILexicalBlock, DIFlags};
|
DICompositeType, DILexicalBlock, DIFlags};
|
||||||
|
|
||||||
use rustc::hir::TransFnAttrFlags;
|
use rustc::hir::CodegenFnAttrFlags;
|
||||||
use rustc::hir::def::CtorKind;
|
use rustc::hir::def::CtorKind;
|
||||||
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
|
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
|
||||||
use rustc::ty::fold::TypeVisitor;
|
use rustc::ty::fold::TypeVisitor;
|
||||||
|
@ -1645,13 +1645,13 @@ pub fn create_global_var_metadata(cx: &CodegenCx,
|
||||||
}
|
}
|
||||||
|
|
||||||
let tcx = cx.tcx;
|
let tcx = cx.tcx;
|
||||||
let attrs = tcx.trans_fn_attrs(def_id);
|
let attrs = tcx.codegen_fn_attrs(def_id);
|
||||||
|
|
||||||
if attrs.flags.contains(TransFnAttrFlags::NO_DEBUG) {
|
if attrs.flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let no_mangle = attrs.flags.contains(TransFnAttrFlags::NO_MANGLE);
|
let no_mangle = attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE);
|
||||||
// We may want to remove the namespace scope if we're in an extern block, see:
|
// We may want to remove the namespace scope if we're in an extern block, see:
|
||||||
// https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952
|
// https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952
|
||||||
let var_scope = get_namespace_for_item(cx, def_id);
|
let var_scope = get_namespace_for_item(cx, def_id);
|
|
@ -23,7 +23,7 @@ use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
|
||||||
use llvm;
|
use llvm;
|
||||||
use llvm::{ModuleRef, ContextRef, ValueRef};
|
use llvm::{ModuleRef, ContextRef, ValueRef};
|
||||||
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
|
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
|
||||||
use rustc::hir::TransFnAttrFlags;
|
use rustc::hir::CodegenFnAttrFlags;
|
||||||
use rustc::hir::def_id::{DefId, CrateNum};
|
use rustc::hir::def_id::{DefId, CrateNum};
|
||||||
use rustc::ty::subst::{Substs, UnpackedKind};
|
use rustc::ty::subst::{Substs, UnpackedKind};
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
if let InstanceDef::Item(def_id) = instance.def {
|
if let InstanceDef::Item(def_id) = instance.def {
|
||||||
if cx.tcx.trans_fn_attrs(def_id).flags.contains(TransFnAttrFlags::NO_DEBUG) {
|
if cx.tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
|
||||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -50,9 +50,9 @@ pub fn set_source_location(
|
||||||
/// Enables emitting source locations for the given functions.
|
/// Enables emitting source locations for the given functions.
|
||||||
///
|
///
|
||||||
/// Since we don't want source locations to be emitted for the function prelude,
|
/// Since we don't want source locations to be emitted for the function prelude,
|
||||||
/// they are disabled when beginning to translate a new function. This functions
|
/// they are disabled when beginning to codegen a new function. This functions
|
||||||
/// switches source location emitting on and must therefore be called before the
|
/// switches source location emitting on and must therefore be called before the
|
||||||
/// first real statement/expression of the function is translated.
|
/// first real statement/expression of the function is codegened.
|
||||||
pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) {
|
pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) {
|
||||||
match *dbg_context {
|
match *dbg_context {
|
||||||
FunctionDebugContext::RegularContext(ref data) => {
|
FunctionDebugContext::RegularContext(ref data) => {
|
|
@ -31,7 +31,7 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool
|
||||||
// externally visible or by being inlined into something externally
|
// externally visible or by being inlined into something externally
|
||||||
// visible). It might better to use the `exported_items` set from
|
// visible). It might better to use the `exported_items` set from
|
||||||
// `driver::CrateAnalysis` in the future, but (atm) this set is not
|
// `driver::CrateAnalysis` in the future, but (atm) this set is not
|
||||||
// available in the translation pass.
|
// available in the codegen pass.
|
||||||
!cx.tcx.is_reachable_non_generic(def_id)
|
!cx.tcx.is_reachable_non_generic(def_id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//!
|
//!
|
||||||
//! Prefer using functions and methods from this module rather than calling LLVM
|
//! Prefer using functions and methods from this module rather than calling LLVM
|
||||||
//! functions directly. These functions do some additional work to ensure we do
|
//! functions directly. These functions do some additional work to ensure we do
|
||||||
//! the right thing given the preconceptions of trans.
|
//! the right thing given the preconceptions of codegen.
|
||||||
//!
|
//!
|
||||||
//! Some useful guidelines:
|
//! Some useful guidelines:
|
||||||
//!
|
//!
|
|
@ -84,8 +84,8 @@ fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
|
||||||
|
|
||||||
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
|
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
|
||||||
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
|
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
|
||||||
/// add them to librustc_trans/trans/context.rs
|
/// add them to librustc_codegen_llvm/context.rs
|
||||||
pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
||||||
callee_ty: Ty<'tcx>,
|
callee_ty: Ty<'tcx>,
|
||||||
fn_ty: &FnType<'tcx, Ty<'tcx>>,
|
fn_ty: &FnType<'tcx, Ty<'tcx>>,
|
||||||
args: &[OperandRef<'tcx>],
|
args: &[OperandRef<'tcx>],
|
||||||
|
@ -386,7 +386,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
"discriminant_value" => {
|
"discriminant_value" => {
|
||||||
args[0].deref(bx.cx).trans_get_discr(bx, ret_ty)
|
args[0].deref(bx.cx).codegen_get_discr(bx, ret_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
"align_offset" => {
|
"align_offset" => {
|
||||||
|
@ -743,9 +743,9 @@ fn try_intrinsic<'a, 'tcx>(
|
||||||
let ptr_align = bx.tcx().data_layout.pointer_align;
|
let ptr_align = bx.tcx().data_layout.pointer_align;
|
||||||
bx.store(C_null(Type::i8p(&bx.cx)), dest, ptr_align);
|
bx.store(C_null(Type::i8p(&bx.cx)), dest, ptr_align);
|
||||||
} else if wants_msvc_seh(bx.sess()) {
|
} else if wants_msvc_seh(bx.sess()) {
|
||||||
trans_msvc_try(bx, cx, func, data, local_ptr, dest);
|
codegen_msvc_try(bx, cx, func, data, local_ptr, dest);
|
||||||
} else {
|
} else {
|
||||||
trans_gnu_try(bx, cx, func, data, local_ptr, dest);
|
codegen_gnu_try(bx, cx, func, data, local_ptr, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +756,7 @@ fn try_intrinsic<'a, 'tcx>(
|
||||||
// instructions are meant to work for all targets, as of the time of this
|
// instructions are meant to work for all targets, as of the time of this
|
||||||
// writing, however, LLVM does not recommend the usage of these new instructions
|
// writing, however, LLVM does not recommend the usage of these new instructions
|
||||||
// as the old ones are still more optimized.
|
// as the old ones are still more optimized.
|
||||||
fn trans_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
||||||
cx: &CodegenCx,
|
cx: &CodegenCx,
|
||||||
func: ValueRef,
|
func: ValueRef,
|
||||||
data: ValueRef,
|
data: ValueRef,
|
||||||
|
@ -857,14 +857,14 @@ fn trans_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
||||||
// of exceptions (e.g. the normal semantics of LLVM's landingpad and invoke
|
// of exceptions (e.g. the normal semantics of LLVM's landingpad and invoke
|
||||||
// instructions).
|
// instructions).
|
||||||
//
|
//
|
||||||
// This translation is a little surprising because we always call a shim
|
// This codegen is a little surprising because we always call a shim
|
||||||
// function instead of inlining the call to `invoke` manually here. This is done
|
// function instead of inlining the call to `invoke` manually here. This is done
|
||||||
// because in LLVM we're only allowed to have one personality per function
|
// because in LLVM we're only allowed to have one personality per function
|
||||||
// definition. The call to the `try` intrinsic is being inlined into the
|
// definition. The call to the `try` intrinsic is being inlined into the
|
||||||
// function calling it, and that function may already have other personality
|
// function calling it, and that function may already have other personality
|
||||||
// functions in play. By calling a shim we're guaranteed that our shim will have
|
// functions in play. By calling a shim we're guaranteed that our shim will have
|
||||||
// the right personality function.
|
// the right personality function.
|
||||||
fn trans_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
||||||
cx: &CodegenCx,
|
cx: &CodegenCx,
|
||||||
func: ValueRef,
|
func: ValueRef,
|
||||||
data: ValueRef,
|
data: ValueRef,
|
||||||
|
@ -873,7 +873,7 @@ fn trans_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
||||||
let llfn = get_rust_try_fn(cx, &mut |bx| {
|
let llfn = get_rust_try_fn(cx, &mut |bx| {
|
||||||
let cx = bx.cx;
|
let cx = bx.cx;
|
||||||
|
|
||||||
// Translates the shims described above:
|
// Codegens the shims described above:
|
||||||
//
|
//
|
||||||
// bx:
|
// bx:
|
||||||
// invoke %func(%args...) normal %normal unwind %catch
|
// invoke %func(%args...) normal %normal unwind %catch
|
||||||
|
@ -922,13 +922,13 @@ fn trans_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
||||||
bx.store(ret, dest, i32_align);
|
bx.store(ret, dest, i32_align);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to give a Block to a closure to translate a shim function.
|
// Helper function to give a Block to a closure to codegen a shim function.
|
||||||
// This is currently primarily used for the `try` intrinsic functions above.
|
// This is currently primarily used for the `try` intrinsic functions above.
|
||||||
fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
inputs: Vec<Ty<'tcx>>,
|
inputs: Vec<Ty<'tcx>>,
|
||||||
output: Ty<'tcx>,
|
output: Ty<'tcx>,
|
||||||
trans: &mut for<'b> FnMut(Builder<'b, 'tcx>))
|
codegen: &mut for<'b> FnMut(Builder<'b, 'tcx>))
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig(
|
let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig(
|
||||||
inputs.into_iter(),
|
inputs.into_iter(),
|
||||||
|
@ -939,7 +939,7 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
)));
|
)));
|
||||||
let llfn = declare::define_internal_fn(cx, name, rust_fn_ty);
|
let llfn = declare::define_internal_fn(cx, name, rust_fn_ty);
|
||||||
let bx = Builder::new_block(cx, llfn, "entry-block");
|
let bx = Builder::new_block(cx, llfn, "entry-block");
|
||||||
trans(bx);
|
codegen(bx);
|
||||||
llfn
|
llfn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,7 +948,7 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
//
|
//
|
||||||
// This function is only generated once and is then cached.
|
// This function is only generated once and is then cached.
|
||||||
fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
trans: &mut for<'b> FnMut(Builder<'b, 'tcx>))
|
codegen: &mut for<'b> FnMut(Builder<'b, 'tcx>))
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
if let Some(llfn) = cx.rust_try_fn.get() {
|
if let Some(llfn) = cx.rust_try_fn.get() {
|
||||||
return llfn;
|
return llfn;
|
||||||
|
@ -965,7 +965,7 @@ fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
Abi::Rust
|
Abi::Rust
|
||||||
)));
|
)));
|
||||||
let output = tcx.types.i32;
|
let output = tcx.types.i32;
|
||||||
let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, trans);
|
let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen);
|
||||||
cx.rust_try_fn.set(Some(rust_try));
|
cx.rust_try_fn.set(Some(rust_try));
|
||||||
return rust_try
|
return rust_try
|
||||||
}
|
}
|
||||||
|
@ -1069,7 +1069,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
|
||||||
let n: usize = match name["simd_shuffle".len()..].parse() {
|
let n: usize = match name["simd_shuffle".len()..].parse() {
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(_) => span_bug!(span,
|
Err(_) => span_bug!(span,
|
||||||
"bad `simd_shuffle` instruction only caught in trans?")
|
"bad `simd_shuffle` instruction only caught in codegen?")
|
||||||
};
|
};
|
||||||
|
|
||||||
require_simd!(ret_ty, "return");
|
require_simd!(ret_ty, "return");
|
|
@ -49,7 +49,7 @@ extern crate rustc_demangle;
|
||||||
extern crate rustc_incremental;
|
extern crate rustc_incremental;
|
||||||
extern crate rustc_llvm as llvm;
|
extern crate rustc_llvm as llvm;
|
||||||
extern crate rustc_platform_intrinsics as intrinsics;
|
extern crate rustc_platform_intrinsics as intrinsics;
|
||||||
extern crate rustc_trans_utils;
|
extern crate rustc_codegen_utils;
|
||||||
|
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
#[macro_use] extern crate syntax;
|
#[macro_use] extern crate syntax;
|
||||||
|
@ -79,12 +79,12 @@ use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||||
use rustc_mir::monomorphize;
|
use rustc_mir::monomorphize;
|
||||||
use rustc_trans_utils::trans_crate::TransCrate;
|
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||||
|
|
||||||
mod diagnostics;
|
mod diagnostics;
|
||||||
|
|
||||||
mod back {
|
mod back {
|
||||||
pub use rustc_trans_utils::symbol_names;
|
pub use rustc_codegen_utils::symbol_names;
|
||||||
mod archive;
|
mod archive;
|
||||||
pub mod bytecode;
|
pub mod bytecode;
|
||||||
mod command;
|
mod command;
|
||||||
|
@ -116,23 +116,23 @@ mod metadata;
|
||||||
mod meth;
|
mod meth;
|
||||||
mod mir;
|
mod mir;
|
||||||
mod time_graph;
|
mod time_graph;
|
||||||
mod trans_item;
|
mod mono_item;
|
||||||
mod type_;
|
mod type_;
|
||||||
mod type_of;
|
mod type_of;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
pub struct LlvmTransCrate(());
|
pub struct LlvmCodegenBackend(());
|
||||||
|
|
||||||
impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis
|
impl !Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
|
||||||
impl !Sync for LlvmTransCrate {}
|
impl !Sync for LlvmCodegenBackend {}
|
||||||
|
|
||||||
impl LlvmTransCrate {
|
impl LlvmCodegenBackend {
|
||||||
pub fn new() -> Box<TransCrate> {
|
pub fn new() -> Box<CodegenBackend> {
|
||||||
box LlvmTransCrate(())
|
box LlvmCodegenBackend(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TransCrate for LlvmTransCrate {
|
impl CodegenBackend for LlvmCodegenBackend {
|
||||||
fn init(&self, sess: &Session) {
|
fn init(&self, sess: &Session) {
|
||||||
llvm_util::init(sess); // Make sure llvm is inited
|
llvm_util::init(sess); // Make sure llvm is inited
|
||||||
}
|
}
|
||||||
|
@ -197,27 +197,28 @@ impl TransCrate for LlvmTransCrate {
|
||||||
attributes::provide_extern(providers);
|
attributes::provide_extern(providers);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_crate<'a, 'tcx>(
|
fn codegen_crate<'a, 'tcx>(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
rx: mpsc::Receiver<Box<Any + Send>>
|
rx: mpsc::Receiver<Box<Any + Send>>
|
||||||
) -> Box<Any> {
|
) -> Box<Any> {
|
||||||
box base::trans_crate(tcx, rx)
|
box base::codegen_crate(tcx, rx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_trans_and_link(
|
fn join_codegen_and_link(
|
||||||
&self,
|
&self,
|
||||||
trans: Box<Any>,
|
ongoing_codegen: Box<Any>,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
dep_graph: &DepGraph,
|
dep_graph: &DepGraph,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> Result<(), CompileIncomplete>{
|
) -> Result<(), CompileIncomplete>{
|
||||||
use rustc::util::common::time;
|
use rustc::util::common::time;
|
||||||
let (trans, work_products) = trans.downcast::<::back::write::OngoingCrateTranslation>()
|
let (ongoing_codegen, work_products) =
|
||||||
.expect("Expected LlvmTransCrate's OngoingCrateTranslation, found Box<Any>")
|
ongoing_codegen.downcast::<::back::write::OngoingCodegen>()
|
||||||
|
.expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
|
||||||
.join(sess);
|
.join(sess);
|
||||||
if sess.opts.debugging_opts.incremental_info {
|
if sess.opts.debugging_opts.incremental_info {
|
||||||
back::write::dump_incremental_data(&trans);
|
back::write::dump_incremental_data(&ongoing_codegen);
|
||||||
}
|
}
|
||||||
|
|
||||||
time(sess,
|
time(sess,
|
||||||
|
@ -234,24 +235,25 @@ impl TransCrate for LlvmTransCrate {
|
||||||
// Run the linker on any artifacts that resulted from the LLVM run.
|
// Run the linker on any artifacts that resulted from the LLVM run.
|
||||||
// This should produce either a finished executable or library.
|
// This should produce either a finished executable or library.
|
||||||
time(sess, "linking", || {
|
time(sess, "linking", || {
|
||||||
back::link::link_binary(sess, &trans, outputs, &trans.crate_name.as_str());
|
back::link::link_binary(sess, &ongoing_codegen,
|
||||||
|
outputs, &ongoing_codegen.crate_name.as_str());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now that we won't touch anything in the incremental compilation directory
|
// Now that we won't touch anything in the incremental compilation directory
|
||||||
// any more, we can finalize it (which involves renaming it)
|
// any more, we can finalize it (which involves renaming it)
|
||||||
rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
|
rustc_incremental::finalize_session_directory(sess, ongoing_codegen.link.crate_hash);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the entrypoint for a hot plugged rustc_trans
|
/// This is the entrypoint for a hot plugged rustc_codegen_llvm
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn __rustc_codegen_backend() -> Box<TransCrate> {
|
pub fn __rustc_codegen_backend() -> Box<CodegenBackend> {
|
||||||
LlvmTransCrate::new()
|
LlvmCodegenBackend::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ModuleTranslation {
|
struct ModuleCodegen {
|
||||||
/// The name of the module. When the crate may be saved between
|
/// The name of the module. When the crate may be saved between
|
||||||
/// compilations, incremental compilation requires that name be
|
/// compilations, incremental compilation requires that name be
|
||||||
/// unique amongst **all** crates. Therefore, it should contain
|
/// unique amongst **all** crates. Therefore, it should contain
|
||||||
|
@ -270,10 +272,10 @@ enum ModuleKind {
|
||||||
Allocator,
|
Allocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleTranslation {
|
impl ModuleCodegen {
|
||||||
fn llvm(&self) -> Option<&ModuleLlvm> {
|
fn llvm(&self) -> Option<&ModuleLlvm> {
|
||||||
match self.source {
|
match self.source {
|
||||||
ModuleSource::Translated(ref llvm) => Some(llvm),
|
ModuleSource::Codegened(ref llvm) => Some(llvm),
|
||||||
ModuleSource::Preexisting(_) => None,
|
ModuleSource::Preexisting(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,7 +287,7 @@ impl ModuleTranslation {
|
||||||
outputs: &OutputFilenames) -> CompiledModule {
|
outputs: &OutputFilenames) -> CompiledModule {
|
||||||
let pre_existing = match self.source {
|
let pre_existing = match self.source {
|
||||||
ModuleSource::Preexisting(_) => true,
|
ModuleSource::Preexisting(_) => true,
|
||||||
ModuleSource::Translated(_) => false,
|
ModuleSource::Codegened(_) => false,
|
||||||
};
|
};
|
||||||
let object = if emit_obj {
|
let object = if emit_obj {
|
||||||
Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
|
Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
|
||||||
|
@ -332,7 +334,7 @@ enum ModuleSource {
|
||||||
Preexisting(WorkProduct),
|
Preexisting(WorkProduct),
|
||||||
|
|
||||||
/// Rebuild from this LLVM module.
|
/// Rebuild from this LLVM module.
|
||||||
Translated(ModuleLlvm),
|
Codegened(ModuleLlvm),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -355,7 +357,7 @@ impl Drop for ModuleLlvm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CrateTranslation {
|
struct CodegenResults {
|
||||||
crate_name: Symbol,
|
crate_name: Symbol,
|
||||||
modules: Vec<CompiledModule>,
|
modules: Vec<CompiledModule>,
|
||||||
allocator_module: Option<CompiledModule>,
|
allocator_module: Option<CompiledModule>,
|
||||||
|
@ -387,4 +389,4 @@ struct CrateInfo {
|
||||||
missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
|
missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
|
__build_diagnostic_array! { librustc_codegen_llvm, DIAGNOSTICS }
|
|
@ -249,7 +249,7 @@ pub(crate) fn print(req: PrintRequest, sess: &Session) {
|
||||||
match req {
|
match req {
|
||||||
PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
|
PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
|
||||||
PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
|
PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
|
||||||
_ => bug!("rustc_trans can't handle print request: {:?}", req),
|
_ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,25 +34,25 @@ use super::operand::OperandRef;
|
||||||
use super::operand::OperandValue::{Pair, Ref, Immediate};
|
use super::operand::OperandValue::{Pair, Ref, Immediate};
|
||||||
|
|
||||||
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
pub fn trans_block(&mut self, bb: mir::BasicBlock) {
|
pub fn codegen_block(&mut self, bb: mir::BasicBlock) {
|
||||||
let mut bx = self.build_block(bb);
|
let mut bx = self.build_block(bb);
|
||||||
let data = &self.mir[bb];
|
let data = &self.mir[bb];
|
||||||
|
|
||||||
debug!("trans_block({:?}={:?})", bb, data);
|
debug!("codegen_block({:?}={:?})", bb, data);
|
||||||
|
|
||||||
for statement in &data.statements {
|
for statement in &data.statements {
|
||||||
bx = self.trans_statement(bx, statement);
|
bx = self.codegen_statement(bx, statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.trans_terminator(bx, bb, data.terminator());
|
self.codegen_terminator(bx, bb, data.terminator());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_terminator(&mut self,
|
fn codegen_terminator(&mut self,
|
||||||
mut bx: Builder<'a, 'tcx>,
|
mut bx: Builder<'a, 'tcx>,
|
||||||
bb: mir::BasicBlock,
|
bb: mir::BasicBlock,
|
||||||
terminator: &mir::Terminator<'tcx>)
|
terminator: &mir::Terminator<'tcx>)
|
||||||
{
|
{
|
||||||
debug!("trans_terminator: {:?}", terminator);
|
debug!("codegen_terminator: {:?}", terminator);
|
||||||
|
|
||||||
// Create the cleanup bundle, if needed.
|
// Create the cleanup bundle, if needed.
|
||||||
let tcx = bx.tcx();
|
let tcx = bx.tcx();
|
||||||
|
@ -190,7 +190,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
|
mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
|
||||||
let discr = self.trans_operand(&bx, discr);
|
let discr = self.codegen_operand(&bx, discr);
|
||||||
if switch_ty == bx.tcx().types.bool {
|
if switch_ty == bx.tcx().types.bool {
|
||||||
let lltrue = llblock(self, targets[0]);
|
let lltrue = llblock(self, targets[0]);
|
||||||
let llfalse = llblock(self, targets[1]);
|
let llfalse = llblock(self, targets[1]);
|
||||||
|
@ -221,7 +221,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
PassMode::Direct(_) | PassMode::Pair(..) => {
|
PassMode::Direct(_) | PassMode::Pair(..) => {
|
||||||
let op = self.trans_consume(&bx, &mir::Place::Local(mir::RETURN_PLACE));
|
let op = self.codegen_consume(&bx, &mir::Place::Local(mir::RETURN_PLACE));
|
||||||
if let Ref(llval, align) = op.val {
|
if let Ref(llval, align) = op.val {
|
||||||
bx.load(llval, align)
|
bx.load(llval, align)
|
||||||
} else {
|
} else {
|
||||||
|
@ -233,10 +233,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
let op = match self.locals[mir::RETURN_PLACE] {
|
let op = match self.locals[mir::RETURN_PLACE] {
|
||||||
LocalRef::Operand(Some(op)) => op,
|
LocalRef::Operand(Some(op)) => op,
|
||||||
LocalRef::Operand(None) => bug!("use of return before def"),
|
LocalRef::Operand(None) => bug!("use of return before def"),
|
||||||
LocalRef::Place(tr_place) => {
|
LocalRef::Place(cg_place) => {
|
||||||
OperandRef {
|
OperandRef {
|
||||||
val: Ref(tr_place.llval, tr_place.align),
|
val: Ref(cg_place.llval, cg_place.align),
|
||||||
layout: tr_place.layout
|
layout: cg_place.layout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -275,7 +275,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let place = self.trans_place(&bx, location);
|
let place = self.codegen_place(&bx, location);
|
||||||
let mut args: &[_] = &[place.llval, place.llextra];
|
let mut args: &[_] = &[place.llval, place.llextra];
|
||||||
args = &args[..1 + place.has_extra() as usize];
|
args = &args[..1 + place.has_extra() as usize];
|
||||||
let (drop_fn, fn_ty) = match ty.sty {
|
let (drop_fn, fn_ty) = match ty.sty {
|
||||||
|
@ -301,7 +301,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
|
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
|
||||||
let cond = self.trans_operand(&bx, cond).immediate();
|
let cond = self.codegen_operand(&bx, cond).immediate();
|
||||||
let mut const_cond = common::const_to_opt_u128(cond, false).map(|c| c == 1);
|
let mut const_cond = common::const_to_opt_u128(cond, false).map(|c| c == 1);
|
||||||
|
|
||||||
// This case can currently arise only from functions marked
|
// This case can currently arise only from functions marked
|
||||||
|
@ -317,7 +317,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't translate the panic block if success if known.
|
// Don't codegen the panic block if success if known.
|
||||||
if const_cond == Some(expected) {
|
if const_cond == Some(expected) {
|
||||||
funclet_br(self, bx, target);
|
funclet_br(self, bx, target);
|
||||||
return;
|
return;
|
||||||
|
@ -353,8 +353,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
// Put together the arguments to the panic entry point.
|
// Put together the arguments to the panic entry point.
|
||||||
let (lang_item, args) = match *msg {
|
let (lang_item, args) = match *msg {
|
||||||
EvalErrorKind::BoundsCheck { ref len, ref index } => {
|
EvalErrorKind::BoundsCheck { ref len, ref index } => {
|
||||||
let len = self.trans_operand(&mut bx, len).immediate();
|
let len = self.codegen_operand(&mut bx, len).immediate();
|
||||||
let index = self.trans_operand(&mut bx, index).immediate();
|
let index = self.codegen_operand(&mut bx, index).immediate();
|
||||||
|
|
||||||
let file_line_col = C_struct(bx.cx, &[filename, line, col], false);
|
let file_line_col = C_struct(bx.cx, &[filename, line, col], false);
|
||||||
let file_line_col = consts::addr_of(bx.cx,
|
let file_line_col = consts::addr_of(bx.cx,
|
||||||
|
@ -386,17 +386,17 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
let fn_ty = FnType::of_instance(bx.cx, &instance);
|
let fn_ty = FnType::of_instance(bx.cx, &instance);
|
||||||
let llfn = callee::get_fn(bx.cx, instance);
|
let llfn = callee::get_fn(bx.cx, instance);
|
||||||
|
|
||||||
// Translate the actual panic invoke/call.
|
// Codegen the actual panic invoke/call.
|
||||||
do_call(self, bx, fn_ty, llfn, &args, None, cleanup);
|
do_call(self, bx, fn_ty, llfn, &args, None, cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::TerminatorKind::DropAndReplace { .. } => {
|
mir::TerminatorKind::DropAndReplace { .. } => {
|
||||||
bug!("undesugared DropAndReplace in trans: {:?}", terminator);
|
bug!("undesugared DropAndReplace in codegen: {:?}", terminator);
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::TerminatorKind::Call { ref func, ref args, ref destination, cleanup } => {
|
mir::TerminatorKind::Call { ref func, ref args, ref destination, cleanup } => {
|
||||||
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
|
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
|
||||||
let callee = self.trans_operand(&bx, func);
|
let callee = self.codegen_operand(&bx, func);
|
||||||
|
|
||||||
let (instance, mut llfn) = match callee.layout.ty.sty {
|
let (instance, mut llfn) = match callee.layout.ty.sty {
|
||||||
ty::TyFnDef(def_id, substs) => {
|
ty::TyFnDef(def_id, substs) => {
|
||||||
|
@ -419,7 +419,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
let abi = sig.abi;
|
let abi = sig.abi;
|
||||||
|
|
||||||
// Handle intrinsics old trans wants Expr's for, ourselves.
|
// Handle intrinsics old codegen wants Expr's for, ourselves.
|
||||||
let intrinsic = match def {
|
let intrinsic = match def {
|
||||||
Some(ty::InstanceDef::Intrinsic(def_id))
|
Some(ty::InstanceDef::Intrinsic(def_id))
|
||||||
=> Some(bx.tcx().item_name(def_id).as_str()),
|
=> Some(bx.tcx().item_name(def_id).as_str()),
|
||||||
|
@ -429,7 +429,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
|
|
||||||
if intrinsic == Some("transmute") {
|
if intrinsic == Some("transmute") {
|
||||||
let &(ref dest, target) = destination.as_ref().unwrap();
|
let &(ref dest, target) = destination.as_ref().unwrap();
|
||||||
self.trans_transmute(&bx, &args[0], dest);
|
self.codegen_transmute(&bx, &args[0], dest);
|
||||||
funclet_br(self, bx, target);
|
funclet_br(self, bx, target);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -467,7 +467,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
|
if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
|
||||||
use intrinsic::trans_intrinsic_call;
|
use intrinsic::codegen_intrinsic_call;
|
||||||
|
|
||||||
let dest = match ret_dest {
|
let dest = match ret_dest {
|
||||||
_ if fn_ty.ret.is_indirect() => llargs[0],
|
_ if fn_ty.ret.is_indirect() => llargs[0],
|
||||||
|
@ -504,12 +504,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.trans_operand(&bx, arg)
|
self.codegen_operand(&bx, arg)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
|
||||||
let callee_ty = instance.as_ref().unwrap().ty(bx.cx.tcx);
|
let callee_ty = instance.as_ref().unwrap().ty(bx.cx.tcx);
|
||||||
trans_intrinsic_call(&bx, callee_ty, &fn_ty, &args, dest,
|
codegen_intrinsic_call(&bx, callee_ty, &fn_ty, &args, dest,
|
||||||
terminator.source_info.span);
|
terminator.source_info.span);
|
||||||
|
|
||||||
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
||||||
|
@ -534,7 +534,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, arg) in first_args.iter().enumerate() {
|
for (i, arg) in first_args.iter().enumerate() {
|
||||||
let mut op = self.trans_operand(&bx, arg);
|
let mut op = self.codegen_operand(&bx, arg);
|
||||||
if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
|
if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
|
||||||
if let Pair(data_ptr, meta) = op.val {
|
if let Pair(data_ptr, meta) = op.val {
|
||||||
llfn = Some(meth::VirtualIndex::from_index(idx)
|
llfn = Some(meth::VirtualIndex::from_index(idx)
|
||||||
|
@ -556,10 +556,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.trans_argument(&bx, op, &mut llargs, &fn_ty.args[i]);
|
self.codegen_argument(&bx, op, &mut llargs, &fn_ty.args[i]);
|
||||||
}
|
}
|
||||||
if let Some(tup) = untuple {
|
if let Some(tup) = untuple {
|
||||||
self.trans_arguments_untupled(&bx, tup, &mut llargs,
|
self.codegen_arguments_untupled(&bx, tup, &mut llargs,
|
||||||
&fn_ty.args[first_args.len()..])
|
&fn_ty.args[first_args.len()..])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,13 +574,13 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
cleanup);
|
cleanup);
|
||||||
}
|
}
|
||||||
mir::TerminatorKind::GeneratorDrop |
|
mir::TerminatorKind::GeneratorDrop |
|
||||||
mir::TerminatorKind::Yield { .. } => bug!("generator ops in trans"),
|
mir::TerminatorKind::Yield { .. } => bug!("generator ops in codegen"),
|
||||||
mir::TerminatorKind::FalseEdges { .. } |
|
mir::TerminatorKind::FalseEdges { .. } |
|
||||||
mir::TerminatorKind::FalseUnwind { .. } => bug!("borrowck false edges in trans"),
|
mir::TerminatorKind::FalseUnwind { .. } => bug!("borrowck false edges in codegen"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_argument(&mut self,
|
fn codegen_argument(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
op: OperandRef<'tcx>,
|
op: OperandRef<'tcx>,
|
||||||
llargs: &mut Vec<ValueRef>,
|
llargs: &mut Vec<ValueRef>,
|
||||||
|
@ -601,7 +601,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
llargs.push(b);
|
llargs.push(b);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => bug!("trans_argument: {:?} invalid for pair arugment", op)
|
_ => bug!("codegen_argument: {:?} invalid for pair arugment", op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,25 +659,25 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
llargs.push(llval);
|
llargs.push(llval);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_arguments_untupled(&mut self,
|
fn codegen_arguments_untupled(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
operand: &mir::Operand<'tcx>,
|
operand: &mir::Operand<'tcx>,
|
||||||
llargs: &mut Vec<ValueRef>,
|
llargs: &mut Vec<ValueRef>,
|
||||||
args: &[ArgType<'tcx, Ty<'tcx>>]) {
|
args: &[ArgType<'tcx, Ty<'tcx>>]) {
|
||||||
let tuple = self.trans_operand(bx, operand);
|
let tuple = self.codegen_operand(bx, operand);
|
||||||
|
|
||||||
// Handle both by-ref and immediate tuples.
|
// Handle both by-ref and immediate tuples.
|
||||||
if let Ref(llval, align) = tuple.val {
|
if let Ref(llval, align) = tuple.val {
|
||||||
let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align);
|
let tuple_ptr = PlaceRef::new_sized(llval, tuple.layout, align);
|
||||||
for i in 0..tuple.layout.fields.count() {
|
for i in 0..tuple.layout.fields.count() {
|
||||||
let field_ptr = tuple_ptr.project_field(bx, i);
|
let field_ptr = tuple_ptr.project_field(bx, i);
|
||||||
self.trans_argument(bx, field_ptr.load(bx), llargs, &args[i]);
|
self.codegen_argument(bx, field_ptr.load(bx), llargs, &args[i]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the tuple is immediate, the elements are as well.
|
// If the tuple is immediate, the elements are as well.
|
||||||
for i in 0..tuple.layout.fields.count() {
|
for i in 0..tuple.layout.fields.count() {
|
||||||
let op = tuple.extract_field(bx, i);
|
let op = tuple.extract_field(bx, i);
|
||||||
self.trans_argument(bx, op, llargs, &args[i]);
|
self.codegen_argument(bx, op, llargs, &args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -792,7 +792,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.trans_place(bx, dest)
|
self.codegen_place(bx, dest)
|
||||||
};
|
};
|
||||||
if fn_ret.is_indirect() {
|
if fn_ret.is_indirect() {
|
||||||
if dest.align.abi() < dest.layout.align.abi() {
|
if dest.align.abi() < dest.layout.align.abi() {
|
||||||
|
@ -811,18 +811,18 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_transmute(&mut self, bx: &Builder<'a, 'tcx>,
|
fn codegen_transmute(&mut self, bx: &Builder<'a, 'tcx>,
|
||||||
src: &mir::Operand<'tcx>,
|
src: &mir::Operand<'tcx>,
|
||||||
dst: &mir::Place<'tcx>) {
|
dst: &mir::Place<'tcx>) {
|
||||||
if let mir::Place::Local(index) = *dst {
|
if let mir::Place::Local(index) = *dst {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(place) => self.trans_transmute_into(bx, src, place),
|
LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
|
||||||
LocalRef::Operand(None) => {
|
LocalRef::Operand(None) => {
|
||||||
let dst_layout = bx.cx.layout_of(self.monomorphized_place_ty(dst));
|
let dst_layout = bx.cx.layout_of(self.monomorphized_place_ty(dst));
|
||||||
assert!(!dst_layout.ty.has_erasable_regions());
|
assert!(!dst_layout.ty.has_erasable_regions());
|
||||||
let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
|
let place = PlaceRef::alloca(bx, dst_layout, "transmute_temp");
|
||||||
place.storage_live(bx);
|
place.storage_live(bx);
|
||||||
self.trans_transmute_into(bx, src, place);
|
self.codegen_transmute_into(bx, src, place);
|
||||||
let op = place.load(bx);
|
let op = place.load(bx);
|
||||||
place.storage_dead(bx);
|
place.storage_dead(bx);
|
||||||
self.locals[index] = LocalRef::Operand(Some(op));
|
self.locals[index] = LocalRef::Operand(Some(op));
|
||||||
|
@ -833,15 +833,15 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let dst = self.trans_place(bx, dst);
|
let dst = self.codegen_place(bx, dst);
|
||||||
self.trans_transmute_into(bx, src, dst);
|
self.codegen_transmute_into(bx, src, dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_transmute_into(&mut self, bx: &Builder<'a, 'tcx>,
|
fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'tcx>,
|
||||||
src: &mir::Operand<'tcx>,
|
src: &mir::Operand<'tcx>,
|
||||||
dst: PlaceRef<'tcx>) {
|
dst: PlaceRef<'tcx>) {
|
||||||
let src = self.trans_operand(bx, src);
|
let src = self.codegen_operand(bx, src);
|
||||||
let llty = src.layout.llvm_type(bx.cx);
|
let llty = src.layout.llvm_type(bx.cx);
|
||||||
let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to());
|
let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to());
|
||||||
let align = src.layout.align.min(dst.layout.align);
|
let align = src.layout.align.min(dst.layout.align);
|
|
@ -158,7 +158,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
|
||||||
C_struct(cx, &llvals, true)
|
C_struct(cx, &llvals, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_static_initializer<'a, 'tcx>(
|
pub fn codegen_static_initializer<'a, 'tcx>(
|
||||||
cx: &CodegenCx<'a, 'tcx>,
|
cx: &CodegenCx<'a, 'tcx>,
|
||||||
def_id: DefId)
|
def_id: DefId)
|
||||||
-> Result<ValueRef, ConstEvalErr<'tcx>>
|
-> Result<ValueRef, ConstEvalErr<'tcx>>
|
|
@ -33,7 +33,7 @@ use std::iter;
|
||||||
use rustc_data_structures::bitvec::BitVector;
|
use rustc_data_structures::bitvec::BitVector;
|
||||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||||
|
|
||||||
pub use self::constant::trans_static_initializer;
|
pub use self::constant::codegen_static_initializer;
|
||||||
|
|
||||||
use self::analyze::CleanupKind;
|
use self::analyze::CleanupKind;
|
||||||
use self::place::PlaceRef;
|
use self::place::PlaceRef;
|
||||||
|
@ -41,7 +41,7 @@ use rustc::mir::traversal;
|
||||||
|
|
||||||
use self::operand::{OperandRef, OperandValue};
|
use self::operand::{OperandRef, OperandValue};
|
||||||
|
|
||||||
/// Master context for translating MIR.
|
/// Master context for codegenning from MIR.
|
||||||
pub struct FunctionCx<'a, 'tcx:'a> {
|
pub struct FunctionCx<'a, 'tcx:'a> {
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ impl<'a, 'tcx> LocalRef<'tcx> {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub fn trans_mir<'a, 'tcx: 'a>(
|
pub fn codegen_mir<'a, 'tcx: 'a>(
|
||||||
cx: &'a CodegenCx<'a, 'tcx>,
|
cx: &'a CodegenCx<'a, 'tcx>,
|
||||||
llfn: ValueRef,
|
llfn: ValueRef,
|
||||||
mir: &'a Mir<'tcx>,
|
mir: &'a Mir<'tcx>,
|
||||||
|
@ -321,10 +321,10 @@ pub fn trans_mir<'a, 'tcx: 'a>(
|
||||||
let rpo = traversal::reverse_postorder(&mir);
|
let rpo = traversal::reverse_postorder(&mir);
|
||||||
let mut visited = BitVector::new(mir.basic_blocks().len());
|
let mut visited = BitVector::new(mir.basic_blocks().len());
|
||||||
|
|
||||||
// Translate the body of each block using reverse postorder
|
// Codegen the body of each block using reverse postorder
|
||||||
for (bb, _) in rpo {
|
for (bb, _) in rpo {
|
||||||
visited.insert(bb.index());
|
visited.insert(bb.index());
|
||||||
fx.trans_block(bb);
|
fx.codegen_block(bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove blocks that haven't been visited, or have no
|
// Remove blocks that haven't been visited, or have no
|
||||||
|
@ -332,7 +332,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
|
||||||
for bb in mir.basic_blocks().indices() {
|
for bb in mir.basic_blocks().indices() {
|
||||||
// Unreachable block
|
// Unreachable block
|
||||||
if !visited.contains(bb.index()) {
|
if !visited.contains(bb.index()) {
|
||||||
debug!("trans_mir: block {:?} was not visited", bb);
|
debug!("codegen_mir: block {:?} was not visited", bb);
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMDeleteBasicBlock(fx.blocks[bb]);
|
llvm::LLVMDeleteBasicBlock(fx.blocks[bb]);
|
||||||
}
|
}
|
|
@ -315,12 +315,12 @@ impl<'a, 'tcx> OperandValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
fn maybe_trans_consume_direct(&mut self,
|
fn maybe_codegen_consume_direct(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
place: &mir::Place<'tcx>)
|
place: &mir::Place<'tcx>)
|
||||||
-> Option<OperandRef<'tcx>>
|
-> Option<OperandRef<'tcx>>
|
||||||
{
|
{
|
||||||
debug!("maybe_trans_consume_direct(place={:?})", place);
|
debug!("maybe_codegen_consume_direct(place={:?})", place);
|
||||||
|
|
||||||
// watch out for locals that do not have an
|
// watch out for locals that do not have an
|
||||||
// alloca; they are handled somewhat differently
|
// alloca; they are handled somewhat differently
|
||||||
|
@ -340,7 +340,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
|
|
||||||
// Moves out of scalar and scalar pair fields are trivial.
|
// Moves out of scalar and scalar pair fields are trivial.
|
||||||
if let &mir::Place::Projection(ref proj) = place {
|
if let &mir::Place::Projection(ref proj) = place {
|
||||||
if let Some(o) = self.maybe_trans_consume_direct(bx, &proj.base) {
|
if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
mir::ProjectionElem::Field(ref f, _) => {
|
mir::ProjectionElem::Field(ref f, _) => {
|
||||||
return Some(o.extract_field(bx, f.index()));
|
return Some(o.extract_field(bx, f.index()));
|
||||||
|
@ -349,7 +349,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
mir::ProjectionElem::ConstantIndex { .. } => {
|
mir::ProjectionElem::ConstantIndex { .. } => {
|
||||||
// ZSTs don't require any actual memory access.
|
// ZSTs don't require any actual memory access.
|
||||||
// FIXME(eddyb) deduplicate this with the identical
|
// FIXME(eddyb) deduplicate this with the identical
|
||||||
// checks in `trans_consume` and `extract_field`.
|
// checks in `codegen_consume` and `extract_field`.
|
||||||
let elem = o.layout.field(bx.cx, 0);
|
let elem = o.layout.field(bx.cx, 0);
|
||||||
if elem.is_zst() {
|
if elem.is_zst() {
|
||||||
return Some(OperandRef::new_zst(bx.cx, elem));
|
return Some(OperandRef::new_zst(bx.cx, elem));
|
||||||
|
@ -363,12 +363,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_consume(&mut self,
|
pub fn codegen_consume(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
place: &mir::Place<'tcx>)
|
place: &mir::Place<'tcx>)
|
||||||
-> OperandRef<'tcx>
|
-> OperandRef<'tcx>
|
||||||
{
|
{
|
||||||
debug!("trans_consume(place={:?})", place);
|
debug!("codegen_consume(place={:?})", place);
|
||||||
|
|
||||||
let ty = self.monomorphized_place_ty(place);
|
let ty = self.monomorphized_place_ty(place);
|
||||||
let layout = bx.cx.layout_of(ty);
|
let layout = bx.cx.layout_of(ty);
|
||||||
|
@ -378,26 +378,26 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
return OperandRef::new_zst(bx.cx, layout);
|
return OperandRef::new_zst(bx.cx, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(o) = self.maybe_trans_consume_direct(bx, place) {
|
if let Some(o) = self.maybe_codegen_consume_direct(bx, place) {
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for most places, to consume them we just load them
|
// for most places, to consume them we just load them
|
||||||
// out from their home
|
// out from their home
|
||||||
self.trans_place(bx, place).load(bx)
|
self.codegen_place(bx, place).load(bx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_operand(&mut self,
|
pub fn codegen_operand(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
operand: &mir::Operand<'tcx>)
|
operand: &mir::Operand<'tcx>)
|
||||||
-> OperandRef<'tcx>
|
-> OperandRef<'tcx>
|
||||||
{
|
{
|
||||||
debug!("trans_operand(operand={:?})", operand);
|
debug!("codegen_operand(operand={:?})", operand);
|
||||||
|
|
||||||
match *operand {
|
match *operand {
|
||||||
mir::Operand::Copy(ref place) |
|
mir::Operand::Copy(ref place) |
|
||||||
mir::Operand::Move(ref place) => {
|
mir::Operand::Move(ref place) => {
|
||||||
self.trans_consume(bx, place)
|
self.codegen_consume(bx, place)
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Operand::Constant(ref constant) => {
|
mir::Operand::Constant(ref constant) => {
|
|
@ -253,7 +253,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the actual discriminant of a value.
|
/// Obtain the actual discriminant of a value.
|
||||||
pub fn trans_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
|
pub fn codegen_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
|
||||||
let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
|
let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
|
||||||
if self.layout.abi == layout::Abi::Uninhabited {
|
if self.layout.abi == layout::Abi::Uninhabited {
|
||||||
return C_undef(cast_to);
|
return C_undef(cast_to);
|
||||||
|
@ -313,7 +313,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
|
||||||
|
|
||||||
/// Set the discriminant for a new value of the given case of the given
|
/// Set the discriminant for a new value of the given case of the given
|
||||||
/// representation.
|
/// representation.
|
||||||
pub fn trans_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) {
|
pub fn codegen_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) {
|
||||||
if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited {
|
if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -399,11 +399,11 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
pub fn trans_place(&mut self,
|
pub fn codegen_place(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
place: &mir::Place<'tcx>)
|
place: &mir::Place<'tcx>)
|
||||||
-> PlaceRef<'tcx> {
|
-> PlaceRef<'tcx> {
|
||||||
debug!("trans_place(place={:?})", place);
|
debug!("codegen_place(place={:?})", place);
|
||||||
|
|
||||||
let cx = bx.cx;
|
let cx = bx.cx;
|
||||||
let tcx = cx.tcx;
|
let tcx = cx.tcx;
|
||||||
|
@ -430,46 +430,46 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
elem: mir::ProjectionElem::Deref
|
elem: mir::ProjectionElem::Deref
|
||||||
}) => {
|
}) => {
|
||||||
// Load the pointer from its location.
|
// Load the pointer from its location.
|
||||||
self.trans_consume(bx, base).deref(bx.cx)
|
self.codegen_consume(bx, base).deref(bx.cx)
|
||||||
}
|
}
|
||||||
mir::Place::Projection(ref projection) => {
|
mir::Place::Projection(ref projection) => {
|
||||||
let tr_base = self.trans_place(bx, &projection.base);
|
let cg_base = self.codegen_place(bx, &projection.base);
|
||||||
|
|
||||||
match projection.elem {
|
match projection.elem {
|
||||||
mir::ProjectionElem::Deref => bug!(),
|
mir::ProjectionElem::Deref => bug!(),
|
||||||
mir::ProjectionElem::Field(ref field, _) => {
|
mir::ProjectionElem::Field(ref field, _) => {
|
||||||
tr_base.project_field(bx, field.index())
|
cg_base.project_field(bx, field.index())
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::Index(index) => {
|
mir::ProjectionElem::Index(index) => {
|
||||||
let index = &mir::Operand::Copy(mir::Place::Local(index));
|
let index = &mir::Operand::Copy(mir::Place::Local(index));
|
||||||
let index = self.trans_operand(bx, index);
|
let index = self.codegen_operand(bx, index);
|
||||||
let llindex = index.immediate();
|
let llindex = index.immediate();
|
||||||
tr_base.project_index(bx, llindex)
|
cg_base.project_index(bx, llindex)
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::ConstantIndex { offset,
|
mir::ProjectionElem::ConstantIndex { offset,
|
||||||
from_end: false,
|
from_end: false,
|
||||||
min_length: _ } => {
|
min_length: _ } => {
|
||||||
let lloffset = C_usize(bx.cx, offset as u64);
|
let lloffset = C_usize(bx.cx, offset as u64);
|
||||||
tr_base.project_index(bx, lloffset)
|
cg_base.project_index(bx, lloffset)
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::ConstantIndex { offset,
|
mir::ProjectionElem::ConstantIndex { offset,
|
||||||
from_end: true,
|
from_end: true,
|
||||||
min_length: _ } => {
|
min_length: _ } => {
|
||||||
let lloffset = C_usize(bx.cx, offset as u64);
|
let lloffset = C_usize(bx.cx, offset as u64);
|
||||||
let lllen = tr_base.len(bx.cx);
|
let lllen = cg_base.len(bx.cx);
|
||||||
let llindex = bx.sub(lllen, lloffset);
|
let llindex = bx.sub(lllen, lloffset);
|
||||||
tr_base.project_index(bx, llindex)
|
cg_base.project_index(bx, llindex)
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::Subslice { from, to } => {
|
mir::ProjectionElem::Subslice { from, to } => {
|
||||||
let mut subslice = tr_base.project_index(bx,
|
let mut subslice = cg_base.project_index(bx,
|
||||||
C_usize(bx.cx, from as u64));
|
C_usize(bx.cx, from as u64));
|
||||||
let projected_ty = PlaceTy::Ty { ty: tr_base.layout.ty }
|
let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty }
|
||||||
.projection_ty(tcx, &projection.elem).to_ty(bx.tcx());
|
.projection_ty(tcx, &projection.elem).to_ty(bx.tcx());
|
||||||
subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty));
|
subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty));
|
||||||
|
|
||||||
if subslice.layout.is_unsized() {
|
if subslice.layout.is_unsized() {
|
||||||
assert!(tr_base.has_extra());
|
assert!(cg_base.has_extra());
|
||||||
subslice.llextra = bx.sub(tr_base.llextra,
|
subslice.llextra = bx.sub(cg_base.llextra,
|
||||||
C_usize(bx.cx, (from as u64) + (to as u64)));
|
C_usize(bx.cx, (from as u64) + (to as u64)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,12 +481,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
subslice
|
subslice
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::Downcast(_, v) => {
|
mir::ProjectionElem::Downcast(_, v) => {
|
||||||
tr_base.project_downcast(bx, v)
|
cg_base.project_downcast(bx, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!("trans_place(place={:?}) => {:?}", place, result);
|
debug!("codegen_place(place={:?}) => {:?}", place, result);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,4 +496,3 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
self.monomorphize(&place_ty.to_ty(tcx))
|
self.monomorphize(&place_ty.to_ty(tcx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,21 +33,21 @@ use super::operand::{OperandRef, OperandValue};
|
||||||
use super::place::PlaceRef;
|
use super::place::PlaceRef;
|
||||||
|
|
||||||
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
pub fn trans_rvalue(&mut self,
|
pub fn codegen_rvalue(&mut self,
|
||||||
bx: Builder<'a, 'tcx>,
|
bx: Builder<'a, 'tcx>,
|
||||||
dest: PlaceRef<'tcx>,
|
dest: PlaceRef<'tcx>,
|
||||||
rvalue: &mir::Rvalue<'tcx>)
|
rvalue: &mir::Rvalue<'tcx>)
|
||||||
-> Builder<'a, 'tcx>
|
-> Builder<'a, 'tcx>
|
||||||
{
|
{
|
||||||
debug!("trans_rvalue(dest.llval={:?}, rvalue={:?})",
|
debug!("codegen_rvalue(dest.llval={:?}, rvalue={:?})",
|
||||||
Value(dest.llval), rvalue);
|
Value(dest.llval), rvalue);
|
||||||
|
|
||||||
match *rvalue {
|
match *rvalue {
|
||||||
mir::Rvalue::Use(ref operand) => {
|
mir::Rvalue::Use(ref operand) => {
|
||||||
let tr_operand = self.trans_operand(&bx, operand);
|
let cg_operand = self.codegen_operand(&bx, operand);
|
||||||
// FIXME: consider not copying constants through stack. (fixable by translating
|
// FIXME: consider not copying constants through stack. (fixable by codegenning
|
||||||
// constants into OperandValue::Ref, why don’t we do that yet if we don’t?)
|
// constants into OperandValue::Ref, why don’t we do that yet if we don’t?)
|
||||||
tr_operand.val.store(&bx, dest);
|
cg_operand.val.store(&bx, dest);
|
||||||
bx
|
bx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,16 +57,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
if dest.layout.is_llvm_scalar_pair() {
|
if dest.layout.is_llvm_scalar_pair() {
|
||||||
// into-coerce of a thin pointer to a fat pointer - just
|
// into-coerce of a thin pointer to a fat pointer - just
|
||||||
// use the operand path.
|
// use the operand path.
|
||||||
let (bx, temp) = self.trans_rvalue_operand(bx, rvalue);
|
let (bx, temp) = self.codegen_rvalue_operand(bx, rvalue);
|
||||||
temp.val.store(&bx, dest);
|
temp.val.store(&bx, dest);
|
||||||
return bx;
|
return bx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsize of a nontrivial struct. I would prefer for
|
// Unsize of a nontrivial struct. I would prefer for
|
||||||
// this to be eliminated by MIR translation, but
|
// this to be eliminated by MIR building, but
|
||||||
// `CoerceUnsized` can be passed by a where-clause,
|
// `CoerceUnsized` can be passed by a where-clause,
|
||||||
// so the (generic) MIR may not be able to expand it.
|
// so the (generic) MIR may not be able to expand it.
|
||||||
let operand = self.trans_operand(&bx, source);
|
let operand = self.codegen_operand(&bx, source);
|
||||||
match operand.val {
|
match operand.val {
|
||||||
OperandValue::Pair(..) |
|
OperandValue::Pair(..) |
|
||||||
OperandValue::Immediate(_) => {
|
OperandValue::Immediate(_) => {
|
||||||
|
@ -76,7 +76,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
// `coerce_unsized_into` use extractvalue to
|
// `coerce_unsized_into` use extractvalue to
|
||||||
// index into the struct, and this case isn't
|
// index into the struct, and this case isn't
|
||||||
// important enough for it.
|
// important enough for it.
|
||||||
debug!("trans_rvalue: creating ugly alloca");
|
debug!("codegen_rvalue: creating ugly alloca");
|
||||||
let scratch = PlaceRef::alloca(&bx, operand.layout, "__unsize_temp");
|
let scratch = PlaceRef::alloca(&bx, operand.layout, "__unsize_temp");
|
||||||
scratch.storage_live(&bx);
|
scratch.storage_live(&bx);
|
||||||
operand.val.store(&bx, scratch);
|
operand.val.store(&bx, scratch);
|
||||||
|
@ -92,7 +92,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::Repeat(ref elem, count) => {
|
mir::Rvalue::Repeat(ref elem, count) => {
|
||||||
let tr_elem = self.trans_operand(&bx, elem);
|
let cg_elem = self.codegen_operand(&bx, elem);
|
||||||
|
|
||||||
// Do not generate the loop for zero-sized elements or empty arrays.
|
// Do not generate the loop for zero-sized elements or empty arrays.
|
||||||
if dest.layout.is_zst() {
|
if dest.layout.is_zst() {
|
||||||
|
@ -101,7 +101,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
|
|
||||||
let start = dest.project_index(&bx, C_usize(bx.cx, 0)).llval;
|
let start = dest.project_index(&bx, C_usize(bx.cx, 0)).llval;
|
||||||
|
|
||||||
if let OperandValue::Immediate(v) = tr_elem.val {
|
if let OperandValue::Immediate(v) = cg_elem.val {
|
||||||
let align = C_i32(bx.cx, dest.align.abi() as i32);
|
let align = C_i32(bx.cx, dest.align.abi() as i32);
|
||||||
let size = C_usize(bx.cx, dest.layout.size.bytes());
|
let size = C_usize(bx.cx, dest.layout.size.bytes());
|
||||||
|
|
||||||
|
@ -133,8 +133,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
let keep_going = header_bx.icmp(llvm::IntNE, current, end);
|
let keep_going = header_bx.icmp(llvm::IntNE, current, end);
|
||||||
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
|
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
|
||||||
|
|
||||||
tr_elem.val.store(&body_bx,
|
cg_elem.val.store(&body_bx,
|
||||||
PlaceRef::new_sized(current, tr_elem.layout, dest.align));
|
PlaceRef::new_sized(current, cg_elem.layout, dest.align));
|
||||||
|
|
||||||
let next = body_bx.inbounds_gep(current, &[C_usize(bx.cx, 1)]);
|
let next = body_bx.inbounds_gep(current, &[C_usize(bx.cx, 1)]);
|
||||||
body_bx.br(header_bx.llbb());
|
body_bx.br(header_bx.llbb());
|
||||||
|
@ -146,7 +146,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
mir::Rvalue::Aggregate(ref kind, ref operands) => {
|
mir::Rvalue::Aggregate(ref kind, ref operands) => {
|
||||||
let (dest, active_field_index) = match **kind {
|
let (dest, active_field_index) = match **kind {
|
||||||
mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
|
mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
|
||||||
dest.trans_set_discr(&bx, variant_index);
|
dest.codegen_set_discr(&bx, variant_index);
|
||||||
if adt_def.is_enum() {
|
if adt_def.is_enum() {
|
||||||
(dest.project_downcast(&bx, variant_index), active_field_index)
|
(dest.project_downcast(&bx, variant_index), active_field_index)
|
||||||
} else {
|
} else {
|
||||||
|
@ -156,7 +156,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
_ => (dest, None)
|
_ => (dest, None)
|
||||||
};
|
};
|
||||||
for (i, operand) in operands.iter().enumerate() {
|
for (i, operand) in operands.iter().enumerate() {
|
||||||
let op = self.trans_operand(&bx, operand);
|
let op = self.codegen_operand(&bx, operand);
|
||||||
// Do not generate stores and GEPis for zero-sized fields.
|
// Do not generate stores and GEPis for zero-sized fields.
|
||||||
if !op.layout.is_zst() {
|
if !op.layout.is_zst() {
|
||||||
let field_index = active_field_index.unwrap_or(i);
|
let field_index = active_field_index.unwrap_or(i);
|
||||||
|
@ -168,23 +168,23 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
assert!(self.rvalue_creates_operand(rvalue));
|
assert!(self.rvalue_creates_operand(rvalue));
|
||||||
let (bx, temp) = self.trans_rvalue_operand(bx, rvalue);
|
let (bx, temp) = self.codegen_rvalue_operand(bx, rvalue);
|
||||||
temp.val.store(&bx, dest);
|
temp.val.store(&bx, dest);
|
||||||
bx
|
bx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_rvalue_operand(&mut self,
|
pub fn codegen_rvalue_operand(&mut self,
|
||||||
bx: Builder<'a, 'tcx>,
|
bx: Builder<'a, 'tcx>,
|
||||||
rvalue: &mir::Rvalue<'tcx>)
|
rvalue: &mir::Rvalue<'tcx>)
|
||||||
-> (Builder<'a, 'tcx>, OperandRef<'tcx>)
|
-> (Builder<'a, 'tcx>, OperandRef<'tcx>)
|
||||||
{
|
{
|
||||||
assert!(self.rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
|
assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue);
|
||||||
|
|
||||||
match *rvalue {
|
match *rvalue {
|
||||||
mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => {
|
mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => {
|
||||||
let operand = self.trans_operand(&bx, source);
|
let operand = self.codegen_operand(&bx, source);
|
||||||
debug!("cast operand is {:?}", operand);
|
debug!("cast operand is {:?}", operand);
|
||||||
let cast = bx.cx.layout_of(self.monomorphize(&mir_cast_ty));
|
let cast = bx.cx.layout_of(self.monomorphize(&mir_cast_ty));
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
OperandValue::Pair(lldata, llextra)
|
OperandValue::Pair(lldata, llextra)
|
||||||
}
|
}
|
||||||
OperandValue::Ref(..) => {
|
OperandValue::Ref(..) => {
|
||||||
bug!("by-ref operand {:?} in trans_rvalue_operand",
|
bug!("by-ref operand {:?} in codegen_rvalue_operand",
|
||||||
operand);
|
operand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,16 +358,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::Ref(_, bk, ref place) => {
|
mir::Rvalue::Ref(_, bk, ref place) => {
|
||||||
let tr_place = self.trans_place(&bx, place);
|
let cg_place = self.codegen_place(&bx, place);
|
||||||
|
|
||||||
let ty = tr_place.layout.ty;
|
let ty = cg_place.layout.ty;
|
||||||
|
|
||||||
// Note: places are indirect, so storing the `llval` into the
|
// Note: places are indirect, so storing the `llval` into the
|
||||||
// destination effectively creates a reference.
|
// destination effectively creates a reference.
|
||||||
let val = if !bx.cx.type_has_metadata(ty) {
|
let val = if !bx.cx.type_has_metadata(ty) {
|
||||||
OperandValue::Immediate(tr_place.llval)
|
OperandValue::Immediate(cg_place.llval)
|
||||||
} else {
|
} else {
|
||||||
OperandValue::Pair(tr_place.llval, tr_place.llextra)
|
OperandValue::Pair(cg_place.llval, cg_place.llextra)
|
||||||
};
|
};
|
||||||
(bx, OperandRef {
|
(bx, OperandRef {
|
||||||
val,
|
val,
|
||||||
|
@ -388,12 +388,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
|
mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
|
||||||
let lhs = self.trans_operand(&bx, lhs);
|
let lhs = self.codegen_operand(&bx, lhs);
|
||||||
let rhs = self.trans_operand(&bx, rhs);
|
let rhs = self.codegen_operand(&bx, rhs);
|
||||||
let llresult = match (lhs.val, rhs.val) {
|
let llresult = match (lhs.val, rhs.val) {
|
||||||
(OperandValue::Pair(lhs_addr, lhs_extra),
|
(OperandValue::Pair(lhs_addr, lhs_extra),
|
||||||
OperandValue::Pair(rhs_addr, rhs_extra)) => {
|
OperandValue::Pair(rhs_addr, rhs_extra)) => {
|
||||||
self.trans_fat_ptr_binop(&bx, op,
|
self.codegen_fat_ptr_binop(&bx, op,
|
||||||
lhs_addr, lhs_extra,
|
lhs_addr, lhs_extra,
|
||||||
rhs_addr, rhs_extra,
|
rhs_addr, rhs_extra,
|
||||||
lhs.layout.ty)
|
lhs.layout.ty)
|
||||||
|
@ -401,7 +401,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
|
|
||||||
(OperandValue::Immediate(lhs_val),
|
(OperandValue::Immediate(lhs_val),
|
||||||
OperandValue::Immediate(rhs_val)) => {
|
OperandValue::Immediate(rhs_val)) => {
|
||||||
self.trans_scalar_binop(&bx, op, lhs_val, rhs_val, lhs.layout.ty)
|
self.codegen_scalar_binop(&bx, op, lhs_val, rhs_val, lhs.layout.ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => bug!()
|
_ => bug!()
|
||||||
|
@ -414,9 +414,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
(bx, operand)
|
(bx, operand)
|
||||||
}
|
}
|
||||||
mir::Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
|
mir::Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
|
||||||
let lhs = self.trans_operand(&bx, lhs);
|
let lhs = self.codegen_operand(&bx, lhs);
|
||||||
let rhs = self.trans_operand(&bx, rhs);
|
let rhs = self.codegen_operand(&bx, rhs);
|
||||||
let result = self.trans_scalar_checked_binop(&bx, op,
|
let result = self.codegen_scalar_checked_binop(&bx, op,
|
||||||
lhs.immediate(), rhs.immediate(),
|
lhs.immediate(), rhs.immediate(),
|
||||||
lhs.layout.ty);
|
lhs.layout.ty);
|
||||||
let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
|
let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
|
||||||
|
@ -430,7 +430,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
mir::Rvalue::UnaryOp(op, ref operand) => {
|
mir::Rvalue::UnaryOp(op, ref operand) => {
|
||||||
let operand = self.trans_operand(&bx, operand);
|
let operand = self.codegen_operand(&bx, operand);
|
||||||
let lloperand = operand.immediate();
|
let lloperand = operand.immediate();
|
||||||
let is_float = operand.layout.ty.is_fp();
|
let is_float = operand.layout.ty.is_fp();
|
||||||
let llval = match op {
|
let llval = match op {
|
||||||
|
@ -449,8 +449,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
|
|
||||||
mir::Rvalue::Discriminant(ref place) => {
|
mir::Rvalue::Discriminant(ref place) => {
|
||||||
let discr_ty = rvalue.ty(&*self.mir, bx.tcx());
|
let discr_ty = rvalue.ty(&*self.mir, bx.tcx());
|
||||||
let discr = self.trans_place(&bx, place)
|
let discr = self.codegen_place(&bx, place)
|
||||||
.trans_get_discr(&bx, discr_ty);
|
.codegen_get_discr(&bx, discr_ty);
|
||||||
(bx, OperandRef {
|
(bx, OperandRef {
|
||||||
val: OperandValue::Immediate(discr),
|
val: OperandValue::Immediate(discr),
|
||||||
layout: self.cx.layout_of(discr_ty)
|
layout: self.cx.layout_of(discr_ty)
|
||||||
|
@ -493,7 +493,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
(bx, operand)
|
(bx, operand)
|
||||||
}
|
}
|
||||||
mir::Rvalue::Use(ref operand) => {
|
mir::Rvalue::Use(ref operand) => {
|
||||||
let operand = self.trans_operand(&bx, operand);
|
let operand = self.codegen_operand(&bx, operand);
|
||||||
(bx, operand)
|
(bx, operand)
|
||||||
}
|
}
|
||||||
mir::Rvalue::Repeat(..) |
|
mir::Rvalue::Repeat(..) |
|
||||||
|
@ -512,7 +512,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
place: &mir::Place<'tcx>) -> ValueRef
|
place: &mir::Place<'tcx>) -> ValueRef
|
||||||
{
|
{
|
||||||
// ZST are passed as operands and require special handling
|
// ZST are passed as operands and require special handling
|
||||||
// because trans_place() panics if Local is operand.
|
// because codegen_place() panics if Local is operand.
|
||||||
if let mir::Place::Local(index) = *place {
|
if let mir::Place::Local(index) = *place {
|
||||||
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
||||||
if let ty::TyArray(_, n) = op.layout.ty.sty {
|
if let ty::TyArray(_, n) = op.layout.ty.sty {
|
||||||
|
@ -522,11 +522,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// use common size calculation for non zero-sized types
|
// use common size calculation for non zero-sized types
|
||||||
let tr_value = self.trans_place(&bx, place);
|
let cg_value = self.codegen_place(&bx, place);
|
||||||
return tr_value.len(bx.cx);
|
return cg_value.len(bx.cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_scalar_binop(&mut self,
|
pub fn codegen_scalar_binop(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
op: mir::BinOp,
|
op: mir::BinOp,
|
||||||
lhs: ValueRef,
|
lhs: ValueRef,
|
||||||
|
@ -592,7 +592,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_fat_ptr_binop(&mut self,
|
pub fn codegen_fat_ptr_binop(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
op: mir::BinOp,
|
op: mir::BinOp,
|
||||||
lhs_addr: ValueRef,
|
lhs_addr: ValueRef,
|
||||||
|
@ -639,7 +639,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_scalar_checked_binop(&mut self,
|
pub fn codegen_scalar_checked_binop(&mut self,
|
||||||
bx: &Builder<'a, 'tcx>,
|
bx: &Builder<'a, 'tcx>,
|
||||||
op: mir::BinOp,
|
op: mir::BinOp,
|
||||||
lhs: ValueRef,
|
lhs: ValueRef,
|
||||||
|
@ -650,7 +650,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
// another crate (mostly core::num generic/#[inline] fns),
|
// another crate (mostly core::num generic/#[inline] fns),
|
||||||
// while the current crate doesn't use overflow checks.
|
// while the current crate doesn't use overflow checks.
|
||||||
if !bx.cx.check_overflow {
|
if !bx.cx.check_overflow {
|
||||||
let val = self.trans_scalar_binop(bx, op, lhs, rhs, input_ty);
|
let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty);
|
||||||
return OperandValue::Pair(val, C_bool(bx.cx, false));
|
return OperandValue::Pair(val, C_bool(bx.cx, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,7 +676,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
let outer_bits = bx.and(rhs, invert_mask);
|
let outer_bits = bx.and(rhs, invert_mask);
|
||||||
|
|
||||||
let of = bx.icmp(llvm::IntNE, outer_bits, C_null(rhs_llty));
|
let of = bx.icmp(llvm::IntNE, outer_bits, C_null(rhs_llty));
|
||||||
let val = self.trans_scalar_binop(bx, op, lhs, rhs, input_ty);
|
let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty);
|
||||||
|
|
||||||
(val, of)
|
(val, of)
|
||||||
}
|
}
|
|
@ -17,22 +17,22 @@ use super::FunctionCx;
|
||||||
use super::LocalRef;
|
use super::LocalRef;
|
||||||
|
|
||||||
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
pub fn trans_statement(&mut self,
|
pub fn codegen_statement(&mut self,
|
||||||
bx: Builder<'a, 'tcx>,
|
bx: Builder<'a, 'tcx>,
|
||||||
statement: &mir::Statement<'tcx>)
|
statement: &mir::Statement<'tcx>)
|
||||||
-> Builder<'a, 'tcx> {
|
-> Builder<'a, 'tcx> {
|
||||||
debug!("trans_statement(statement={:?})", statement);
|
debug!("codegen_statement(statement={:?})", statement);
|
||||||
|
|
||||||
self.set_debug_loc(&bx, statement.source_info);
|
self.set_debug_loc(&bx, statement.source_info);
|
||||||
match statement.kind {
|
match statement.kind {
|
||||||
mir::StatementKind::Assign(ref place, ref rvalue) => {
|
mir::StatementKind::Assign(ref place, ref rvalue) => {
|
||||||
if let mir::Place::Local(index) = *place {
|
if let mir::Place::Local(index) = *place {
|
||||||
match self.locals[index] {
|
match self.locals[index] {
|
||||||
LocalRef::Place(tr_dest) => {
|
LocalRef::Place(cg_dest) => {
|
||||||
self.trans_rvalue(bx, tr_dest, rvalue)
|
self.codegen_rvalue(bx, cg_dest, rvalue)
|
||||||
}
|
}
|
||||||
LocalRef::Operand(None) => {
|
LocalRef::Operand(None) => {
|
||||||
let (bx, operand) = self.trans_rvalue_operand(bx, rvalue);
|
let (bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
|
||||||
self.locals[index] = LocalRef::Operand(Some(operand));
|
self.locals[index] = LocalRef::Operand(Some(operand));
|
||||||
bx
|
bx
|
||||||
}
|
}
|
||||||
|
@ -44,42 +44,42 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the type is zero-sized, it's already been set here,
|
// If the type is zero-sized, it's already been set here,
|
||||||
// but we still need to make sure we translate the operand
|
// but we still need to make sure we codegen the operand
|
||||||
self.trans_rvalue_operand(bx, rvalue).0
|
self.codegen_rvalue_operand(bx, rvalue).0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let tr_dest = self.trans_place(&bx, place);
|
let cg_dest = self.codegen_place(&bx, place);
|
||||||
self.trans_rvalue(bx, tr_dest, rvalue)
|
self.codegen_rvalue(bx, cg_dest, rvalue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::StatementKind::SetDiscriminant{ref place, variant_index} => {
|
mir::StatementKind::SetDiscriminant{ref place, variant_index} => {
|
||||||
self.trans_place(&bx, place)
|
self.codegen_place(&bx, place)
|
||||||
.trans_set_discr(&bx, variant_index);
|
.codegen_set_discr(&bx, variant_index);
|
||||||
bx
|
bx
|
||||||
}
|
}
|
||||||
mir::StatementKind::StorageLive(local) => {
|
mir::StatementKind::StorageLive(local) => {
|
||||||
if let LocalRef::Place(tr_place) = self.locals[local] {
|
if let LocalRef::Place(cg_place) = self.locals[local] {
|
||||||
tr_place.storage_live(&bx);
|
cg_place.storage_live(&bx);
|
||||||
}
|
}
|
||||||
bx
|
bx
|
||||||
}
|
}
|
||||||
mir::StatementKind::StorageDead(local) => {
|
mir::StatementKind::StorageDead(local) => {
|
||||||
if let LocalRef::Place(tr_place) = self.locals[local] {
|
if let LocalRef::Place(cg_place) = self.locals[local] {
|
||||||
tr_place.storage_dead(&bx);
|
cg_place.storage_dead(&bx);
|
||||||
}
|
}
|
||||||
bx
|
bx
|
||||||
}
|
}
|
||||||
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||||
let outputs = outputs.iter().map(|output| {
|
let outputs = outputs.iter().map(|output| {
|
||||||
self.trans_place(&bx, output)
|
self.codegen_place(&bx, output)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
let input_vals = inputs.iter().map(|input| {
|
let input_vals = inputs.iter().map(|input| {
|
||||||
self.trans_operand(&bx, input).immediate()
|
self.codegen_operand(&bx, input).immediate()
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
asm::trans_inline_asm(&bx, asm, outputs, input_vals);
|
asm::codegen_inline_asm(&bx, asm, outputs, input_vals);
|
||||||
bx
|
bx
|
||||||
}
|
}
|
||||||
mir::StatementKind::EndRegion(_) |
|
mir::StatementKind::EndRegion(_) |
|
|
@ -58,18 +58,18 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
let attrs = tcx.get_attrs(def_id);
|
let attrs = tcx.get_attrs(def_id);
|
||||||
|
|
||||||
consts::trans_static(&cx, def_id, is_mutable, &attrs);
|
consts::codegen_static(&cx, def_id, is_mutable, &attrs);
|
||||||
}
|
}
|
||||||
MonoItem::GlobalAsm(node_id) => {
|
MonoItem::GlobalAsm(node_id) => {
|
||||||
let item = cx.tcx.hir.expect_item(node_id);
|
let item = cx.tcx.hir.expect_item(node_id);
|
||||||
if let hir::ItemGlobalAsm(ref ga) = item.node {
|
if let hir::ItemGlobalAsm(ref ga) = item.node {
|
||||||
asm::trans_global_asm(cx, ga);
|
asm::codegen_global_asm(cx, ga);
|
||||||
} else {
|
} else {
|
||||||
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
|
span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MonoItem::Fn(instance) => {
|
MonoItem::Fn(instance) => {
|
||||||
base::trans_instance(&cx, instance);
|
base::codegen_instance(&cx, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue