2023-10-09 19:53:34 +00:00
|
|
|
use std::collections::HashSet;
|
2020-05-10 14:54:30 +00:00
|
|
|
use std::env;
|
2024-06-26 12:54:49 +00:00
|
|
|
use std::sync::Arc;
|
2020-05-10 14:54:30 +00:00
|
|
|
use std::time::Instant;
|
|
|
|
|
2024-06-13 12:45:41 +00:00
|
|
|
use gccjit::{CType, FunctionType, GlobalKind};
|
2020-05-10 14:54:30 +00:00
|
|
|
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
|
|
|
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
2024-09-17 00:15:26 +00:00
|
|
|
use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
|
2024-03-05 18:58:36 +00:00
|
|
|
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
|
|
|
|
use rustc_middle::dep_graph;
|
|
|
|
use rustc_middle::mir::mono::Linkage;
|
|
|
|
#[cfg(feature = "master")]
|
|
|
|
use rustc_middle::mir::mono::Visibility;
|
|
|
|
use rustc_middle::ty::TyCtxt;
|
2020-05-10 14:54:30 +00:00
|
|
|
use rustc_session::config::DebugInfo;
|
|
|
|
use rustc_span::Symbol;
|
2023-11-19 18:42:13 +00:00
|
|
|
use rustc_target::spec::PanicStrategy;
|
2020-05-10 14:54:30 +00:00
|
|
|
|
|
|
|
use crate::builder::Builder;
|
|
|
|
use crate::context::CodegenCx;
|
2024-03-05 18:58:36 +00:00
|
|
|
use crate::{gcc_util, new_context, GccContext, LockedTargetInfo, SyncContext};
|
2020-05-10 14:54:30 +00:00
|
|
|
|
2024-03-05 18:58:36 +00:00
|
|
|
#[cfg(feature = "master")]
|
2023-03-05 17:03:19 +00:00
|
|
|
pub fn visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility {
|
|
|
|
match linkage {
|
|
|
|
Visibility::Default => gccjit::Visibility::Default,
|
|
|
|
Visibility::Hidden => gccjit::Visibility::Hidden,
|
|
|
|
Visibility::Protected => gccjit::Visibility::Protected,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-10 14:54:30 +00:00
|
|
|
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 12:28:46 +00:00
|
|
|
Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage.
|
2020-05-10 14:54:30 +00:00
|
|
|
Linkage::Common => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
|
|
|
|
match linkage {
|
|
|
|
Linkage::External => FunctionType::Exported,
|
2023-10-09 19:53:34 +00:00
|
|
|
// TODO(antoyo): set the attribute externally_visible.
|
2020-05-10 14:54:30 +00:00
|
|
|
Linkage::AvailableExternally => FunctionType::Extern,
|
|
|
|
Linkage::LinkOnceAny => unimplemented!(),
|
|
|
|
Linkage::LinkOnceODR => unimplemented!(),
|
2021-08-15 12:28:46 +00:00
|
|
|
Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce.
|
2020-05-10 14:54:30 +00:00
|
|
|
Linkage::WeakODR => unimplemented!(),
|
|
|
|
Linkage::Appending => unimplemented!(),
|
|
|
|
Linkage::Internal => FunctionType::Internal,
|
|
|
|
Linkage::Private => FunctionType::Internal,
|
|
|
|
Linkage::ExternalWeak => unimplemented!(),
|
|
|
|
Linkage::Common => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 18:58:36 +00:00
|
|
|
pub fn compile_codegen_unit(
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
cgu_name: Symbol,
|
|
|
|
target_info: LockedTargetInfo,
|
|
|
|
) -> (ModuleCodegen<GccContext>, u64) {
|
2020-05-10 14:54:30 +00:00
|
|
|
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);
|
2021-10-16 20:31:48 +00:00
|
|
|
let (module, _) = tcx.dep_graph.with_task(
|
|
|
|
dep_node,
|
|
|
|
tcx,
|
2023-10-09 19:53:34 +00:00
|
|
|
(cgu_name, target_info),
|
2021-10-16 20:31:48 +00:00
|
|
|
module_codegen,
|
|
|
|
Some(dep_graph::hash_result),
|
|
|
|
);
|
2020-05-10 14:54:30 +00:00
|
|
|
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;
|
|
|
|
|
2024-03-05 18:58:36 +00:00
|
|
|
fn module_codegen(
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
(cgu_name, target_info): (Symbol, LockedTargetInfo),
|
|
|
|
) -> ModuleCodegen<GccContext> {
|
2020-05-10 14:54:30 +00:00
|
|
|
let cgu = tcx.codegen_unit(cgu_name);
|
|
|
|
// Instantiate monomorphizations without filling out definitions yet...
|
2023-11-19 18:51:56 +00:00
|
|
|
let context = new_context(tcx);
|
2023-03-05 17:03:19 +00:00
|
|
|
|
2023-11-19 18:42:13 +00:00
|
|
|
if tcx.sess.panic_strategy() == PanicStrategy::Unwind {
|
|
|
|
context.add_command_line_option("-fexceptions");
|
|
|
|
context.add_driver_option("-fexceptions");
|
|
|
|
}
|
2023-03-05 17:03:19 +00:00
|
|
|
|
2024-03-05 18:58:36 +00:00
|
|
|
let disabled_features: HashSet<_> = tcx
|
|
|
|
.sess
|
|
|
|
.opts
|
|
|
|
.cg
|
|
|
|
.target_feature
|
|
|
|
.split(',')
|
2023-10-09 19:53:34 +00:00
|
|
|
.filter(|feature| feature.starts_with('-'))
|
|
|
|
.map(|string| &string[1..])
|
|
|
|
.collect();
|
|
|
|
|
2023-10-26 21:42:02 +00:00
|
|
|
if !disabled_features.contains("avx") && tcx.sess.target.arch == "x86_64" {
|
2023-10-09 19:53:34 +00:00
|
|
|
// NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for
|
|
|
|
// SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead.
|
|
|
|
// FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar.
|
|
|
|
context.add_command_line_option("-mavx");
|
|
|
|
}
|
2023-03-05 17:03:19 +00:00
|
|
|
|
2020-05-10 14:54:30 +00:00
|
|
|
for arg in &tcx.sess.opts.cg.llvm_args {
|
|
|
|
context.add_command_line_option(arg);
|
|
|
|
}
|
2022-06-07 02:04:37 +00:00
|
|
|
// NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc.
|
|
|
|
context.add_command_line_option("-fno-var-tracking-assignments");
|
2021-12-31 15:26:32 +00:00
|
|
|
// NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53).
|
2020-05-10 14:54:30 +00:00
|
|
|
context.add_command_line_option("-fno-semantic-interposition");
|
2021-12-31 15:26:32 +00: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");
|
2023-03-05 17:03:19 +00:00
|
|
|
// NOTE: Rust relies on LLVM doing wrapping on overflow.
|
|
|
|
context.add_command_line_option("-fwrapv");
|
2022-03-26 17:29:37 +00:00
|
|
|
|
2023-10-09 20:03:05 +00:00
|
|
|
if tcx.sess.relocation_model() == rustc_target::spec::RelocModel::Static {
|
2023-10-09 19:53:34 +00:00
|
|
|
context.add_command_line_option("-mcmodel=kernel");
|
|
|
|
context.add_command_line_option("-fno-pie");
|
|
|
|
}
|
|
|
|
|
|
|
|
let target_cpu = gcc_util::target_cpu(tcx.sess);
|
|
|
|
if target_cpu != "generic" {
|
2024-03-08 10:47:20 +00:00
|
|
|
context.add_command_line_option(format!("-march={}", target_cpu));
|
2023-10-09 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2024-03-05 18:58:36 +00:00
|
|
|
if tcx
|
|
|
|
.sess
|
|
|
|
.opts
|
|
|
|
.unstable_opts
|
|
|
|
.function_sections
|
|
|
|
.unwrap_or(tcx.sess.target.function_sections)
|
|
|
|
{
|
2022-03-26 17:29:37 +00:00
|
|
|
context.add_command_line_option("-ffunction-sections");
|
|
|
|
context.add_command_line_option("-fdata-sections");
|
|
|
|
}
|
|
|
|
|
2023-03-05 17:03:19 +00:00
|
|
|
if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") {
|
|
|
|
context.add_command_line_option("-fdump-rtl-vregs");
|
|
|
|
}
|
2023-10-09 19:53:34 +00:00
|
|
|
if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") {
|
|
|
|
context.add_command_line_option("-fdump-rtl-all");
|
|
|
|
}
|
2023-03-05 17:03:19 +00:00
|
|
|
if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") {
|
2023-10-09 19:53:34 +00:00
|
|
|
context.add_command_line_option("-fdump-tree-all-eh");
|
|
|
|
}
|
|
|
|
if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") {
|
|
|
|
context.add_command_line_option("-fdump-ipa-all-eh");
|
2023-03-05 17:03:19 +00:00
|
|
|
}
|
2021-08-15 12:28:46 +00:00
|
|
|
if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
|
|
|
|
context.set_dump_code_on_compile(true);
|
|
|
|
}
|
2020-05-10 14:54:30 +00:00
|
|
|
if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") {
|
|
|
|
context.set_dump_initial_gimple(true);
|
|
|
|
}
|
2021-08-15 12:28:46 +00: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);
|
|
|
|
}
|
2023-10-09 19:53:34 +00:00
|
|
|
if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") {
|
|
|
|
context.add_driver_option("-v");
|
|
|
|
}
|
|
|
|
|
2024-03-05 18:58:36 +00:00
|
|
|
// NOTE: The codegen generates unreachable blocks.
|
2022-03-26 17:29:37 +00:00
|
|
|
context.set_allow_unreachable_blocks(true);
|
|
|
|
|
2020-05-10 14:54:30 +00:00
|
|
|
{
|
2024-06-13 12:45:41 +00:00
|
|
|
// TODO: to make it less error-prone (calling get_target_info() will add the flag
|
|
|
|
// -fsyntax-only), forbid the compilation when get_target_info() is called on a
|
|
|
|
// context.
|
|
|
|
let f16_type_supported = target_info.supports_target_dependent_type(CType::Float16);
|
|
|
|
let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32);
|
2024-06-21 20:10:52 +00:00
|
|
|
let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64);
|
2024-06-13 12:45:41 +00:00
|
|
|
let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128);
|
|
|
|
// TODO: improve this to avoid passing that many arguments.
|
|
|
|
let cx = CodegenCx::new(
|
|
|
|
&context,
|
|
|
|
cgu,
|
|
|
|
tcx,
|
|
|
|
target_info.supports_128bit_int(),
|
|
|
|
f16_type_supported,
|
|
|
|
f32_type_supported,
|
2024-06-21 20:10:52 +00:00
|
|
|
f64_type_supported,
|
2024-06-13 12:45:41 +00:00
|
|
|
f128_type_supported,
|
|
|
|
);
|
2020-05-10 14:54:30 +00:00
|
|
|
|
|
|
|
let mono_items = cgu.items_in_deterministic_order(tcx);
|
2023-07-14 06:32:10 +00:00
|
|
|
for &(mono_item, data) in &mono_items {
|
|
|
|
mono_item.predefine::<Builder<'_, '_, '_>>(&cx, data.linkage, data.visibility);
|
2020-05-10 14:54:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ... 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(),
|
2024-06-26 12:54:49 +00:00
|
|
|
module_llvm: GccContext {
|
2024-06-28 18:00:45 +00:00
|
|
|
context: Arc::new(SyncContext::new(context)),
|
2024-06-26 12:54:49 +00:00
|
|
|
should_combine_object_files: false,
|
|
|
|
temp_dir: None,
|
|
|
|
},
|
2020-05-10 14:54:30 +00:00
|
|
|
kind: ModuleKind::Regular,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(module, cost)
|
|
|
|
}
|