2020-05-10 09:54:30 -05:00
|
|
|
use std::env;
|
|
|
|
use std::time::Instant;
|
|
|
|
|
|
|
|
use gccjit::{
|
|
|
|
Context,
|
|
|
|
FunctionType,
|
|
|
|
GlobalKind,
|
|
|
|
};
|
|
|
|
use rustc_middle::dep_graph;
|
|
|
|
use rustc_middle::middle::cstore::EncodedMetadata;
|
|
|
|
use rustc_middle::middle::exported_symbols;
|
|
|
|
use rustc_middle::ty::TyCtxt;
|
|
|
|
use rustc_middle::mir::mono::Linkage;
|
|
|
|
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
|
|
|
|
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
|
|
|
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
|
|
|
use rustc_codegen_ssa::traits::DebugInfoMethods;
|
|
|
|
use rustc_session::config::DebugInfo;
|
|
|
|
use rustc_span::Symbol;
|
|
|
|
|
2021-09-26 11:20:02 -05:00
|
|
|
use crate::GccContext;
|
2020-05-10 09:54:30 -05:00
|
|
|
use crate::builder::Builder;
|
|
|
|
use crate::context::CodegenCx;
|
|
|
|
|
|
|
|
pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
|
|
|
|
match linkage {
|
|
|
|
Linkage::External => GlobalKind::Imported,
|
|
|
|
Linkage::AvailableExternally => GlobalKind::Imported,
|
|
|
|
Linkage::LinkOnceAny => unimplemented!(),
|
|
|
|
Linkage::LinkOnceODR => unimplemented!(),
|
|
|
|
Linkage::WeakAny => unimplemented!(),
|
|
|
|
Linkage::WeakODR => unimplemented!(),
|
|
|
|
Linkage::Appending => unimplemented!(),
|
|
|
|
Linkage::Internal => GlobalKind::Internal,
|
|
|
|
Linkage::Private => GlobalKind::Internal,
|
2021-08-15 07:28:46 -05:00
|
|
|
Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage.
|
2020-05-10 09:54:30 -05:00
|
|
|
Linkage::Common => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
|
|
|
|
match linkage {
|
|
|
|
Linkage::External => FunctionType::Exported,
|
|
|
|
Linkage::AvailableExternally => FunctionType::Extern,
|
|
|
|
Linkage::LinkOnceAny => unimplemented!(),
|
|
|
|
Linkage::LinkOnceODR => unimplemented!(),
|
2021-08-15 07:28:46 -05:00
|
|
|
Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce.
|
2020-05-10 09:54:30 -05:00
|
|
|
Linkage::WeakODR => unimplemented!(),
|
|
|
|
Linkage::Appending => unimplemented!(),
|
|
|
|
Linkage::Internal => FunctionType::Internal,
|
|
|
|
Linkage::Private => FunctionType::Internal,
|
|
|
|
Linkage::ExternalWeak => unimplemented!(),
|
|
|
|
Linkage::Common => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<GccContext>, u64) {
|
|
|
|
let prof_timer = tcx.prof.generic_activity("codegen_module");
|
|
|
|
let start_time = Instant::now();
|
|
|
|
|
|
|
|
let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
|
|
|
|
let (module, _) = tcx.dep_graph.with_task(dep_node, tcx, cgu_name, module_codegen, dep_graph::hash_result);
|
|
|
|
let time_to_codegen = start_time.elapsed();
|
|
|
|
drop(prof_timer);
|
|
|
|
|
|
|
|
// We assume that the cost to run GCC on a CGU is proportional to
|
|
|
|
// the time we needed for codegenning it.
|
|
|
|
let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
|
|
|
|
|
|
|
|
fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<GccContext> {
|
|
|
|
let cgu = tcx.codegen_unit(cgu_name);
|
|
|
|
// Instantiate monomorphizations without filling out definitions yet...
|
|
|
|
//let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
|
|
|
|
let context = Context::default();
|
2021-08-15 07:28:46 -05:00
|
|
|
// TODO(antoyo): only set on x86 platforms.
|
2020-05-10 09:54:30 -05:00
|
|
|
context.add_command_line_option("-masm=intel");
|
|
|
|
for arg in &tcx.sess.opts.cg.llvm_args {
|
|
|
|
context.add_command_line_option(arg);
|
|
|
|
}
|
2021-10-25 16:48:15 -05:00
|
|
|
// NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53).
|
2020-05-10 09:54:30 -05:00
|
|
|
context.add_command_line_option("-fno-semantic-interposition");
|
2021-10-25 16:48:15 -05:00
|
|
|
// NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292).
|
|
|
|
context.add_command_line_option("-fno-strict-aliasing");
|
2021-08-15 07:28:46 -05:00
|
|
|
if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
|
|
|
|
context.set_dump_code_on_compile(true);
|
|
|
|
}
|
2020-05-10 09:54:30 -05:00
|
|
|
if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") {
|
|
|
|
context.set_dump_initial_gimple(true);
|
|
|
|
}
|
|
|
|
context.set_debug_info(true);
|
2021-08-15 07:28:46 -05:00
|
|
|
if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") {
|
|
|
|
context.set_dump_everything(true);
|
|
|
|
}
|
|
|
|
if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") {
|
|
|
|
context.set_keep_intermediates(true);
|
|
|
|
}
|
2020-05-10 09:54:30 -05:00
|
|
|
|
|
|
|
{
|
|
|
|
let cx = CodegenCx::new(&context, cgu, tcx);
|
|
|
|
|
|
|
|
let mono_items = cgu.items_in_deterministic_order(tcx);
|
|
|
|
for &(mono_item, (linkage, visibility)) in &mono_items {
|
|
|
|
mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ... and now that we have everything pre-defined, fill out those definitions.
|
|
|
|
for &(mono_item, _) in &mono_items {
|
|
|
|
mono_item.define::<Builder<'_, '_, '_>>(&cx);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this codegen unit contains the main function, also create the
|
|
|
|
// wrapper here
|
|
|
|
maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx);
|
|
|
|
|
|
|
|
// Finalize debuginfo
|
|
|
|
if cx.sess().opts.debuginfo != DebugInfo::None {
|
|
|
|
cx.debuginfo_finalize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ModuleCodegen {
|
|
|
|
name: cgu_name.to_string(),
|
|
|
|
module_llvm: GccContext {
|
|
|
|
context
|
|
|
|
},
|
|
|
|
kind: ModuleKind::Regular,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(module, cost)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write_compressed_metadata<'tcx>(tcx: TyCtxt<'tcx>, metadata: &EncodedMetadata, gcc_module: &mut GccContext) {
|
|
|
|
use snap::write::FrameEncoder;
|
|
|
|
use std::io::Write;
|
|
|
|
|
|
|
|
// Historical note:
|
|
|
|
//
|
|
|
|
// When using link.exe it was seen that the section name `.note.rustc`
|
|
|
|
// was getting shortened to `.note.ru`, and according to the PE and COFF
|
|
|
|
// specification:
|
|
|
|
//
|
|
|
|
// > Executable images do not use a string table and do not support
|
|
|
|
// > section names longer than 8 characters
|
|
|
|
//
|
|
|
|
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
|
|
|
|
//
|
|
|
|
// As a result, we choose a slightly shorter name! As to why
|
|
|
|
// `.note.rustc` works on MinGW, see
|
|
|
|
// https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197
|
|
|
|
let section_name = if tcx.sess.target.is_like_osx { "__DATA,.rustc" } else { ".rustc" };
|
|
|
|
|
|
|
|
let context = &gcc_module.context;
|
|
|
|
let mut compressed = rustc_metadata::METADATA_HEADER.to_vec();
|
|
|
|
FrameEncoder::new(&mut compressed).write_all(&metadata.raw_data).unwrap();
|
|
|
|
|
|
|
|
let name = exported_symbols::metadata_symbol_name(tcx);
|
|
|
|
let typ = context.new_array_type(None, context.new_type::<u8>(), compressed.len() as i32);
|
|
|
|
let global = context.new_global(None, GlobalKind::Exported, typ, name);
|
|
|
|
global.global_set_initializer(&compressed);
|
|
|
|
global.set_link_section(section_name);
|
|
|
|
|
|
|
|
// Also generate a .section directive to force no
|
|
|
|
// flags, at least for ELF outputs, so that the
|
|
|
|
// metadata doesn't get loaded into memory.
|
|
|
|
let directive = format!(".section {}", section_name);
|
|
|
|
context.add_top_level_asm(None, &directive);
|
|
|
|
}
|