summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_gcc/src/lib.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_codegen_gcc/src/lib.rs
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_codegen_gcc/src/lib.rs')
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs196
1 files changed, 125 insertions, 71 deletions
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index ce7e31682..a530fc994 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -2,10 +2,19 @@
* TODO(antoyo): implement equality in libgccjit based on https://zpz.github.io/blog/overloading-equality-operator-in-cpp-class-hierarchy/ (for type equality?)
* TODO(antoyo): support #[inline] attributes.
* TODO(antoyo): support LTO (gcc's equivalent to Full LTO is -flto -flto-partition=one — https://documentation.suse.com/sbp/all/html/SBP-GCC-10/index.html).
+ * For Thin LTO, this might be helpful:
+ * In gcc 4.6 -fwhopr was removed and became default with -flto. The non-whopr path can still be executed via -flto-partition=none.
+ *
+ * Maybe some missing optizations enabled by rustc's LTO is in there: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
+ * Like -fipa-icf (should be already enabled) and maybe -fdevirtualize-at-ltrans.
+ * TODO: disable debug info always being emitted. Perhaps this slows down things?
*
* TODO(antoyo): remove the patches.
*/
+#![cfg_attr(not(bootstrap), allow(internal_features))]
+#![cfg_attr(not(bootstrap), doc(rust_logo))]
+#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![feature(
rustc_private,
decl_macro,
@@ -28,6 +37,7 @@ extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fluent_macro;
+extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_macros;
extern crate rustc_metadata;
@@ -35,7 +45,8 @@ extern crate rustc_middle;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
-extern crate tempfile;
+#[macro_use]
+extern crate tracing;
// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
@@ -57,6 +68,7 @@ mod coverageinfo;
mod debuginfo;
mod declare;
mod errors;
+mod gcc_util;
mod int;
mod intrinsic;
mod mono_item;
@@ -64,18 +76,29 @@ mod type_;
mod type_of;
use std::any::Any;
-use std::sync::{Arc, Mutex};
-
-use crate::errors::LTONotSupported;
-use gccjit::{Context, OptimizationLevel, CType};
+use std::fmt::Debug;
+use std::sync::Arc;
+use std::sync::Mutex;
+#[cfg(not(feature="master"))]
+use std::sync::atomic::AtomicBool;
+#[cfg(not(feature="master"))]
+use std::sync::atomic::Ordering;
+
+use gccjit::{Context, OptimizationLevel};
+#[cfg(feature="master")]
+use gccjit::TargetInfo;
+#[cfg(not(feature="master"))]
+use gccjit::CType;
+use errors::LTONotSupported;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_codegen_ssa::base::codegen_crate;
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn};
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
use rustc_codegen_ssa::target_features::supported_target_features;
-use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::sync::IntoDynSyncSend;
+use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods};
use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages;
use rustc_metadata::EncodedMetadata;
@@ -88,6 +111,9 @@ use rustc_span::Symbol;
use rustc_span::fatal_error::FatalError;
use tempfile::TempDir;
+use crate::back::lto::ModuleBuffer;
+use crate::gcc_util::target_cpu;
+
fluent_messages! { "../messages.ftl" }
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
@@ -100,9 +126,47 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
}
}
+#[cfg(not(feature="master"))]
+#[derive(Debug)]
+pub struct TargetInfo {
+ supports_128bit_integers: AtomicBool,
+}
+
+#[cfg(not(feature="master"))]
+impl TargetInfo {
+ fn cpu_supports(&self, _feature: &str) -> bool {
+ false
+ }
+
+ fn supports_128bit_int(&self) -> bool {
+ self.supports_128bit_integers.load(Ordering::SeqCst)
+ }
+}
+
+#[derive(Clone)]
+pub struct LockedTargetInfo {
+ info: Arc<Mutex<IntoDynSyncSend<TargetInfo>>>,
+}
+
+impl Debug for LockedTargetInfo {
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.info.lock().expect("lock").fmt(formatter)
+ }
+}
+
+impl LockedTargetInfo {
+ fn cpu_supports(&self, feature: &str) -> bool {
+ self.info.lock().expect("lock").cpu_supports(feature)
+ }
+
+ fn supports_128bit_int(&self) -> bool {
+ self.info.lock().expect("lock").supports_128bit_int()
+ }
+}
+
#[derive(Clone)]
pub struct GccCodegenBackend {
- supports_128bit_integers: Arc<Mutex<bool>>,
+ target_info: LockedTargetInfo,
}
impl CodegenBackend for GccCodegenBackend {
@@ -112,24 +176,40 @@ impl CodegenBackend for GccCodegenBackend {
fn init(&self, sess: &Session) {
#[cfg(feature="master")]
+ {
+ let target_cpu = target_cpu(sess);
+
+ // Get the second TargetInfo with the correct CPU features by setting the arch.
+ let context = Context::default();
+ if target_cpu != "generic" {
+ context.add_command_line_option(&format!("-march={}", target_cpu));
+ }
+
+ **self.target_info.info.lock().expect("lock") = context.get_target_info();
+ }
+
+ #[cfg(feature="master")]
gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
- if sess.lto() != Lto::No {
+ if sess.lto() == Lto::Thin {
sess.emit_warning(LTONotSupported {});
}
- let temp_dir = TempDir::new().expect("cannot create temporary directory");
- let temp_file = temp_dir.into_path().join("result.asm");
- let check_context = Context::default();
- check_context.set_print_errors_to_stderr(false);
- let _int128_ty = check_context.new_c_type(CType::UInt128t);
- // NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
- check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str"));
- *self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None);
+ #[cfg(not(feature="master"))]
+ {
+ let temp_dir = TempDir::new().expect("cannot create temporary directory");
+ let temp_file = temp_dir.into_path().join("result.asm");
+ let check_context = Context::default();
+ check_context.set_print_errors_to_stderr(false);
+ let _int128_ty = check_context.new_c_type(CType::UInt128t);
+ // NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
+ check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str"));
+ self.target_info.info.lock().expect("lock").supports_128bit_integers.store(check_context.get_last_error() == Ok(None), Ordering::SeqCst);
+ }
}
fn provide(&self, providers: &mut Providers) {
- // FIXME(antoyo) compute list of enabled features from cli flags
- providers.global_backend_features = |_tcx, ()| vec![];
+ providers.global_backend_features =
+ |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true)
}
fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box<dyn Any> {
@@ -160,7 +240,7 @@ impl CodegenBackend for GccCodegenBackend {
}
fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
- target_features(sess, allow_unstable)
+ target_features(sess, allow_unstable, &self.target_info)
}
}
@@ -168,13 +248,19 @@ impl ExtraBackendMethods for GccCodegenBackend {
fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module {
let mut mods = GccContext {
context: Context::default(),
+ should_combine_object_files: false,
+ temp_dir: None,
};
+
+ if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
+ mods.context.add_command_line_option("-masm=intel");
+ }
unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
mods
}
fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
- base::compile_codegen_unit(tcx, cgu_name, *self.supports_128bit_integers.lock().expect("lock"))
+ base::compile_codegen_unit(tcx, cgu_name, self.target_info.clone())
}
fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn<Self> {
@@ -185,14 +271,6 @@ impl ExtraBackendMethods for GccCodegenBackend {
}
}
-pub struct ModuleBuffer;
-
-impl ModuleBufferMethods for ModuleBuffer {
- fn data(&self) -> &[u8] {
- unimplemented!();
- }
-}
-
pub struct ThinBuffer;
impl ThinBufferMethods for ThinBuffer {
@@ -203,6 +281,9 @@ impl ThinBufferMethods for ThinBuffer {
pub struct GccContext {
context: Context<'static>,
+ should_combine_object_files: bool,
+ // Temporary directory used by LTO. We keep it here so that it's not removed before linking.
+ temp_dir: Option<TempDir>,
}
unsafe impl Send for GccContext {}
@@ -217,18 +298,8 @@ impl WriteBackendMethods for GccCodegenBackend {
type ThinData = ();
type ThinBuffer = ThinBuffer;
- fn run_fat_lto(_cgcx: &CodegenContext<Self>, mut modules: Vec<FatLtoInput<Self>>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
- // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins.
- // NOTE: implemented elsewhere.
- // TODO(antoyo): what is implemented elsewhere ^ ?
- let module =
- match modules.remove(0) {
- FatLtoInput::InMemory(module) => module,
- FatLtoInput::Serialized { .. } => {
- unimplemented!();
- }
- };
- Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: vec![] })
+ fn run_fat_lto(cgcx: &CodegenContext<Self>, modules: Vec<FatLtoInput<Self>>, cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
+ 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> {
@@ -277,8 +348,19 @@ impl WriteBackendMethods for GccCodegenBackend {
/// This is the entrypoint for a hot plugged rustc_codegen_gccjit
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
+ #[cfg(feature="master")]
+ let info = {
+ // Check whether the target supports 128-bit integers.
+ let context = Context::default();
+ Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info())))
+ };
+ #[cfg(not(feature="master"))]
+ let info = Arc::new(Mutex::new(IntoDynSyncSend(TargetInfo {
+ supports_128bit_integers: AtomicBool::new(false),
+ })));
+
Box::new(GccCodegenBackend {
- supports_128bit_integers: Arc::new(Mutex::new(false)),
+ target_info: LockedTargetInfo { info },
})
}
@@ -297,22 +379,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
}
}
-fn handle_native(name: &str) -> &str {
- if name != "native" {
- return name;
- }
-
- unimplemented!();
-}
-
-pub fn target_cpu(sess: &Session) -> &str {
- match sess.opts.cg.target_cpu {
- Some(ref name) => handle_native(name),
- None => handle_native(sess.target.cpu.as_ref()),
- }
-}
-
-pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
+pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo) -> Vec<Symbol> {
supported_target_features(sess)
.iter()
.filter_map(
@@ -321,26 +388,13 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
},
)
.filter(|_feature| {
- // TODO(antoyo): implement a way to get enabled feature in libgccjit.
- // Probably using the equivalent of __builtin_cpu_supports.
- // TODO(antoyo): maybe use whatever outputs the following command:
- // gcc -march=native -Q --help=target
- #[cfg(feature="master")]
- {
- // NOTE: the CPU in the CI doesn't support sse4a, so disable it to make the stdarch tests pass in the CI.
- (_feature.contains("sse") || _feature.contains("avx")) && !_feature.contains("avx512") && !_feature.contains("sse4a")
- }
- #[cfg(not(feature="master"))]
- {
- false
- }
+ target_info.cpu_supports(_feature)
/*
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512ifma,
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
*/
- //false
})
.map(|feature| Symbol::intern(feature))
.collect()