rust/src/librustc_codegen_llvm/lib.rs

430 lines
13 KiB
Rust
Raw Normal View History

//! The Rust compiler.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
2015-09-27 20:20:49 +00:00
#![feature(custom_attribute)]
#![feature(extern_types)]
#![feature(in_band_lifetimes)]
2015-09-27 20:20:49 +00:00
#![allow(unused_attributes)]
#![feature(libc)]
#![feature(nll)]
#![feature(rustc_diagnostic_macros)]
#![feature(optin_builtin_traits)]
#![feature(concat_idents)]
#![feature(link_args)]
#![feature(static_nobundle)]
#![feature(trusted_len)]
2019-02-17 18:58:58 +00:00
#![deny(rust_2018_idioms)]
#![allow(explicit_outlives_requirements)]
use back::write::{create_target_machine, create_informational_target_machine};
use syntax_pos::symbol::Symbol;
extern crate flate2;
#[macro_use] extern crate bitflags;
extern crate libc;
#[macro_use] extern crate rustc;
2017-10-25 13:39:54 +00:00
extern crate rustc_mir;
extern crate rustc_allocator;
extern crate rustc_target;
2018-03-03 05:17:06 +00:00
#[macro_use] extern crate rustc_data_structures;
extern crate rustc_incremental;
2018-05-08 13:10:16 +00:00
extern crate rustc_codegen_utils;
extern crate rustc_codegen_ssa;
extern crate rustc_fs_util;
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
extern crate syntax_pos;
extern crate rustc_errors as errors;
extern crate serialize;
extern crate tempfile;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, FatLTOInput};
use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModule};
use rustc_codegen_ssa::CompiledModule;
use errors::{FatalError, Handler};
use rustc::dep_graph::WorkProduct;
2018-09-27 13:31:20 +00:00
use syntax_pos::symbol::InternedString;
use rustc::mir::mono::Stats;
pub use llvm_util::target_features;
rustc: Enable LTO and multiple codegen units This commit is a refactoring of the LTO backend in Rust to support compilations with multiple codegen units. The immediate result of this PR is to remove the artificial error emitted by rustc about `-C lto -C codegen-units-8`, but longer term this is intended to lay the groundwork for LTO with incremental compilation and ultimately be the underpinning of ThinLTO support. The problem here that needed solving is that when rustc is producing multiple codegen units in one compilation LTO needs to merge them all together. Previously only upstream dependencies were merged and it was inherently relied on that there was only one local codegen unit. Supporting this involved refactoring the optimization backend architecture for rustc, namely splitting the `optimize_and_codegen` function into `optimize` and `codegen`. After an LLVM module has been optimized it may be blocked and queued up for LTO, and only after LTO are modules code generated. Non-LTO compilations should look the same as they do today backend-wise, we'll spin up a thread for each codegen unit and optimize/codegen in that thread. LTO compilations will, however, send the LLVM module back to the coordinator thread once optimizations have finished. When all LLVM modules have finished optimizing the coordinator will invoke the LTO backend, producing a further list of LLVM modules. Currently this is always a list of one LLVM module. The coordinator then spawns further work to run LTO and code generation passes over each module. In the course of this refactoring a number of other pieces were refactored: * Management of the bytecode encoding in rlibs was centralized into one module instead of being scattered across LTO and linking. * Some internal refactorings on the link stage of the compiler was done to work directly from `CompiledModule` structures instead of lists of paths. * The trans time-graph output was tweaked a little to include a name on each bar and inflate the size of the bars a little
2017-07-23 15:14:38 +00:00
use std::any::Any;
use std::sync::{mpsc, Arc};
rustc: Enable LTO and multiple codegen units This commit is a refactoring of the LTO backend in Rust to support compilations with multiple codegen units. The immediate result of this PR is to remove the artificial error emitted by rustc about `-C lto -C codegen-units-8`, but longer term this is intended to lay the groundwork for LTO with incremental compilation and ultimately be the underpinning of ThinLTO support. The problem here that needed solving is that when rustc is producing multiple codegen units in one compilation LTO needs to merge them all together. Previously only upstream dependencies were merged and it was inherently relied on that there was only one local codegen unit. Supporting this involved refactoring the optimization backend architecture for rustc, namely splitting the `optimize_and_codegen` function into `optimize` and `codegen`. After an LLVM module has been optimized it may be blocked and queued up for LTO, and only after LTO are modules code generated. Non-LTO compilations should look the same as they do today backend-wise, we'll spin up a thread for each codegen unit and optimize/codegen in that thread. LTO compilations will, however, send the LLVM module back to the coordinator thread once optimizations have finished. When all LLVM modules have finished optimizing the coordinator will invoke the LTO backend, producing a further list of LLVM modules. Currently this is always a list of one LLVM module. The coordinator then spawns further work to run LTO and code generation passes over each module. In the course of this refactoring a number of other pieces were refactored: * Management of the bytecode encoding in rlibs was centralized into one module instead of being scattered across LTO and linking. * Some internal refactorings on the link stage of the compiler was done to work directly from `CompiledModule` structures instead of lists of paths. * The trans time-graph output was tweaked a little to include a name on each bar and inflate the size of the bars a little
2017-07-23 15:14:38 +00:00
use rustc::dep_graph::DepGraph;
2018-09-25 15:52:03 +00:00
use rustc::middle::allocator::AllocatorKind;
use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc::session::Session;
use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
rustc: Enable LTO and multiple codegen units This commit is a refactoring of the LTO backend in Rust to support compilations with multiple codegen units. The immediate result of this PR is to remove the artificial error emitted by rustc about `-C lto -C codegen-units-8`, but longer term this is intended to lay the groundwork for LTO with incremental compilation and ultimately be the underpinning of ThinLTO support. The problem here that needed solving is that when rustc is producing multiple codegen units in one compilation LTO needs to merge them all together. Previously only upstream dependencies were merged and it was inherently relied on that there was only one local codegen unit. Supporting this involved refactoring the optimization backend architecture for rustc, namely splitting the `optimize_and_codegen` function into `optimize` and `codegen`. After an LLVM module has been optimized it may be blocked and queued up for LTO, and only after LTO are modules code generated. Non-LTO compilations should look the same as they do today backend-wise, we'll spin up a thread for each codegen unit and optimize/codegen in that thread. LTO compilations will, however, send the LLVM module back to the coordinator thread once optimizations have finished. When all LLVM modules have finished optimizing the coordinator will invoke the LTO backend, producing a further list of LLVM modules. Currently this is always a list of one LLVM module. The coordinator then spawns further work to run LTO and code generation passes over each module. In the course of this refactoring a number of other pieces were refactored: * Management of the bytecode encoding in rlibs was centralized into one module instead of being scattered across LTO and linking. * Some internal refactorings on the link stage of the compiler was done to work directly from `CompiledModule` structures instead of lists of paths. * The trans time-graph output was tweaked a little to include a name on each bar and inflate the size of the bars a little
2017-07-23 15:14:38 +00:00
use rustc::ty::{self, TyCtxt};
2018-05-19 17:50:58 +00:00
use rustc::util::profiling::ProfileCategory;
use rustc::util::common::ErrorReported;
use rustc_mir::monomorphize;
use rustc_codegen_ssa::ModuleCodegen;
2018-05-08 13:10:16 +00:00
use rustc_codegen_utils::codegen_backend::CodegenBackend;
2017-10-19 09:01:31 +00:00
mod diagnostics;
2017-12-27 18:03:48 +00:00
mod back {
mod archive;
pub mod bytecode;
pub mod link;
pub mod lto;
pub mod write;
2017-08-19 00:09:55 +00:00
mod rpath;
Upgrade to LLVM's master branch (LLVM 7) This commit upgrades the main LLVM submodule to LLVM's current master branch. The LLD submodule is updated in tandem as well as compiler-builtins. Along the way support was also added for LLVM 7's new features. This primarily includes the support for custom section concatenation natively in LLD so we now add wasm custom sections in LLVM IR rather than having custom support in rustc itself for doing so. Some other miscellaneous changes are: * We now pass `--gc-sections` to `wasm-ld` * The optimization level is now passed to `wasm-ld` * A `--stack-first` option is passed to LLD to have stack overflow always cause a trap instead of corrupting static data * The wasm target for LLVM switched to `wasm32-unknown-unknown`. * The syntax for aligned pointers has changed in LLVM IR and tests are updated to reflect this. * The `thumbv6m-none-eabi` target is disabled due to an [LLVM bug][llbug] Nowadays we've been mostly only upgrading whenever there's a major release of LLVM but enough changes have been happening on the wasm target that there's been growing motivation for quite some time now to upgrade out version of LLD. To upgrade LLD, however, we need to upgrade LLVM to avoid needing to build yet another version of LLVM on the builders. The revision of LLVM in use here is arbitrarily chosen. We will likely need to continue to update it over time if and when we discover bugs. Once LLVM 7 is fully released we can switch to that channel as well. [llbug]: https://bugs.llvm.org/show_bug.cgi?id=37382
2018-06-01 17:20:00 +00:00
pub mod wasm;
}
mod abi;
mod allocator;
mod asm;
mod attributes;
mod base;
mod builder;
mod callee;
mod common;
mod consts;
mod context;
mod debuginfo;
mod declare;
mod intrinsic;
// The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
#[path = "llvm/mod.rs"] mod llvm_; pub mod llvm { pub use super::llvm_::*; }
mod llvm_util;
mod metadata;
2018-05-08 13:10:16 +00:00
mod mono_item;
mod type_;
mod type_of;
mod value;
mod va_arg;
#[derive(Clone)]
2018-05-08 13:10:16 +00:00
pub struct LlvmCodegenBackend(());
2017-09-16 15:27:29 +00:00
impl ExtraBackendMethods for LlvmCodegenBackend {
fn new_metadata(&self, tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> ModuleLlvm {
ModuleLlvm::new_metadata(tcx, mod_name)
2018-09-25 15:52:03 +00:00
}
fn write_metadata<'b, 'gcx>(
2018-09-25 15:52:03 +00:00
&self,
tcx: TyCtxt<'b, 'gcx, 'gcx>,
metadata: &mut ModuleLlvm
2018-09-25 15:52:03 +00:00
) -> EncodedMetadata {
base::write_metadata(tcx, metadata)
}
fn codegen_allocator<'b, 'gcx>(
&self,
tcx: TyCtxt<'b, 'gcx, 'gcx>,
mods: &mut ModuleLlvm,
kind: AllocatorKind
) {
unsafe { allocator::codegen(tcx, mods, kind) }
}
fn compile_codegen_unit<'a, 'tcx: 'a>(
2018-09-25 15:52:03 +00:00
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cgu_name: InternedString,
) -> Stats {
base::compile_codegen_unit(tcx, cgu_name)
2018-09-25 15:52:03 +00:00
}
fn target_machine_factory(
2018-09-25 15:52:03 +00:00
&self,
sess: &Session,
optlvl: OptLevel,
find_features: bool
) -> Arc<dyn Fn() ->
Result<&'static mut llvm::TargetMachine, String> + Send + Sync> {
back::write::target_machine_factory(sess, optlvl, find_features)
2018-09-25 15:52:03 +00:00
}
fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
llvm_util::target_cpu(sess)
}
}
impl WriteBackendMethods for LlvmCodegenBackend {
type Module = ModuleLlvm;
type ModuleBuffer = back::lto::ModuleBuffer;
type Context = llvm::Context;
type TargetMachine = &'static mut llvm::TargetMachine;
type ThinData = back::lto::ThinData;
type ThinBuffer = back::lto::ThinBuffer;
fn print_pass_timings(&self) {
unsafe { llvm::LLVMRustPrintPassTimings(); }
2018-09-25 15:52:03 +00:00
}
fn run_fat_lto(
cgcx: &CodegenContext<Self>,
modules: Vec<FatLTOInput<Self>>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<LtoModuleCodegen<Self>, FatalError> {
2019-02-13 13:13:30 +00:00
back::lto::run_fat(cgcx, modules, cached_modules)
}
fn run_thin_lto(
cgcx: &CodegenContext<Self>,
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
2019-02-13 13:13:30 +00:00
back::lto::run_thin(cgcx, modules, cached_modules)
2018-09-25 15:52:03 +00:00
}
unsafe fn optimize(
cgcx: &CodegenContext<Self>,
diag_handler: &Handler,
module: &ModuleCodegen<Self::Module>,
config: &ModuleConfig,
) -> Result<(), FatalError> {
2019-02-13 13:13:30 +00:00
back::write::optimize(cgcx, diag_handler, module, config)
2018-09-25 15:52:03 +00:00
}
unsafe fn optimize_thin(
cgcx: &CodegenContext<Self>,
thin: &mut ThinModule<Self>,
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
2019-02-13 13:13:30 +00:00
back::lto::optimize_thin_module(thin, cgcx)
2018-09-25 15:52:03 +00:00
}
unsafe fn codegen(
cgcx: &CodegenContext<Self>,
diag_handler: &Handler,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
) -> Result<CompiledModule, FatalError> {
2019-02-13 13:13:30 +00:00
back::write::codegen(cgcx, diag_handler, module, config)
2018-09-25 15:52:03 +00:00
}
fn prepare_thin(
module: ModuleCodegen<Self::Module>
) -> (String, Self::ThinBuffer) {
back::lto::prepare_thin(module)
}
fn serialize_module(
module: ModuleCodegen<Self::Module>
) -> (String, Self::ModuleBuffer) {
(module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod()))
}
fn run_lto_pass_manager(
cgcx: &CodegenContext<Self>,
module: &ModuleCodegen<Self::Module>,
config: &ModuleConfig,
thin: bool
) {
back::lto::run_pass_manager(cgcx, module, config, thin)
}
}
unsafe impl Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
unsafe impl Sync for LlvmCodegenBackend {}
2018-05-08 13:10:16 +00:00
impl LlvmCodegenBackend {
pub fn new() -> Box<dyn CodegenBackend> {
2018-05-08 13:10:16 +00:00
box LlvmCodegenBackend(())
2017-09-16 15:27:29 +00:00
}
}
impl CodegenBackend for LlvmCodegenBackend {
fn init(&self, sess: &Session) {
llvm_util::init(sess); // Make sure llvm is inited
}
fn print(&self, req: PrintRequest, sess: &Session) {
match req {
PrintRequest::RelocationModels => {
println!("Available relocation models:");
for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
println!(" {}", name);
}
println!("");
}
PrintRequest::CodeModels => {
println!("Available code models:");
for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
println!(" {}", name);
}
println!("");
}
PrintRequest::TlsModels => {
println!("Available TLS models:");
for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
println!(" {}", name);
}
println!("");
}
req => llvm_util::print(req, sess),
}
}
2017-09-16 15:27:29 +00:00
fn print_passes(&self) {
llvm_util::print_passes();
}
fn print_version(&self) {
llvm_util::print_version();
}
fn diagnostics(&self) -> &[(&'static str, &'static str)] {
&DIAGNOSTICS
}
fn target_features(&self, sess: &Session) -> Vec<Symbol> {
target_features(sess)
}
fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
2017-09-16 15:27:29 +00:00
box metadata::LlvmMetadataLoader
}
fn provide(&self, providers: &mut ty::query::Providers<'_>) {
2018-10-20 12:45:08 +00:00
rustc_codegen_utils::symbol_names::provide(providers);
rustc_codegen_ssa::back::symbol_export::provide(providers);
rustc_codegen_ssa::base::provide_both(providers);
attributes::provide(providers);
2017-09-23 12:46:15 +00:00
}
fn provide_extern(&self, providers: &mut ty::query::Providers<'_>) {
rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
rustc_codegen_ssa::base::provide_both(providers);
rustc: Add a `#[wasm_import_module]` attribute This commit adds a new attribute to the Rust compiler specific to the wasm target (and no other targets). The `#[wasm_import_module]` attribute is used to specify the module that a name is imported from, and is used like so: #[wasm_import_module = "./foo.js"] extern { fn some_js_function(); } Here the import of the symbol `some_js_function` is tagged with the `./foo.js` module in the wasm output file. Wasm-the-format includes two fields on all imports, a module and a field. The field is the symbol name (`some_js_function` above) and the module has historically unconditionally been `"env"`. I'm not sure if this `"env"` convention has asm.js or LLVM roots, but regardless we'd like the ability to configure it! The proposed ES module integration with wasm (aka a wasm module is "just another ES module") requires that the import module of wasm imports is interpreted as an ES module import, meaning that you'll need to encode paths, NPM packages, etc. As a result, we'll need this to be something other than `"env"`! Unfortunately neither our version of LLVM nor LLD supports custom import modules (aka anything not `"env"`). My hope is that by the time LLVM 7 is released both will have support, but in the meantime this commit adds some primitive encoding/decoding of wasm files to the compiler. This way rustc postprocesses the wasm module that LLVM emits to ensure it's got all the imports we'd like to have in it. Eventually I'd ideally like to unconditionally require this attribute to be placed on all `extern { ... }` blocks. For now though it seemed prudent to add it as an unstable attribute, so for now it's not required (as that'd force usage of a feature gate). Hopefully it doesn't take too long to "stabilize" this! cc rust-lang-nursery/rust-wasm#29
2018-02-10 22:28:17 +00:00
attributes::provide_extern(providers);
2017-09-16 15:27:29 +00:00
}
fn codegen_crate<'b, 'tcx>(
&self,
tcx: TyCtxt<'b, 'tcx, 'tcx>,
rx: mpsc::Receiver<Box<dyn Any + Send>>
) -> Box<dyn Any> {
box rustc_codegen_ssa::base::codegen_crate(LlvmCodegenBackend(()), tcx, rx)
2017-09-16 15:27:29 +00:00
}
2018-05-08 13:10:16 +00:00
fn join_codegen_and_link(
&self,
ongoing_codegen: Box<dyn Any>,
2017-09-16 15:27:29 +00:00
sess: &Session,
dep_graph: &DepGraph,
outputs: &OutputFilenames,
) -> Result<(), ErrorReported>{
use rustc::util::common::time;
let (codegen_results, work_products) =
ongoing_codegen.downcast::
<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>()
2018-05-08 13:10:16 +00:00
.expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
.join(sess);
if sess.opts.debugging_opts.incremental_info {
rustc_codegen_ssa::back::write::dump_incremental_data(&codegen_results);
}
2017-09-16 15:27:29 +00:00
2017-12-03 13:21:23 +00:00
time(sess,
"serialize work products",
2018-05-09 15:16:08 +00:00
move || rustc_incremental::save_work_product_index(sess, &dep_graph, work_products));
sess.compile_status()?;
if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
i == OutputType::Metadata) {
return Ok(());
}
// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
2019-02-13 13:13:30 +00:00
sess.profiler(|p| p.start_activity(ProfileCategory::Linking, "link_crate"));
2017-12-03 13:21:23 +00:00
time(sess, "linking", || {
back::link::link_binary(sess, &codegen_results,
outputs, &codegen_results.crate_name.as_str());
});
2019-02-13 13:13:30 +00:00
sess.profiler(|p| p.end_activity(ProfileCategory::Linking, "link_crate"));
// Now that we won't touch anything in the incremental compilation directory
// any more, we can finalize it (which involves renaming it)
rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
2017-09-16 15:27:29 +00:00
Ok(())
2017-09-16 15:27:29 +00:00
}
}
2018-05-08 13:10:16 +00:00
/// This is the entrypoint for a hot plugged rustc_codegen_llvm
2018-01-04 11:40:11 +00:00
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
2018-05-08 13:10:16 +00:00
LlvmCodegenBackend::new()
2018-01-04 11:40:11 +00:00
}
2018-01-01 11:17:07 +00:00
2018-09-25 15:52:03 +00:00
pub struct ModuleLlvm {
llcx: &'static mut llvm::Context,
llmod_raw: *const llvm::Module,
tm: &'static mut llvm::TargetMachine,
}
unsafe impl Send for ModuleLlvm { }
unsafe impl Sync for ModuleLlvm { }
rustc: Enable LTO and multiple codegen units This commit is a refactoring of the LTO backend in Rust to support compilations with multiple codegen units. The immediate result of this PR is to remove the artificial error emitted by rustc about `-C lto -C codegen-units-8`, but longer term this is intended to lay the groundwork for LTO with incremental compilation and ultimately be the underpinning of ThinLTO support. The problem here that needed solving is that when rustc is producing multiple codegen units in one compilation LTO needs to merge them all together. Previously only upstream dependencies were merged and it was inherently relied on that there was only one local codegen unit. Supporting this involved refactoring the optimization backend architecture for rustc, namely splitting the `optimize_and_codegen` function into `optimize` and `codegen`. After an LLVM module has been optimized it may be blocked and queued up for LTO, and only after LTO are modules code generated. Non-LTO compilations should look the same as they do today backend-wise, we'll spin up a thread for each codegen unit and optimize/codegen in that thread. LTO compilations will, however, send the LLVM module back to the coordinator thread once optimizations have finished. When all LLVM modules have finished optimizing the coordinator will invoke the LTO backend, producing a further list of LLVM modules. Currently this is always a list of one LLVM module. The coordinator then spawns further work to run LTO and code generation passes over each module. In the course of this refactoring a number of other pieces were refactored: * Management of the bytecode encoding in rlibs was centralized into one module instead of being scattered across LTO and linking. * Some internal refactorings on the link stage of the compiler was done to work directly from `CompiledModule` structures instead of lists of paths. * The trans time-graph output was tweaked a little to include a name on each bar and inflate the size of the bars a little
2017-07-23 15:14:38 +00:00
impl ModuleLlvm {
fn new(tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self {
unsafe {
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
ModuleLlvm {
llmod_raw,
llcx,
tm: create_target_machine(tcx, false),
}
}
}
fn new_metadata(tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self {
unsafe {
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
ModuleLlvm {
llmod_raw,
llcx,
tm: create_informational_target_machine(&tcx.sess, false),
}
}
}
fn parse(
cgcx: &CodegenContext<LlvmCodegenBackend>,
name: &str,
buffer: &back::lto::ModuleBuffer,
handler: &Handler,
) -> Result<Self, FatalError> {
unsafe {
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
let llmod_raw = buffer.parse(name, llcx, handler)?;
let tm = match (cgcx.tm_factory.0)() {
Ok(m) => m,
Err(e) => {
handler.struct_err(&e).emit();
return Err(FatalError)
}
};
Ok(ModuleLlvm {
llmod_raw,
llcx,
tm,
})
}
}
fn llmod(&self) -> &llvm::Module {
unsafe {
&*self.llmod_raw
}
}
}
impl Drop for ModuleLlvm {
rustc: Enable LTO and multiple codegen units This commit is a refactoring of the LTO backend in Rust to support compilations with multiple codegen units. The immediate result of this PR is to remove the artificial error emitted by rustc about `-C lto -C codegen-units-8`, but longer term this is intended to lay the groundwork for LTO with incremental compilation and ultimately be the underpinning of ThinLTO support. The problem here that needed solving is that when rustc is producing multiple codegen units in one compilation LTO needs to merge them all together. Previously only upstream dependencies were merged and it was inherently relied on that there was only one local codegen unit. Supporting this involved refactoring the optimization backend architecture for rustc, namely splitting the `optimize_and_codegen` function into `optimize` and `codegen`. After an LLVM module has been optimized it may be blocked and queued up for LTO, and only after LTO are modules code generated. Non-LTO compilations should look the same as they do today backend-wise, we'll spin up a thread for each codegen unit and optimize/codegen in that thread. LTO compilations will, however, send the LLVM module back to the coordinator thread once optimizations have finished. When all LLVM modules have finished optimizing the coordinator will invoke the LTO backend, producing a further list of LLVM modules. Currently this is always a list of one LLVM module. The coordinator then spawns further work to run LTO and code generation passes over each module. In the course of this refactoring a number of other pieces were refactored: * Management of the bytecode encoding in rlibs was centralized into one module instead of being scattered across LTO and linking. * Some internal refactorings on the link stage of the compiler was done to work directly from `CompiledModule` structures instead of lists of paths. * The trans time-graph output was tweaked a little to include a name on each bar and inflate the size of the bars a little
2017-07-23 15:14:38 +00:00
fn drop(&mut self) {
unsafe {
llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
rustc: Enable LTO and multiple codegen units This commit is a refactoring of the LTO backend in Rust to support compilations with multiple codegen units. The immediate result of this PR is to remove the artificial error emitted by rustc about `-C lto -C codegen-units-8`, but longer term this is intended to lay the groundwork for LTO with incremental compilation and ultimately be the underpinning of ThinLTO support. The problem here that needed solving is that when rustc is producing multiple codegen units in one compilation LTO needs to merge them all together. Previously only upstream dependencies were merged and it was inherently relied on that there was only one local codegen unit. Supporting this involved refactoring the optimization backend architecture for rustc, namely splitting the `optimize_and_codegen` function into `optimize` and `codegen`. After an LLVM module has been optimized it may be blocked and queued up for LTO, and only after LTO are modules code generated. Non-LTO compilations should look the same as they do today backend-wise, we'll spin up a thread for each codegen unit and optimize/codegen in that thread. LTO compilations will, however, send the LLVM module back to the coordinator thread once optimizations have finished. When all LLVM modules have finished optimizing the coordinator will invoke the LTO backend, producing a further list of LLVM modules. Currently this is always a list of one LLVM module. The coordinator then spawns further work to run LTO and code generation passes over each module. In the course of this refactoring a number of other pieces were refactored: * Management of the bytecode encoding in rlibs was centralized into one module instead of being scattered across LTO and linking. * Some internal refactorings on the link stage of the compiler was done to work directly from `CompiledModule` structures instead of lists of paths. * The trans time-graph output was tweaked a little to include a name on each bar and inflate the size of the bars a little
2017-07-23 15:14:38 +00:00
}
}
}
2018-05-08 13:10:16 +00:00
__build_diagnostic_array! { librustc_codegen_llvm, DIAGNOSTICS }