Merge commit '59a81c2ca1
' into subtree-update_cg_gcc_2025_01_12
This commit is contained in:
commit
06f0a9bc78
49 changed files with 825 additions and 1519 deletions
|
@ -1,6 +1,6 @@
|
|||
#[cfg(feature = "master")]
|
||||
use gccjit::FnAttribute;
|
||||
use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{FnAttribute, VarAttribute};
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||
alloc_error_handler_name, default_fn_name, global_fn_name,
|
||||
|
@ -10,6 +10,8 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_session::config::OomStrategy;
|
||||
|
||||
use crate::GccContext;
|
||||
#[cfg(feature = "master")]
|
||||
use crate::base::symbol_visibility_to_gcc;
|
||||
|
||||
pub(crate) unsafe fn codegen(
|
||||
tcx: TyCtxt<'_>,
|
||||
|
@ -70,12 +72,20 @@ pub(crate) unsafe fn codegen(
|
|||
|
||||
let name = OomStrategy::SYMBOL.to_string();
|
||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||
#[cfg(feature = "master")]
|
||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
tcx.sess.default_visibility(),
|
||||
)));
|
||||
let value = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let value = context.new_rvalue_from_int(i8, value as i32);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
|
||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||
#[cfg(feature = "master")]
|
||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
tcx.sess.default_visibility(),
|
||||
)));
|
||||
let value = context.new_rvalue_from_int(i8, 0);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
}
|
||||
|
@ -105,15 +115,9 @@ fn create_wrapper_function(
|
|||
);
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
match tcx.sess.default_visibility() {
|
||||
rustc_target::spec::SymbolVisibility::Hidden => {
|
||||
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden))
|
||||
}
|
||||
rustc_target::spec::SymbolVisibility::Protected => {
|
||||
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Protected))
|
||||
}
|
||||
rustc_target::spec::SymbolVisibility::Interposable => {}
|
||||
}
|
||||
func.add_attribute(FnAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
tcx.sess.default_visibility(),
|
||||
)));
|
||||
|
||||
if tcx.sess.must_emit_unwind_tables() {
|
||||
// TODO(antoyo): emit unwind tables.
|
||||
|
|
|
@ -35,16 +35,13 @@ use rustc_middle::bug;
|
|||
use rustc_middle::dep_graph::WorkProduct;
|
||||
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
|
||||
use rustc_session::config::{CrateType, Lto};
|
||||
use rustc_target::spec::RelocModel;
|
||||
use tempfile::{TempDir, tempdir};
|
||||
|
||||
use crate::back::write::save_temp_bitcode;
|
||||
use crate::errors::{DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib};
|
||||
use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level};
|
||||
|
||||
/// We keep track of the computed LTO cache keys from the previous
|
||||
/// session to determine which CGUs we can reuse.
|
||||
//pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
|
||||
|
||||
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
||||
match crate_type {
|
||||
CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
|
||||
|
@ -54,7 +51,7 @@ pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
|||
|
||||
struct LtoData {
|
||||
// TODO(antoyo): use symbols_below_threshold.
|
||||
//symbols_below_threshold: Vec<CString>,
|
||||
//symbols_below_threshold: Vec<String>,
|
||||
upstream_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
tmp_path: TempDir,
|
||||
}
|
||||
|
@ -83,7 +80,7 @@ fn prepare_lto(
|
|||
|
||||
let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
|
||||
if info.level.is_below_threshold(export_threshold) || info.used {
|
||||
Some(CString::new(name.as_str()).unwrap())
|
||||
Some(name.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -91,7 +88,7 @@ fn prepare_lto(
|
|||
let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
|
||||
let mut symbols_below_threshold = {
|
||||
let _timer = cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold");
|
||||
exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<CString>>()
|
||||
exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<String>>()
|
||||
};
|
||||
info!("{} symbols to preserve in this crate", symbols_below_threshold.len());
|
||||
|
||||
|
@ -159,11 +156,7 @@ fn prepare_lto(
|
|||
}
|
||||
}
|
||||
|
||||
Ok(LtoData {
|
||||
//symbols_below_threshold,
|
||||
upstream_modules,
|
||||
tmp_path,
|
||||
})
|
||||
Ok(LtoData { upstream_modules, tmp_path })
|
||||
}
|
||||
|
||||
fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> {
|
||||
|
@ -191,7 +184,7 @@ pub(crate) fn run_fat(
|
|||
cached_modules,
|
||||
lto_data.upstream_modules,
|
||||
lto_data.tmp_path,
|
||||
//&symbols_below_threshold,
|
||||
//<o_data.symbols_below_threshold,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -202,7 +195,7 @@ fn fat_lto(
|
|||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
tmp_path: TempDir,
|
||||
//symbols_below_threshold: &[*const libc::c_char],
|
||||
//symbols_below_threshold: &[String],
|
||||
) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
|
||||
info!("going for a fat lto");
|
||||
|
@ -327,6 +320,7 @@ fn fat_lto(
|
|||
ptr as *const *const libc::c_char,
|
||||
symbols_below_threshold.len() as libc::size_t,
|
||||
);*/
|
||||
|
||||
save_temp_bitcode(cgcx, &module, "lto.after-restriction");
|
||||
//}
|
||||
}
|
||||
|
@ -363,8 +357,6 @@ pub(crate) fn run_thin(
|
|||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
let lto_data = prepare_lto(cgcx, dcx)?;
|
||||
/*let symbols_below_threshold =
|
||||
symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();*/
|
||||
if cgcx.opts.cg.linker_plugin_lto.enabled() {
|
||||
unreachable!(
|
||||
"We should never reach this case if the LTO step \
|
||||
|
@ -377,7 +369,8 @@ pub(crate) fn run_thin(
|
|||
modules,
|
||||
lto_data.upstream_modules,
|
||||
lto_data.tmp_path,
|
||||
cached_modules, /*, &symbols_below_threshold*/
|
||||
cached_modules,
|
||||
//<o_data.symbols_below_threshold,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -428,7 +421,7 @@ fn thin_lto(
|
|||
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
tmp_path: TempDir,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
//symbols_below_threshold: &[*const libc::c_char],
|
||||
//_symbols_below_threshold: &[String],
|
||||
) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
|
||||
info!("going for that thin, thin LTO");
|
||||
|
@ -640,7 +633,13 @@ pub unsafe fn optimize_thin_module(
|
|||
}
|
||||
};
|
||||
let module = ModuleCodegen {
|
||||
module_llvm: GccContext { context, should_combine_object_files, temp_dir: None },
|
||||
module_llvm: GccContext {
|
||||
context,
|
||||
should_combine_object_files,
|
||||
// TODO(antoyo): use the correct relocation model here.
|
||||
relocation_model: RelocModel::Pic,
|
||||
temp_dir: None,
|
||||
},
|
||||
name: thin_module.name().to_string(),
|
||||
kind: ModuleKind::Regular,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{env, fs};
|
||||
|
||||
use gccjit::OutputKind;
|
||||
use gccjit::{Context, OutputKind};
|
||||
use rustc_codegen_ssa::back::link::ensure_removed;
|
||||
use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
|
||||
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
|
||||
|
@ -10,6 +10,7 @@ use rustc_session::config::OutputType;
|
|||
use rustc_span::fatal_error::FatalError;
|
||||
use rustc_target::spec::SplitDebuginfo;
|
||||
|
||||
use crate::base::add_pic_option;
|
||||
use crate::errors::CopyBitcode;
|
||||
use crate::{GccCodegenBackend, GccContext};
|
||||
|
||||
|
@ -31,51 +32,87 @@ pub(crate) unsafe fn codegen(
|
|||
|
||||
// NOTE: Only generate object files with GIMPLE when this environment variable is set for
|
||||
// now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit).
|
||||
// TODO: remove this environment variable.
|
||||
// TODO(antoyo): remove this environment variable.
|
||||
let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1");
|
||||
|
||||
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
|
||||
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
|
||||
|
||||
if config.bitcode_needed() && fat_lto {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name);
|
||||
|
||||
// TODO(antoyo)
|
||||
/*if let Some(bitcode_filename) = bc_out.file_name() {
|
||||
cgcx.prof.artifact_size(
|
||||
"llvm_bitcode",
|
||||
bitcode_filename.to_string_lossy(),
|
||||
data.len() as u64,
|
||||
);
|
||||
}*/
|
||||
|
||||
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||
if config.bitcode_needed() {
|
||||
if fat_lto {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name);
|
||||
context.add_command_line_option("-flto=auto");
|
||||
context.add_command_line_option("-flto-partition=one");
|
||||
// TODO: remove since we don't want fat objects when it is for Bitcode only.
|
||||
context.add_command_line_option("-ffat-lto-objects");
|
||||
context
|
||||
.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
|
||||
}
|
||||
.generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name);
|
||||
|
||||
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name);
|
||||
// TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
|
||||
//embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
// TODO(antoyo)
|
||||
/*if let Some(bitcode_filename) = bc_out.file_name() {
|
||||
cgcx.prof.artifact_size(
|
||||
"llvm_bitcode",
|
||||
bitcode_filename.to_string_lossy(),
|
||||
data.len() as u64,
|
||||
);
|
||||
}*/
|
||||
|
||||
context.add_command_line_option("-flto=auto");
|
||||
context.add_command_line_option("-flto-partition=one");
|
||||
context.add_command_line_option("-ffat-lto-objects");
|
||||
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
|
||||
context
|
||||
.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
|
||||
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"GCC_module_codegen_emit_bitcode",
|
||||
&*module.name,
|
||||
);
|
||||
context.add_command_line_option("-flto=auto");
|
||||
context.add_command_line_option("-flto-partition=one");
|
||||
// TODO(antoyo): remove since we don't want fat objects when it is for Bitcode only.
|
||||
context.add_command_line_option("-ffat-lto-objects");
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
bc_out.to_str().expect("path to str"),
|
||||
);
|
||||
}
|
||||
|
||||
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"GCC_module_codegen_embed_bitcode",
|
||||
&*module.name,
|
||||
);
|
||||
// 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");
|
||||
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
bc_out.to_str().expect("path to str"),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"GCC_module_codegen_emit_bitcode",
|
||||
&*module.name,
|
||||
);
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
bc_out.to_str().expect("path to str"),
|
||||
);
|
||||
}
|
||||
|
||||
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
|
||||
// TODO(antoyo): we might want to emit to emit an error here, saying to set the
|
||||
// environment variable EMBED_LTO_BITCODE.
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"GCC_module_codegen_embed_bitcode",
|
||||
&*module.name,
|
||||
);
|
||||
// TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
|
||||
//embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
|
||||
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
bc_out.to_str().expect("path to str"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,6 +160,8 @@ pub(crate) unsafe fn codegen(
|
|||
|
||||
// NOTE: without -fuse-linker-plugin, we get the following error:
|
||||
// lto1: internal compiler error: decompressed stream: Destination buffer is too small
|
||||
// TODO(antoyo): since we do not do LTO when the linker is invoked anymore, perhaps
|
||||
// the following flag is not necessary anymore.
|
||||
context.add_driver_option("-fuse-linker-plugin");
|
||||
}
|
||||
|
||||
|
@ -131,11 +170,43 @@ pub(crate) unsafe fn codegen(
|
|||
// /usr/bin/ld: cannot find -lgcc_s: No such file or directory
|
||||
context.add_driver_option("-nostdlib");
|
||||
|
||||
// NOTE: this doesn't actually generate an executable. With the above flags, it combines the .o files together in another .o.
|
||||
context.compile_to_file(
|
||||
OutputKind::Executable,
|
||||
obj_out.to_str().expect("path to str"),
|
||||
);
|
||||
let path = obj_out.to_str().expect("path to str");
|
||||
|
||||
if fat_lto {
|
||||
let lto_path = format!("{}.lto", path);
|
||||
// FIXME(antoyo): The LTO frontend generates the following warning:
|
||||
// ../build_sysroot/sysroot_src/library/core/src/num/dec2flt/lemire.rs:150:15: warning: type of ‘_ZN4core3num7dec2flt5table17POWER_OF_FIVE_12817ha449a68fb31379e4E’ does not match original declaration [-Wlto-type-mismatch]
|
||||
// 150 | let (lo5, hi5) = POWER_OF_FIVE_128[index];
|
||||
// | ^
|
||||
// lto1: note: ‘_ZN4core3num7dec2flt5table17POWER_OF_FIVE_12817ha449a68fb31379e4E’ was previously declared here
|
||||
//
|
||||
// This option is to mute it to make the UI tests pass with LTO enabled.
|
||||
context.add_driver_option("-Wno-lto-type-mismatch");
|
||||
// NOTE: this doesn't actually generate an executable. With the above
|
||||
// flags, it combines the .o files together in another .o.
|
||||
context.compile_to_file(OutputKind::Executable, <o_path);
|
||||
|
||||
let context = Context::default();
|
||||
if cgcx.target_arch == "x86" || cgcx.target_arch == "x86_64" {
|
||||
// NOTE: it seems we need to use add_driver_option instead of
|
||||
// add_command_line_option here because we use the LTO frontend via gcc.
|
||||
context.add_driver_option("-masm=intel");
|
||||
}
|
||||
|
||||
// NOTE: these two options are needed to invoke LTO to produce an object file.
|
||||
// We need to initiate a second compilation because the arguments "-x lto"
|
||||
// needs to be at the very beginning.
|
||||
context.add_driver_option("-x");
|
||||
context.add_driver_option("lto");
|
||||
add_pic_option(&context, module.module_llvm.relocation_model);
|
||||
context.add_driver_option(lto_path);
|
||||
|
||||
context.compile_to_file(OutputKind::ObjectFile, path);
|
||||
} else {
|
||||
// NOTE: this doesn't actually generate an executable. With the above
|
||||
// flags, it combines the .o files together in another .o.
|
||||
context.compile_to_file(OutputKind::Executable, path);
|
||||
}
|
||||
} else {
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::env;
|
|||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
use gccjit::{CType, FunctionType, GlobalKind};
|
||||
use gccjit::{CType, Context, FunctionType, GlobalKind};
|
||||
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
||||
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
||||
use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
|
||||
|
@ -15,21 +15,32 @@ use rustc_middle::mir::mono::Visibility;
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_target::spec::SymbolVisibility;
|
||||
use rustc_target::spec::{PanicStrategy, RelocModel};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::{GccContext, LockedTargetInfo, SyncContext, gcc_util, new_context};
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
pub fn visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility {
|
||||
match linkage {
|
||||
pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility {
|
||||
match visibility {
|
||||
Visibility::Default => gccjit::Visibility::Default,
|
||||
Visibility::Hidden => gccjit::Visibility::Hidden,
|
||||
Visibility::Protected => gccjit::Visibility::Protected,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
pub fn symbol_visibility_to_gcc(visibility: SymbolVisibility) -> gccjit::Visibility {
|
||||
match visibility {
|
||||
SymbolVisibility::Hidden => gccjit::Visibility::Hidden,
|
||||
SymbolVisibility::Protected => gccjit::Visibility::Protected,
|
||||
SymbolVisibility::Interposable => gccjit::Visibility::Default,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
|
||||
match linkage {
|
||||
Linkage::External => GlobalKind::Imported,
|
||||
|
@ -140,9 +151,7 @@ pub fn compile_codegen_unit(
|
|||
});
|
||||
}
|
||||
|
||||
if tcx.sess.relocation_model() == rustc_target::spec::RelocModel::Static {
|
||||
context.add_command_line_option("-fno-pie");
|
||||
}
|
||||
add_pic_option(&context, tcx.sess.relocation_model());
|
||||
|
||||
let target_cpu = gcc_util::target_cpu(tcx.sess);
|
||||
if target_cpu != "generic" {
|
||||
|
@ -199,12 +208,13 @@ pub fn compile_codegen_unit(
|
|||
let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32);
|
||||
let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64);
|
||||
let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128);
|
||||
let u128_type_supported = target_info.supports_target_dependent_type(CType::UInt128t);
|
||||
// TODO: improve this to avoid passing that many arguments.
|
||||
let cx = CodegenCx::new(
|
||||
&context,
|
||||
cgu,
|
||||
tcx,
|
||||
target_info.supports_128bit_int(),
|
||||
u128_type_supported,
|
||||
f16_type_supported,
|
||||
f32_type_supported,
|
||||
f64_type_supported,
|
||||
|
@ -235,6 +245,7 @@ pub fn compile_codegen_unit(
|
|||
name: cgu_name.to_string(),
|
||||
module_llvm: GccContext {
|
||||
context: Arc::new(SyncContext::new(context)),
|
||||
relocation_model: tcx.sess.relocation_model(),
|
||||
should_combine_object_files: false,
|
||||
temp_dir: None,
|
||||
},
|
||||
|
@ -244,3 +255,24 @@ 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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1102,18 +1102,24 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
val: RValue<'gcc>,
|
||||
ptr: RValue<'gcc>,
|
||||
align: Align,
|
||||
_flags: MemFlags,
|
||||
flags: MemFlags,
|
||||
) -> RValue<'gcc> {
|
||||
let ptr = self.check_store(val, ptr);
|
||||
let destination = ptr.dereference(self.location);
|
||||
// NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast
|
||||
// to type so it gets the proper alignment.
|
||||
let destination_type = destination.to_rvalue().get_type().unqualified();
|
||||
let aligned_type = destination_type.get_aligned(align.bytes()).make_pointer();
|
||||
let aligned_destination = self.cx.context.new_bitcast(self.location, ptr, aligned_type);
|
||||
let aligned_destination = aligned_destination.dereference(self.location);
|
||||
self.llbb().add_assignment(self.location, aligned_destination, val);
|
||||
// TODO(antoyo): handle align and flags.
|
||||
let align = if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() };
|
||||
let mut modified_destination_type = destination_type.get_aligned(align);
|
||||
if flags.contains(MemFlags::VOLATILE) {
|
||||
modified_destination_type = modified_destination_type.make_volatile();
|
||||
}
|
||||
|
||||
let modified_ptr =
|
||||
self.cx.context.new_cast(self.location, ptr, modified_destination_type.make_pointer());
|
||||
let modified_destination = modified_ptr.dereference(self.location);
|
||||
self.llbb().add_assignment(self.location, modified_destination, val);
|
||||
// TODO(antoyo): handle `MemFlags::NONTEMPORAL`.
|
||||
// NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here?
|
||||
// When adding support for NONTEMPORAL, make sure to not just emit MOVNT on x86; see the
|
||||
// LLVM backend for details.
|
||||
|
@ -1236,13 +1242,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
let usize_value = self.cx.const_bitcast(value, self.cx.type_isize());
|
||||
let usize_value = self.cx.context.new_cast(None, value, self.cx.type_isize());
|
||||
self.intcast(usize_value, dest_ty, false)
|
||||
}
|
||||
|
||||
fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
let usize_value = self.intcast(value, self.cx.type_isize(), false);
|
||||
self.cx.const_bitcast(usize_value, dest_ty)
|
||||
self.cx.context.new_cast(None, usize_value, dest_ty)
|
||||
}
|
||||
|
||||
fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
|
@ -1901,6 +1907,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
v2: RValue<'gcc>,
|
||||
mask: RValue<'gcc>,
|
||||
) -> RValue<'gcc> {
|
||||
// NOTE: if the `mask` is a constant value, the following code will copy it in many places,
|
||||
// which will make GCC create a lot (+4000) local variables in some cases.
|
||||
// So we assign it to an explicit local variable once to avoid this.
|
||||
let func = self.current_func();
|
||||
let mask_var = func.new_local(self.location, mask.get_type(), "mask");
|
||||
let block = self.block;
|
||||
block.add_assignment(self.location, mask_var, mask);
|
||||
let mask = mask_var.to_rvalue();
|
||||
|
||||
// TODO(antoyo): use a recursive unqualified() here.
|
||||
let vector_type = v1.get_type().unqualified().dyncast_vector().expect("vector type");
|
||||
let element_type = vector_type.get_element_type();
|
||||
|
@ -1917,18 +1932,35 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
self.int_type
|
||||
};
|
||||
|
||||
let vector_type =
|
||||
mask.get_type().dyncast_vector().expect("simd_shuffle mask should be of vector type");
|
||||
let mask_num_units = vector_type.get_num_units();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
self.extract_element(mask, index).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
// NOTE: this condition is needed because we call shuffle_vector in the implementation of
|
||||
// simd_gather.
|
||||
let mut mask_elements = if let Some(vector_type) = mask.get_type().dyncast_vector() {
|
||||
let mask_num_units = vector_type.get_num_units();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
self.extract_element(mask, index).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
mask_elements
|
||||
} else {
|
||||
let struct_type = mask.get_type().is_struct().expect("mask should be of struct type");
|
||||
let mask_num_units = struct_type.get_field_count();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let field = struct_type.get_field(i as i32);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
mask.access_field(self.location, field).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
mask_elements
|
||||
};
|
||||
let mask_num_units = mask_elements.len();
|
||||
|
||||
// NOTE: the mask needs to be the same length as the input vectors, so add the missing
|
||||
// elements in the mask if needed.
|
||||
|
|
|
@ -72,95 +72,74 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
|||
|
||||
attributes::from_fn_attrs(cx, func, instance);
|
||||
|
||||
let instance_def_id = instance.def_id();
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
let instance_def_id = instance.def_id();
|
||||
|
||||
// TODO(antoyo): set linkage and attributes.
|
||||
// TODO(antoyo): set linkage and attributes.
|
||||
|
||||
// Apply an appropriate linkage/visibility value to our item that we
|
||||
// just declared.
|
||||
//
|
||||
// This is sort of subtle. Inside our codegen unit we started off
|
||||
// compilation by predefining all our own `MonoItem` instances. That
|
||||
// is, everything we're codegenning ourselves is already defined. That
|
||||
// means that anything we're actually codegenning in this codegen unit
|
||||
// will have hit the above branch in `get_declared_value`. As a result,
|
||||
// we're guaranteed here that we're declaring a symbol that won't get
|
||||
// defined, or in other words we're referencing a value from another
|
||||
// codegen unit or even another crate.
|
||||
//
|
||||
// So because this is a foreign value we blanket apply an external
|
||||
// linkage directive because it's coming from a different object file.
|
||||
// The visibility here is where it gets tricky. This symbol could be
|
||||
// referencing some foreign crate or foreign library (an `extern`
|
||||
// block) in which case we want to leave the default visibility. We may
|
||||
// also, though, have multiple codegen units. It could be a
|
||||
// monomorphization, in which case its expected visibility depends on
|
||||
// whether we are sharing generics or not. The important thing here is
|
||||
// that the visibility we apply to the declaration is the same one that
|
||||
// has been applied to the definition (wherever that definition may be).
|
||||
let is_generic = instance.args.non_erasable_generics().next().is_some();
|
||||
// Apply an appropriate linkage/visibility value to our item that we
|
||||
// just declared.
|
||||
//
|
||||
// This is sort of subtle. Inside our codegen unit we started off
|
||||
// compilation by predefining all our own `MonoItem` instances. That
|
||||
// is, everything we're codegenning ourselves is already defined. That
|
||||
// means that anything we're actually codegenning in this codegen unit
|
||||
// will have hit the above branch in `get_declared_value`. As a result,
|
||||
// we're guaranteed here that we're declaring a symbol that won't get
|
||||
// defined, or in other words we're referencing a value from another
|
||||
// codegen unit or even another crate.
|
||||
//
|
||||
// So because this is a foreign value we blanket apply an external
|
||||
// linkage directive because it's coming from a different object file.
|
||||
// The visibility here is where it gets tricky. This symbol could be
|
||||
// referencing some foreign crate or foreign library (an `extern`
|
||||
// block) in which case we want to leave the default visibility. We may
|
||||
// also, though, have multiple codegen units. It could be a
|
||||
// monomorphization, in which case its expected visibility depends on
|
||||
// whether we are sharing generics or not. The important thing here is
|
||||
// that the visibility we apply to the declaration is the same one that
|
||||
// has been applied to the definition (wherever that definition may be).
|
||||
let is_generic = instance.args.non_erasable_generics().next().is_some();
|
||||
|
||||
if is_generic {
|
||||
// This is a monomorphization. Its expected visibility depends
|
||||
// on whether we are in share-generics mode.
|
||||
|
||||
if cx.tcx.sess.opts.share_generics() {
|
||||
// We are in share_generics mode.
|
||||
|
||||
if let Some(instance_def_id) = instance_def_id.as_local() {
|
||||
// This is a definition from the current crate. If the
|
||||
// definition is unreachable for downstream crates or
|
||||
// the current crate does not re-export generics, the
|
||||
// definition of the instance will have been declared
|
||||
// as `hidden`.
|
||||
if cx.tcx.is_unreachable_local_definition(instance_def_id)
|
||||
let is_hidden = if is_generic {
|
||||
// This is a monomorphization of a generic function.
|
||||
if !(cx.tcx.sess.opts.share_generics()
|
||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||
== rustc_attr_parsing::InlineAttr::Never)
|
||||
{
|
||||
// When not sharing generics, all instances are in the same
|
||||
// crate and have hidden visibility.
|
||||
true
|
||||
} else if let Some(instance_def_id) = instance_def_id.as_local() {
|
||||
// This is a monomorphization of a generic function
|
||||
// defined in the current crate. It is hidden if:
|
||||
// - the definition is unreachable for downstream
|
||||
// crates, or
|
||||
// - the current crate does not re-export generics
|
||||
// (because the crate is a C library or executable)
|
||||
cx.tcx.is_unreachable_local_definition(instance_def_id)
|
||||
|| !cx.tcx.local_crate_exports_generics()
|
||||
{
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
} else {
|
||||
// This is a monomorphization of a generic function
|
||||
// defined in an upstream crate.
|
||||
if instance.upstream_monomorphization(tcx).is_some() {
|
||||
// This is instantiated in another crate. It cannot
|
||||
// be `hidden`.
|
||||
} else {
|
||||
// This is a local instantiation of an upstream definition.
|
||||
// If the current crate does not re-export it
|
||||
// (because it is a C library or an executable), it
|
||||
// will have been declared `hidden`.
|
||||
if !cx.tcx.local_crate_exports_generics() {
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
}
|
||||
// defined in an upstream crate. It is hidden if:
|
||||
// - it is instantiated in this crate, and
|
||||
// - the current crate does not re-export generics
|
||||
instance.upstream_monomorphization(tcx).is_none()
|
||||
&& !cx.tcx.local_crate_exports_generics()
|
||||
}
|
||||
} else {
|
||||
// When not sharing generics, all instances are in the same
|
||||
// crate and have hidden visibility
|
||||
#[cfg(feature = "master")]
|
||||
// This is a non-generic function. It is hidden if:
|
||||
// - it is instantiated in the local crate, and
|
||||
// - it is defined an upstream crate (non-local), or
|
||||
// - it is not reachable
|
||||
cx.tcx.is_codegened_item(instance_def_id)
|
||||
&& (!instance_def_id.is_local()
|
||||
|| !cx.tcx.is_reachable_non_generic(instance_def_id))
|
||||
};
|
||||
if is_hidden {
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
} else {
|
||||
// This is a non-generic function
|
||||
if cx.tcx.is_codegened_item(instance_def_id) {
|
||||
// This is a function that is instantiated in the local crate
|
||||
|
||||
if instance_def_id.is_local() {
|
||||
// This is function that is defined in the local crate.
|
||||
// If it is not reachable, it is hidden.
|
||||
if !cx.tcx.is_reachable_non_generic(instance_def_id) {
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
} else {
|
||||
// This is a function from an upstream crate that has
|
||||
// been instantiated here. These are always hidden.
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func
|
||||
|
|
|
@ -240,14 +240,14 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
};
|
||||
let ptr_type = base_addr.get_type();
|
||||
let base_addr = self.const_bitcast(base_addr, self.usize_type);
|
||||
let base_addr = self.context.new_cast(None, base_addr, self.usize_type);
|
||||
let offset =
|
||||
self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64);
|
||||
let ptr = self.const_bitcast(base_addr + offset, ptr_type);
|
||||
let ptr = self.context.new_cast(None, base_addr + offset, ptr_type);
|
||||
if !matches!(layout.primitive(), Pointer(_)) {
|
||||
self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
|
||||
} else {
|
||||
self.const_bitcast(ptr, ty)
|
||||
self.context.new_cast(None, ptr, ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -252,7 +252,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let global = self.declare_global(
|
||||
sym,
|
||||
gcc_type,
|
||||
GlobalKind::Exported,
|
||||
GlobalKind::Imported,
|
||||
is_tls,
|
||||
fn_attrs.link_section,
|
||||
);
|
||||
|
@ -404,7 +404,6 @@ fn check_and_apply_linkage<'gcc, 'tcx>(
|
|||
// TODO(antoyo): set linkage.
|
||||
let value = cx.const_ptrcast(global1.get_address(None), gcc_type);
|
||||
global2.global_set_initializer_rvalue(value);
|
||||
// TODO(antoyo): use global_set_initializer() when it will work.
|
||||
global2
|
||||
} else {
|
||||
// Generate an external declaration.
|
||||
|
|
|
@ -386,6 +386,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
|
||||
type Value = RValue<'gcc>;
|
||||
type Metadata = RValue<'gcc>;
|
||||
// TODO(antoyo): change to Function<'gcc>.
|
||||
type Function = RValue<'gcc>;
|
||||
|
||||
type BasicBlock = Block<'gcc>;
|
||||
|
|
|
@ -40,10 +40,6 @@ pub(crate) enum PossibleFeature<'a> {
|
|||
None,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_lto_not_supported)]
|
||||
pub(crate) struct LTONotSupported;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_unwinding_inline_asm)]
|
||||
pub(crate) struct UnwindingInlineAsm {
|
||||
|
|
|
@ -66,16 +66,14 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
|||
// We do the equivalent above in `target_features_cfg`.
|
||||
// See <https://github.com/rust-lang/rust/issues/134792>.
|
||||
all_rust_features.push((false, feature));
|
||||
} else if !feature.is_empty() {
|
||||
if diagnostics {
|
||||
sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature });
|
||||
}
|
||||
} else if !feature.is_empty() && diagnostics {
|
||||
sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature });
|
||||
}
|
||||
}
|
||||
// Remove features that are meant for rustc, not codegen.
|
||||
all_rust_features.retain(|(_, feature)| {
|
||||
all_rust_features.retain(|&(_, feature)| {
|
||||
// Retain if it is not a rustc feature
|
||||
!RUSTC_SPECIFIC_FEATURES.contains(feature)
|
||||
!RUSTC_SPECIFIC_FEATURES.contains(&feature)
|
||||
});
|
||||
|
||||
// Check feature validity.
|
||||
|
@ -103,7 +101,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
|||
};
|
||||
sess.dcx().emit_warn(unknown_feature);
|
||||
}
|
||||
Some((_, stability, _)) => {
|
||||
Some(&(_, stability, _)) => {
|
||||
if let Err(reason) = stability.toggle_allowed() {
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature {
|
||||
feature,
|
||||
|
@ -165,29 +163,25 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
|||
);
|
||||
|
||||
// Translate this into GCC features.
|
||||
let feats = all_rust_features
|
||||
.iter()
|
||||
.filter_map(|&(enable, feature)| {
|
||||
let feats =
|
||||
all_rust_features.iter().flat_map(|&(enable, feature)| {
|
||||
let enable_disable = if enable { '+' } else { '-' };
|
||||
// We run through `to_gcc_features` when
|
||||
// passing requests down to GCC. This means that all in-language
|
||||
// features also work on the command line instead of having two
|
||||
// different names when the GCC name and the Rust name differ.
|
||||
Some(
|
||||
to_gcc_features(sess, feature)
|
||||
.iter()
|
||||
.flat_map(|feat| to_gcc_features(sess, feat).into_iter())
|
||||
.map(|feature| {
|
||||
if enable_disable == '-' {
|
||||
format!("-{}", feature)
|
||||
} else {
|
||||
feature.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.flatten();
|
||||
to_gcc_features(sess, feature)
|
||||
.iter()
|
||||
.flat_map(|feat| to_gcc_features(sess, feat).into_iter())
|
||||
.map(|feature| {
|
||||
if enable_disable == '-' {
|
||||
format!("-{}", feature)
|
||||
} else {
|
||||
feature.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
features.extend(feats);
|
||||
|
||||
if diagnostics {
|
||||
|
|
|
@ -90,7 +90,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if a_type.is_vector() && a_type.is_vector() {
|
||||
} else if a_type.is_vector() && b_type.is_vector() {
|
||||
a >> b
|
||||
} else if a_native && !b_native {
|
||||
self.gcc_lshr(a, self.gcc_int_cast(b, a_type))
|
||||
|
@ -660,7 +660,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if a_type.is_vector() && a_type.is_vector() {
|
||||
} else if a_type.is_vector() && b_type.is_vector() {
|
||||
a << b
|
||||
} else if a_native && !b_native {
|
||||
self.gcc_shl(a, self.gcc_int_cast(b, a_type))
|
||||
|
|
|
@ -421,7 +421,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
|
|||
| "__builtin_ia32_xsaveopt64" => {
|
||||
let new_args = args.to_vec();
|
||||
let thirty_two = builder.context.new_rvalue_from_int(new_args[1].get_type(), 32);
|
||||
let arg2 = new_args[1] << thirty_two | new_args[2];
|
||||
let arg2 = (new_args[1] << thirty_two) | new_args[2];
|
||||
let arg2_type = gcc_func.get_param_type(1);
|
||||
let arg2 = builder.context.new_cast(None, arg2, arg2_type);
|
||||
args = vec![new_args[0], arg2].into();
|
||||
|
|
|
@ -13,15 +13,16 @@ use rustc_codegen_ssa::common::IntPredicate;
|
|||
use rustc_codegen_ssa::errors::InvalidMonomorphization;
|
||||
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
||||
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
||||
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_codegen_ssa::traits::MiscCodegenMethods;
|
||||
use rustc_codegen_ssa::traits::{
|
||||
ArgAbiBuilderMethods, BuilderMethods, ConstCodegenMethods, IntrinsicCallBuilderMethods,
|
||||
};
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, MiscCodegenMethods};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_target::abi::HasDataLayout;
|
||||
|
@ -139,6 +140,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
sym::fmaf16 => {
|
||||
// TODO(antoyo): use the correct builtin for f16.
|
||||
let func = self.cx.context.get_builtin_function("fmaf");
|
||||
let args: Vec<_> = args
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
self.cx.context.new_cast(self.location, arg.immediate(), self.cx.type_f32())
|
||||
})
|
||||
.collect();
|
||||
let result = self.cx.context.new_call(self.location, func, &args);
|
||||
self.cx.context.new_cast(self.location, result, self.cx.type_f16())
|
||||
}
|
||||
sym::is_val_statically_known => {
|
||||
let a = args[0].immediate();
|
||||
let builtin = self.context.get_builtin_function("__builtin_constant_p");
|
||||
|
|
|
@ -379,7 +379,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
// Make sure this is actually a SIMD vector.
|
||||
let idx_ty = args[2].layout.ty;
|
||||
let n: u64 = if idx_ty.is_simd()
|
||||
&& matches!(idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), ty::Uint(ty::UintTy::U32))
|
||||
&& matches!(*idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), ty::Uint(ty::UintTy::U32))
|
||||
{
|
||||
idx_ty.simd_size_and_type(bx.cx.tcx).0
|
||||
} else {
|
||||
|
@ -829,6 +829,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
| sym::simd_flog
|
||||
| sym::simd_floor
|
||||
| sym::simd_fma
|
||||
| sym::simd_relaxed_fma
|
||||
| sym::simd_fpow
|
||||
| sym::simd_fpowi
|
||||
| sym::simd_fsin
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
// Some "regular" crates we want to share with rustc
|
||||
extern crate object;
|
||||
extern crate smallvec;
|
||||
// FIXME(antoyo): clippy bug: remove the #[allow] when it's fixed.
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate tempfile;
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
@ -88,7 +90,6 @@ use std::sync::atomic::Ordering;
|
|||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use back::lto::{ThinBuffer, ThinData};
|
||||
use errors::LTONotSupported;
|
||||
use gccjit::{CType, Context, OptimizationLevel};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{TargetInfo, Version};
|
||||
|
@ -109,9 +110,10 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::util::Providers;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{Lto, OptLevel, OutputFilenames};
|
||||
use rustc_session::config::{OptLevel, OutputFilenames};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::fatal_error::FatalError;
|
||||
use rustc_target::spec::RelocModel;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use crate::back::lto::ModuleBuffer;
|
||||
|
@ -141,11 +143,15 @@ impl TargetInfo {
|
|||
false
|
||||
}
|
||||
|
||||
fn supports_128bit_int(&self) -> bool {
|
||||
self.supports_128bit_integers.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
fn supports_target_dependent_type(&self, _typ: CType) -> bool {
|
||||
fn supports_target_dependent_type(&self, typ: CType) -> bool {
|
||||
match typ {
|
||||
CType::UInt128t | CType::Int128t => {
|
||||
if self.supports_128bit_integers.load(Ordering::SeqCst) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -166,10 +172,6 @@ impl LockedTargetInfo {
|
|||
self.info.lock().expect("lock").cpu_supports(feature)
|
||||
}
|
||||
|
||||
fn supports_128bit_int(&self) -> bool {
|
||||
self.info.lock().expect("lock").supports_128bit_int()
|
||||
}
|
||||
|
||||
fn supports_target_dependent_type(&self, typ: CType) -> bool {
|
||||
self.info.lock().expect("lock").supports_target_dependent_type(typ)
|
||||
}
|
||||
|
@ -202,10 +204,6 @@ impl CodegenBackend for GccCodegenBackend {
|
|||
#[cfg(feature = "master")]
|
||||
gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
|
||||
|
||||
if sess.lto() == Lto::Thin {
|
||||
sess.dcx().emit_warn(LTONotSupported {});
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "master"))]
|
||||
{
|
||||
let temp_dir = TempDir::new().expect("cannot create temporary directory");
|
||||
|
@ -297,6 +295,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
|
|||
) -> Self::Module {
|
||||
let mut mods = GccContext {
|
||||
context: Arc::new(SyncContext::new(new_context(tcx))),
|
||||
relocation_model: tcx.sess.relocation_model(),
|
||||
should_combine_object_files: false,
|
||||
temp_dir: None,
|
||||
};
|
||||
|
@ -328,6 +327,9 @@ impl ExtraBackendMethods for GccCodegenBackend {
|
|||
|
||||
pub struct GccContext {
|
||||
context: Arc<SyncContext>,
|
||||
/// This field is needed in order to be able to set the flag -fPIC when necessary when doing
|
||||
/// LTO.
|
||||
relocation_model: RelocModel,
|
||||
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>,
|
||||
|
@ -492,10 +494,10 @@ fn target_features_cfg(
|
|||
sess.target
|
||||
.rust_target_features()
|
||||
.iter()
|
||||
.filter(|(_, gate, _)| gate.in_cfg())
|
||||
.filter_map(|(feature, gate, _)| {
|
||||
.filter(|&&(_, gate, _)| gate.in_cfg())
|
||||
.filter_map(|&(feature, gate, _)| {
|
||||
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
|
||||
Some(*feature)
|
||||
Some(feature)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue