Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use rustc_log::tracing::debug;
use rustc_session::config::OutputType;
use rustc_target::spec::SplitDebuginfo;

use crate::base::add_pic_option;
use crate::errors::CopyBitcode;
use crate::gcc_util::add_pic_option;
use crate::{GccContext, LtoMode};

pub(crate) fn codegen(
Expand Down Expand Up @@ -68,9 +68,6 @@ pub(crate) fn codegen(
let _timer = prof
.generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name);
if lto_supported {
// TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
//embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);

context.add_command_line_option("-flto=auto");
context.add_command_line_option("-flto-partition=one");
context.add_command_line_option("-ffat-lto-objects");
Expand Down
123 changes: 4 additions & 119 deletions src/base.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::collections::HashSet;
use std::env;
use std::sync::Arc;
use std::time::Instant;

use gccjit::{CType, Context, FunctionType, GlobalKind};
use gccjit::{CType, FunctionType, GlobalKind};
use rustc_codegen_ssa::ModuleCodegen;
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
Expand All @@ -18,11 +16,11 @@ use rustc_session::config::DebugInfo;
use rustc_span::Symbol;
#[cfg(feature = "master")]
use rustc_target::spec::SymbolVisibility;
use rustc_target::spec::{Arch, RelocModel};

use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext, gcc_util, new_context};
use crate::gcc_util::new_context;
use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext};

#[cfg(feature = "master")]
pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility {
Expand Down Expand Up @@ -101,41 +99,7 @@ pub fn compile_codegen_unit(
) -> ModuleCodegen<GccContext> {
let cgu = tcx.codegen_unit(cgu_name);
// Instantiate monomorphizations without filling out definitions yet...
let context = new_context(tcx);

if tcx.sess.panic_strategy().unwinds() {
context.add_command_line_option("-fexceptions");
context.add_driver_option("-fexceptions");
}

let disabled_features: HashSet<_> = tcx
.sess
.opts
.cg
.target_feature
.split(',')
.filter(|feature| feature.starts_with('-'))
.map(|string| &string[1..])
.collect();

if !disabled_features.contains("avx") && tcx.sess.target.arch == Arch::X86_64 {
// 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");
}

for arg in &tcx.sess.opts.cg.llvm_args {
context.add_command_line_option(arg);
}
// 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");
// NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53).
context.add_command_line_option("-fno-semantic-interposition");
// 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");
// NOTE: Rust relies on LLVM doing wrapping on overflow.
context.add_command_line_option("-fwrapv");
let context = new_context(tcx.sess);

// NOTE: We need to honor the `#![no_builtins]` attribute to prevent GCC from
// replacing code patterns (like loops) with calls to builtins (like memset).
Expand All @@ -148,64 +112,6 @@ pub fn compile_codegen_unit(
context.add_command_line_option("-fno-tree-loop-distribute-patterns");
}

if let Some(model) = tcx.sess.code_model() {
use rustc_target::spec::CodeModel;

context.add_command_line_option(match model {
CodeModel::Tiny => "-mcmodel=tiny",
CodeModel::Small => "-mcmodel=small",
CodeModel::Kernel => "-mcmodel=kernel",
CodeModel::Medium => "-mcmodel=medium",
CodeModel::Large => "-mcmodel=large",
});
}

add_pic_option(&context, tcx.sess.relocation_model());

let target_cpu = gcc_util::target_cpu(tcx.sess);
if target_cpu != "generic" {
context.add_command_line_option(format!("-march={}", target_cpu));
}

if tcx
.sess
.opts
.unstable_opts
.function_sections
.unwrap_or(tcx.sess.target.function_sections)
{
context.add_command_line_option("-ffunction-sections");
context.add_command_line_option("-fdata-sections");
}

if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") {
context.add_command_line_option("-fdump-rtl-vregs");
}
if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") {
context.add_command_line_option("-fdump-rtl-all");
}
if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") {
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");
}
if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
context.set_dump_code_on_compile(true);
}
if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") {
context.set_dump_initial_gimple(true);
}
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);
}
if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") {
context.add_driver_option("-v");
}

// NOTE: The codegen generates unreachable blocks.
context.set_allow_unreachable_blocks(true);

Expand Down Expand Up @@ -269,24 +175,3 @@ pub fn compile_codegen_unit(

(module, cost)
}

pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) {
match relocation_model {
rustc_target::spec::RelocModel::Static => {
context.add_command_line_option("-fno-pie");
context.add_driver_option("-fno-pie");
}
rustc_target::spec::RelocModel::Pic => {
context.add_command_line_option("-fPIC");
// NOTE: we use both add_command_line_option and add_driver_option because the usage in
// this module (compile_codegen_unit) requires add_command_line_option while the usage
// in the back::write module (codegen) requires add_driver_option.
context.add_driver_option("-fPIC");
}
rustc_target::spec::RelocModel::Pie => {
context.add_command_line_option("-fPIE");
context.add_driver_option("-fPIE");
}
model => eprintln!("Unsupported relocation model: {:?}", model),
}
}
136 changes: 134 additions & 2 deletions src/gcc_util.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#[cfg(feature = "master")]
use std::collections::HashSet;
use std::env;

use gccjit::Context;
#[cfg(feature = "master")]
use gccjit::Version;
use rustc_codegen_ssa::target_features;
use rustc_data_structures::smallvec::{SmallVec, smallvec};
use rustc_session::Session;
use rustc_target::spec::Arch;
use rustc_target::spec::{Arch, RelocModel};

fn gcc_features_by_flags(sess: &Session, features: &mut Vec<String>) {
target_features::retpoline_features_by_flags(sess, features);
Expand Down Expand Up @@ -135,3 +139,131 @@ pub fn target_cpu(sess: &Session) -> &str {
None => handle_native(sess.target.cpu.as_ref()),
}
}

pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> {
let context = Context::default();
if matches!(sess.target.arch, Arch::X86 | Arch::X86_64) {
context.add_command_line_option("-masm=intel");
}
#[cfg(feature = "master")]
{
context.set_special_chars_allowed_in_func_names("$.*");
let version = Version::get();
let version = format!("{}.{}.{}", version.major, version.minor, version.patch);
context.set_output_ident(&format!(
"rustc version {} with libgccjit {}",
rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
version,
));
}
// TODO(antoyo): check if this should only be added when using -Cforce-unwind-tables=n.
context.add_command_line_option("-fno-asynchronous-unwind-tables");

if sess.panic_strategy().unwinds() {
context.add_command_line_option("-fexceptions");
context.add_driver_option("-fexceptions");
}

let disabled_features: HashSet<_> = sess
.opts
.cg
.target_feature
.split(',')
.filter(|feature| feature.starts_with('-'))
.map(|string| &string[1..])
.collect();

if !disabled_features.contains("avx") && sess.target.arch == Arch::X86_64 {
// 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");
}

for arg in &sess.opts.cg.llvm_args {
context.add_command_line_option(arg);
}
// 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");
// NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53).
context.add_command_line_option("-fno-semantic-interposition");
// 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");
// NOTE: Rust relies on LLVM doing wrapping on overflow.
context.add_command_line_option("-fwrapv");

if let Some(model) = sess.code_model() {
use rustc_target::spec::CodeModel;

context.add_command_line_option(match model {
CodeModel::Tiny => "-mcmodel=tiny",
CodeModel::Small => "-mcmodel=small",
CodeModel::Kernel => "-mcmodel=kernel",
CodeModel::Medium => "-mcmodel=medium",
CodeModel::Large => "-mcmodel=large",
});
}

add_pic_option(&context, sess.relocation_model());

let target_cpu = target_cpu(sess);
if target_cpu != "generic" {
context.add_command_line_option(format!("-march={}", target_cpu));
}

if sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections) {
context.add_command_line_option("-ffunction-sections");
context.add_command_line_option("-fdata-sections");
}

if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") {
context.add_command_line_option("-fdump-rtl-vregs");
}
if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") {
context.add_command_line_option("-fdump-rtl-all");
}
if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") {
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");
}
if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
context.set_dump_code_on_compile(true);
}
if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") {
context.set_dump_initial_gimple(true);
}
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);
}
if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") {
context.add_driver_option("-v");
}

context
}

pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) {
match relocation_model {
rustc_target::spec::RelocModel::Static => {
context.add_command_line_option("-fno-pie");
context.add_driver_option("-fno-pie");
}
rustc_target::spec::RelocModel::Pic => {
context.add_command_line_option("-fPIC");
// NOTE: we use both add_command_line_option and add_driver_option because the usage in
// this module (compile_codegen_unit) requires add_command_line_option while the usage
// in the back::write module (codegen) requires add_driver_option.
context.add_driver_option("-fPIC");
}
rustc_target::spec::RelocModel::Pie => {
context.add_command_line_option("-fPIE");
context.add_driver_option("-fPIE");
}
model => eprintln!("Unsupported relocation model: {:?}", model),
}
}
29 changes: 4 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};

use gccjit::{CType, Context, OptimizationLevel};
#[cfg(feature = "master")]
use gccjit::{TargetInfo, Version};
use gccjit::TargetInfo;
use gccjit::{CType, Context, OptimizationLevel};
use rustc_ast::expand::allocator::AllocatorMethod;
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
use rustc_codegen_ssa::back::write::{
Expand All @@ -99,7 +99,7 @@ use rustc_middle::util::Providers;
use rustc_session::Session;
use rustc_session::config::{OptLevel, OutputFilenames};
use rustc_span::Symbol;
use rustc_target::spec::{Arch, RelocModel};
use rustc_target::spec::RelocModel;
use tempfile::TempDir;

use crate::back::lto::ModuleBuffer;
Expand Down Expand Up @@ -312,27 +312,6 @@ impl CodegenBackend for GccCodegenBackend {
}
}

fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
let context = Context::default();
if matches!(tcx.sess.target.arch, Arch::X86 | Arch::X86_64) {
context.add_command_line_option("-masm=intel");
}
#[cfg(feature = "master")]
{
context.set_special_chars_allowed_in_func_names("$.*");
let version = Version::get();
let version = format!("{}.{}.{}", version.major, version.minor, version.patch);
context.set_output_ident(&format!(
"rustc version {} with libgccjit {}",
rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
version,
));
}
// TODO(antoyo): check if this should only be added when using -Cforce-unwind-tables=n.
context.add_command_line_option("-fno-asynchronous-unwind-tables");
context
}

impl ExtraBackendMethods for GccCodegenBackend {
fn supports_parallel(&self) -> bool {
false
Expand All @@ -346,7 +325,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
) -> Self::Module {
let lto_supported = self.lto_supported.load(Ordering::SeqCst);
let mut mods = GccContext {
context: Arc::new(SyncContext::new(new_context(tcx))),
context: Arc::new(SyncContext::new(gcc_util::new_context(tcx.sess))),
relocation_model: tcx.sess.relocation_model(),
lto_mode: LtoMode::None,
lto_supported,
Expand Down
Loading