Merge pull request #650 from rust-lang/sync_from_rust_2025_04_17

Sync from rust 2025/04/17
This commit is contained in:
antoyo 2025-04-18 12:43:27 -04:00 committed by GitHub
commit db1a31c243
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
51 changed files with 929 additions and 839 deletions

View file

@ -426,19 +426,6 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> {
run_command_with_env(&command, None, Some(env))?;
maybe_run_command_in_vm(&[&cargo_target_dir.join("track-caller-attribute")], env, args)?;
// FIXME: create a function "display_if_not_quiet" or something along the line.
println!("[AOT] mod_bench");
let mut command = args.config_info.rustc_command_vec();
command.extend_from_slice(&[
&"example/mod_bench.rs",
&"--crate-type",
&"bin",
&"--target",
&args.config_info.target_triple,
]);
run_command_with_env(&command, None, Some(env))?;
// FIXME: the compiled binary is not run.
Ok(())
}
@ -691,25 +678,12 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
// FIXME: create a function "display_if_not_quiet" or something along the line.
println!("[TEST] libcore");
let path = get_sysroot_dir().join("sysroot_src/library/core/tests");
let path = get_sysroot_dir().join("sysroot_src/library/coretests");
let _ = remove_dir_all(path.join("target"));
run_cargo_command(&[&"test"], Some(&path), env, args)?;
Ok(())
}
// echo "[BENCH COMPILE] mod_bench"
//
// COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline"
// COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort"
// COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort"
// COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort"
// COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort"
//
// Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow
// hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3"
// echo "[BENCH RUN] mod_bench"
// hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_*
fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> {
if !args.is_using_gcc_master_branch() {
println!("Not using GCC master branch. Skipping `extended_rand_tests`.");

View file

@ -1,5 +1,6 @@
#![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
#![feature(core_intrinsics, alloc_error_handler, lang_items)]
#![no_std]
#![no_main]
#![allow(internal_features)]
extern crate alloc;
@ -37,8 +38,8 @@ unsafe extern "C" fn _Unwind_Resume() {
core::intrinsics::unreachable();
}
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int {
let world: Box<&str> = Box::new("Hello World!\0");
unsafe {
puts(*world as *const str as *const u8);

View file

@ -58,6 +58,9 @@ trait Receiver {
#[lang = "copy"]
pub trait Copy {}
#[lang = "bikeshed_guaranteed_no_drop"]
pub trait BikeshedGuaranteedNoDrop {}
impl Copy for bool {}
impl Copy for u8 {}
impl Copy for u16 {}
@ -135,6 +138,14 @@ impl Mul for u8 {
}
}
impl Mul for i32 {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self * rhs
}
}
impl Mul for usize {
type Output = Self;
@ -245,6 +256,14 @@ impl Sub for i16 {
}
}
impl Sub for i32 {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self - rhs
}
}
#[lang = "rem"]
pub trait Rem<RHS = Self> {
type Output;
@ -617,40 +636,28 @@ pub union MaybeUninit<T> {
pub mod intrinsics {
#[rustc_intrinsic]
pub fn abort() -> !;
#[rustc_intrinsic]
pub fn size_of<T>() -> usize;
#[rustc_intrinsic]
pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize;
pub unsafe fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
#[rustc_intrinsic]
pub fn min_align_of<T>() -> usize;
#[rustc_intrinsic]
pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize;
pub unsafe fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
#[rustc_intrinsic]
pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize);
pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
#[rustc_intrinsic]
pub unsafe fn transmute<T, U>(_e: T) -> U;
pub unsafe fn transmute<T, U>(e: T) -> U;
#[rustc_intrinsic]
pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32;
pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
#[rustc_intrinsic]
pub fn needs_drop<T: ?::Sized>() -> bool;
#[rustc_intrinsic]
pub fn bitreverse<T>(_x: T) -> T;
pub fn bitreverse<T>(x: T) -> T;
#[rustc_intrinsic]
pub fn bswap<T>(_x: T) -> T;
pub fn bswap<T>(x: T) -> T;
#[rustc_intrinsic]
pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize);
pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
#[rustc_intrinsic]
pub unsafe fn unreachable() -> !;
}
@ -694,7 +701,7 @@ impl<T> Index<usize> for [T] {
}
}
extern {
extern "C" {
type VaListImpl;
}

View file

@ -1,7 +1,7 @@
// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
#![feature(
no_core, unboxed_closures, start, lang_items, never_type, linkage,
no_core, unboxed_closures, lang_items, never_type, linkage,
extern_types, thread_local
)]
#![no_core]
@ -258,13 +258,13 @@ fn main() {
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
extern {
extern "C" {
#[linkage = "weak"]
static ABC: *const u8;
}
{
extern {
extern "C" {
#[linkage = "weak"]
static ABC: *const u8;
}

View file

@ -1,36 +0,0 @@
#![feature(start, core_intrinsics, lang_items)]
#![no_std]
#![allow(internal_features)]
#[link(name = "c")]
extern {}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
core::intrinsics::abort();
}
#[lang="eh_personality"]
fn eh_personality(){}
// Required for rustc_codegen_llvm
#[no_mangle]
unsafe extern "C" fn _Unwind_Resume() {
core::intrinsics::unreachable();
}
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
for i in 2..100_000_000 {
black_box((i + 1) % i);
}
0
}
#[inline(never)]
fn black_box(i: u32) {
if i != 1 {
core::intrinsics::abort();
}
}

View file

@ -7,7 +7,7 @@ use std::arch::x86_64::*;
use std::io::Write;
use std::ops::Coroutine;
extern {
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}

View file

@ -1 +1 @@
d6f5a708104a98199ac0f01a3b6b279a0f7c66d3
0ea98a1365b81f7488073512c850e8ee951a4afd

View file

@ -1,44 +0,0 @@
From af0e237f056fa838c77463381a19b0dc993c0a35 Mon Sep 17 00:00:00 2001
From: None <none@example.com>
Date: Sun, 1 Sep 2024 11:42:17 -0400
Subject: [PATCH] Disable not compiling tests
---
library/core/tests/Cargo.toml | 14 ++++++++++++++
library/core/tests/lib.rs | 1 +
2 files changed, 15 insertions(+)
create mode 100644 library/core/tests/Cargo.toml
diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml
new file mode 100644
index 0000000..ca326ac
--- /dev/null
+++ b/library/core/tests/Cargo.toml
@@ -0,0 +1,14 @@
+[workspace]
+
+[package]
+name = "coretests"
+version = "0.0.0"
+edition = "2021"
+
+[lib]
+name = "coretests"
+path = "lib.rs"
+
+[dependencies]
+rand = { version = "0.8.5", default-features = false }
+rand_xorshift = { version = "0.3.0", default-features = false }
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index a4a7946..ecfe43f 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,4 +1,5 @@
// tidy-alphabetical-start
+#![cfg(test)]
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
#![cfg_attr(test, feature(cfg_match))]
#![feature(alloc_layout_extra)]
--
2.47.1

View file

@ -1,17 +1,17 @@
From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Fri, 3 Dec 2021 12:16:30 +0100
From ec2d0dc77fb484d926b45bb626b0db6a4bb0ab5c Mon Sep 17 00:00:00 2001
From: None <none@example.com>
Date: Thu, 27 Mar 2025 09:20:41 -0400
Subject: [PATCH] Disable long running tests
---
library/core/tests/slice.rs | 2 ++
library/coretests/tests/slice.rs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 8402833..84592e0 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -2462,6 +2462,7 @@ take_tests! {
diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs
index d17e681..fba5cd6 100644
--- a/library/coretests/tests/slice.rs
+++ b/library/coretests/tests/slice.rs
@@ -2486,6 +2486,7 @@ split_off_tests! {
#[cfg(not(miri))] // unused in Miri
const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
@ -19,14 +19,14 @@ index 8402833..84592e0 100644
// can't be a constant due to const mutability rules
#[cfg(not(miri))] // unused in Miri
macro_rules! empty_max_mut {
@@ -2485,6 +2486,7 @@ take_tests! {
(take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
(take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
@@ -2509,6 +2510,7 @@ split_off_tests! {
(split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
(split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
}
+*/
#[test]
fn test_slice_from_ptr_range() {
--
2.26.2.7.g19db9cfb68
2.49.0

View file

@ -1,19 +1,18 @@
From 966beefe08be6045bfcca26079b76a7a80413080 Mon Sep 17 00:00:00 2001
From b2911e732d1bf0e28872495c4c47af1dad3c7911 Mon Sep 17 00:00:00 2001
From: None <none@example.com>
Date: Thu, 28 Sep 2023 17:37:38 -0400
Date: Thu, 27 Mar 2025 14:30:10 -0400
Subject: [PATCH] Disable libstd and libtest dylib
---
library/std/Cargo.toml | 2 +-
library/test/Cargo.toml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
library/std/Cargo.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 5b21355..cb0c49b 100644
index 176da60..c183cdb 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -9,7 +9,7 @@ description = "The Rust Standard Library"
edition = "2021"
@@ -10,7 +10,7 @@ edition = "2024"
autobenches = false
[lib]
-crate-type = ["dylib", "rlib"]
@ -21,3 +20,6 @@ index 5b21355..cb0c49b 100644
[dependencies]
alloc = { path = "../alloc", public = true }
--
2.49.0

View file

@ -1,25 +1,17 @@
From 124a11ce086952a5794d5cfbaa45175809497b81 Mon Sep 17 00:00:00 2001
From 1a8f6b8e39f343959d4d2e6b6957a6d780ac3fc0 Mon Sep 17 00:00:00 2001
From: None <none@example.com>
Date: Sat, 18 Nov 2023 10:50:36 -0500
Subject: [PATCH] [core] Disable portable-simd test
Date: Thu, 27 Mar 2025 14:32:14 -0400
Subject: [PATCH] Disable portable-simd test
---
library/core/tests/lib.rs | 2 --
1 file changed, 2 deletions(-)
library/coretests/tests/lib.rs | 1 -
1 file changed, 1 deletion(-)
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index b71786c..cf484d5 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -87,7 +87,6 @@
#![feature(numfmt)]
#![feature(pattern)]
#![feature(pointer_is_aligned_to)]
-#![feature(portable_simd)]
#![feature(ptr_metadata)]
#![feature(slice_from_ptr_range)]
#![feature(slice_internals)]
@@ -155,7 +154,6 @@ mod pin;
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 79022fe..9223b2f 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -165,7 +165,6 @@ mod pin;
mod pin_macro;
mod ptr;
mod result;
@ -27,4 +19,6 @@ index b71786c..cf484d5 100644
mod slice;
mod str;
mod str_lossy;
-- 2.45.2
--
2.49.0

View file

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2025-01-12"
channel = "nightly-2025-04-17"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -1,6 +1,7 @@
#[cfg(feature = "master")]
use gccjit::FnAttribute;
use gccjit::{ToLValue, ToRValue, Type};
use rustc_abi::{Reg, RegKind};
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
@ -8,16 +9,16 @@ use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf;
#[cfg(feature = "master")]
use rustc_session::config;
use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind};
#[cfg(feature = "master")]
use rustc_target::callconv::Conv;
use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::intrinsic::ArgAbiExt;
use crate::type_of::LayoutGccExt;
impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
impl AbiBuilderMethods for Builder<'_, '_, '_> {
fn get_param(&mut self, index: usize) -> Self::Value {
let func = self.current_func();
let param = func.get_param(index as i32);
@ -136,10 +137,10 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
if cx.sess().opts.optimize == config::OptLevel::No {
return ty;
}
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) {
if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) {
ty = ty.make_restrict()
}
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) {
if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) {
non_null_args.push(arg_index as i32 + 1);
}
ty
@ -238,7 +239,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
}
#[cfg(feature = "master")]
pub fn conv_to_fn_attribute<'gcc>(conv: Conv, _arch: &str) -> Option<FnAttribute<'gcc>> {
pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute<'gcc>> {
// TODO: handle the calling conventions returning None.
let attribute = match conv {
Conv::C
@ -249,20 +250,21 @@ pub fn conv_to_fn_attribute<'gcc>(conv: Conv, _arch: &str) -> Option<FnAttribute
Conv::Cold => return None,
Conv::PreserveMost => return None,
Conv::PreserveAll => return None,
/*Conv::GpuKernel => {
Conv::GpuKernel => {
// TODO(antoyo): remove clippy allow attribute when this is implemented.
#[allow(clippy::if_same_then_else)]
if arch == "amdgpu" {
return None
return None;
} else if arch == "nvptx64" {
return None
return None;
} else {
panic!("Architecture {arch} does not support GpuKernel calling convention");
panic!("Architecture {} does not support GpuKernel calling convention", arch);
}
}*/
}
Conv::AvrInterrupt => return None,
Conv::AvrNonBlockingInterrupt => return None,
Conv::ArmAapcs => return None,
Conv::Msp430Intr => return None,
Conv::PtxKernel => return None,
Conv::X86Fastcall => return None,
Conv::X86Intr => return None,
Conv::X86Stdcall => return None,

View file

@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::OomStrategy;
use rustc_symbol_mangling::mangle_internal_symbol;
use crate::GccContext;
#[cfg(feature = "master")]
@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
panic!("invalid allocator output")
}
};
let from_name = global_fn_name(method.name);
let to_name = default_fn_name(method.name);
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
}
@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen(
create_wrapper_function(
tcx,
context,
"__rust_alloc_error_handler",
alloc_error_handler_name(alloc_error_handler_kind),
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
&[usize, usize],
None,
);
let name = OomStrategy::SYMBOL.to_string();
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
let global = context.new_global(None, GlobalKind::Exported, i8, name);
#[cfg(feature = "master")]
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
@ -80,7 +81,7 @@ pub(crate) unsafe fn codegen(
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 name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE);
let global = context.new_global(None, GlobalKind::Exported, i8, name);
#[cfg(feature = "master")]
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(

View file

@ -632,17 +632,16 @@ pub unsafe fn optimize_thin_module(
Arc::new(SyncContext::new(context))
}
};
let module = ModuleCodegen {
module_llvm: GccContext {
let module = ModuleCodegen::new_regular(
thin_module.name().to_string(),
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,
};
);
/*{
let target = &*module.module_llvm.tm;
let llmod = module.module_llvm.llmod();
@ -710,10 +709,6 @@ pub struct ThinBuffer {
context: Arc<SyncContext>,
}
// TODO: check if this makes sense to make ThinBuffer Send and Sync.
unsafe impl Send for ThinBuffer {}
unsafe impl Sync for ThinBuffer {}
impl ThinBuffer {
pub(crate) fn new(context: &Arc<SyncContext>) -> Self {
Self { context: Arc::clone(context) }

View file

@ -24,19 +24,23 @@ pub(crate) unsafe fn codegen(
{
let context = &module.module_llvm.context;
let module_name = module.name.clone();
let should_combine_object_files = module.module_llvm.should_combine_object_files;
let module_name = Some(&module_name[..]);
// 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(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);
let bc_out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Bitcode,
&module.name,
cgcx.invocation_temp.as_deref(),
);
let obj_out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Object,
&module.name,
cgcx.invocation_temp.as_deref(),
);
if config.bitcode_needed() {
if fat_lto {
@ -117,14 +121,22 @@ pub(crate) unsafe fn codegen(
}
if config.emit_ir {
let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
let out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::LlvmAssembly,
&module.name,
cgcx.invocation_temp.as_deref(),
);
std::fs::write(out, "").expect("write file");
}
if config.emit_asm {
let _timer =
cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name);
let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
let path = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Assembly,
&module.name,
cgcx.invocation_temp.as_deref(),
);
context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str"));
}
@ -238,6 +250,7 @@ pub(crate) unsafe fn codegen(
config.emit_asm,
config.emit_ir,
&cgcx.output_filenames,
cgcx.invocation_temp.as_deref(),
))
}

View file

@ -4,10 +4,10 @@ use std::sync::Arc;
use std::time::Instant;
use gccjit::{CType, Context, FunctionType, GlobalKind};
use rustc_codegen_ssa::ModuleCodegen;
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
use rustc_middle::dep_graph;
use rustc_middle::mir::mono::Linkage;
#[cfg(feature = "master")]
@ -49,9 +49,7 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
Linkage::LinkOnceODR => unimplemented!(),
Linkage::WeakAny => unimplemented!(),
Linkage::WeakODR => unimplemented!(),
Linkage::Appending => unimplemented!(),
Linkage::Internal => GlobalKind::Internal,
Linkage::Private => GlobalKind::Internal,
Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage.
Linkage::Common => unimplemented!(),
}
@ -66,9 +64,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
Linkage::LinkOnceODR => unimplemented!(),
Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce.
Linkage::WeakODR => unimplemented!(),
Linkage::Appending => unimplemented!(),
Linkage::Internal => FunctionType::Internal,
Linkage::Private => FunctionType::Internal,
Linkage::ExternalWeak => unimplemented!(),
Linkage::Common => unimplemented!(),
}
@ -241,16 +237,15 @@ pub fn compile_codegen_unit(
}
}
ModuleCodegen {
name: cgu_name.to_string(),
module_llvm: GccContext {
ModuleCodegen::new_regular(
cgu_name.to_string(),
GccContext {
context: Arc::new(SyncContext::new(context)),
relocation_model: tcx.sess.relocation_model(),
should_combine_object_files: false,
temp_dir: None,
},
kind: ModuleKind::Regular,
}
)
}
(module, cost)

View file

@ -29,7 +29,7 @@ use rustc_middle::ty::layout::{
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_target::abi::call::FnAbi;
use rustc_target::callconv::FnAbi;
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi};
use crate::common::{SignType, TypeReflection, type_is_pointer};
@ -155,14 +155,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
// NOTE: not sure why, but we have the wrong type here.
let int_type = compare_exchange.get_param(2).to_rvalue().get_type();
let src = self.context.new_bitcast(self.location, src, int_type);
self.context.new_call(self.location, compare_exchange, &[
dst,
expected,
src,
weak,
order,
failure_order,
])
self.context.new_call(
self.location,
compare_exchange,
&[dst, expected, src, weak, order, failure_order],
)
}
pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) {
@ -660,6 +657,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
a + b
}
// TODO(antoyo): should we also override the `unchecked_` versions?
fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_sub(a, b)
}
@ -827,31 +825,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
set_rvalue_location(self, self.gcc_not(a))
}
fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
set_rvalue_location(self, self.gcc_add(a, b))
}
fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
set_rvalue_location(self, self.gcc_add(a, b))
}
fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
set_rvalue_location(self, self.gcc_sub(a, b))
}
fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
// TODO(antoyo): should generate poison value?
set_rvalue_location(self, self.gcc_sub(a, b))
}
fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
set_rvalue_location(self, self.gcc_mul(a, b))
}
fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
set_rvalue_location(self, self.gcc_mul(a, b))
}
fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs + rhs)
@ -1008,10 +981,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
OperandValue::Ref(place.val)
} else if place.layout.is_gcc_immediate() {
let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align);
if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
scalar_load_metadata(self, load, scalar);
}
OperandValue::Immediate(self.to_immediate(load, place.layout))
OperandValue::Immediate(
if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
scalar_load_metadata(self, load, scalar);
self.to_immediate_scalar(load, *scalar)
} else {
load
},
)
} else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr {
let b_offset = a.size(self).align_to(b.align(self).abi);
@ -1068,9 +1045,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
let align = dest.val.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align));
let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[
self.const_usize(1),
]);
let next = self.inbounds_gep(
self.backend_type(cg_elem.layout),
current.to_rvalue(),
&[self.const_usize(1)],
);
self.llbb().add_assignment(self.location, current, next);
self.br(header_bb);
@ -1754,7 +1733,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
if scalar.is_bool() {
return self.trunc(val, self.cx().type_i1());
return self.unchecked_utrunc(val, self.cx().type_i1());
}
val
}
@ -2495,9 +2474,5 @@ fn get_maybe_pointer_size(value: RValue<'_>) -> u32 {
#[cfg(not(feature = "master"))]
fn get_maybe_pointer_size(value: RValue<'_>) -> u32 {
let type_ = value.get_type();
if type_.get_pointee().is_some() {
std::mem::size_of::<*const ()>() as _
} else {
type_.get_size()
}
if type_.get_pointee().is_some() { size_of::<*const ()>() as _ } else { type_.get_size() }
}

View file

@ -59,7 +59,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool {
typ.get_pointee().is_some()
}
impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> {
if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
}
@ -141,13 +141,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
fn const_str(&self, s: &str) -> (RValue<'gcc>, RValue<'gcc>) {
let str_global = *self
.const_str_cache
.borrow_mut()
.raw_entry_mut()
.from_key(s)
.or_insert_with(|| (s.to_owned(), self.global_string(s)))
.1;
let mut const_str_cache = self.const_str_cache.borrow_mut();
let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
let g = self.global_string(s);
const_str_cache.insert(s.to_owned(), g);
g
});
let len = s.len();
let cs = self.const_ptrcast(
str_global.get_address(None),
@ -229,7 +228,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
GlobalAlloc::VTable(ty, dyn_ty) => {
let alloc = self
.tcx
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
.global_alloc(self.tcx.vtable_allocation((
ty,
dyn_ty.principal().map(|principal| {
self.tcx.instantiate_bound_regions_with_erased(principal)
}),
)))
.unwrap_memory();
let init = const_alloc_to_gcc(self, alloc);
self.static_addr_of(init, alloc.inner().align, None)
@ -253,7 +257,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
}
fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value {
const_alloc_to_gcc(self, alloc)
}

View file

@ -1,6 +1,7 @@
#[cfg(feature = "master")]
use gccjit::{FnAttribute, VarAttribute, Visibility};
use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type};
use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange};
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
};
@ -14,7 +15,6 @@ use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
use crate::base;
use crate::context::CodegenCx;
@ -131,7 +131,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
// will use load-unaligned instructions instead, and thus avoiding the crash.
//
// We could remove this hack whenever we decide to drop macOS 10.10 support.
if self.tcx.sess.target.options.is_like_osx {
if self.tcx.sess.target.options.is_like_darwin {
// The `inspect` method is okay here because we checked for provenance, and
// because we are doing this access to inspect the final interpreter state
// (not as part of the interpreter execution).
@ -302,9 +302,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
}
pub fn const_alloc_to_gcc<'gcc, 'tcx>(
cx: &CodegenCx<'gcc, 'tcx>,
alloc: ConstAllocation<'tcx>,
pub fn const_alloc_to_gcc<'gcc>(
cx: &CodegenCx<'gcc, '_>,
alloc: ConstAllocation<'_>,
) -> RValue<'gcc> {
let alloc = alloc.inner();
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
@ -364,6 +364,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(
llvals.push(cx.const_bytes(bytes));
}
// FIXME(bjorn3) avoid wrapping in a struct when there is only a single element.
cx.const_struct(&llvals, true)
}

View file

@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell};
use gccjit::{
Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type,
};
use rustc_abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::errors as ssa_errors;
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods};
@ -14,11 +15,10 @@ use rustc_middle::ty::layout::{
FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
LayoutOfHelpers,
};
use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::source_map::respan;
use rustc_span::{DUMMY_SP, Span};
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_target::spec::{
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi,
};
@ -92,7 +92,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
/// Cache generated vtables
pub vtables:
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
// TODO(antoyo): improve the SSA API to not require those.
/// Mapping from function pointer type to indexes of on stack parameters.
@ -215,33 +215,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let bool_type = context.new_type::<bool>();
let mut functions = FxHashMap::default();
let builtins = [
"__builtin_unreachable",
"abort",
"__builtin_expect", /*"__builtin_expect_with_probability",*/
"__builtin_constant_p",
"__builtin_add_overflow",
"__builtin_mul_overflow",
"__builtin_saddll_overflow",
/*"__builtin_sadd_overflow",*/
"__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/
"__builtin_ssubll_overflow",
/*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow",
"__builtin_uaddll_overflow",
"__builtin_uadd_overflow",
"__builtin_umulll_overflow",
"__builtin_umul_overflow",
"__builtin_usubll_overflow",
"__builtin_usub_overflow",
"__builtin_powif",
"__builtin_powi",
"fabsf",
"fabs",
"copysignf",
"copysign",
"nearbyintf",
"nearbyint",
];
let builtins = ["abort"];
for builtin in builtins.iter() {
functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
@ -403,7 +377,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn vtables(
&self,
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
&self.vtables
}
@ -519,7 +493,6 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
} else {
// If the symbol already exists, it is an error: for example, the user wrote
// #[no_mangle] extern "C" fn main(..) {..}
// instead of #[start]
None
}
}

View file

@ -1,17 +1,17 @@
use std::ops::Range;
use std::sync::Arc;
use gccjit::{Location, RValue};
use rustc_abi::Size;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
use rustc_data_structures::sync::Lrc;
use rustc_index::bit_set::DenseBitSet;
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::{self, Body, SourceScope};
use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty};
use rustc_session::config::DebugInfo;
use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol};
use rustc_target::abi::Size;
use rustc_target::abi::call::FnAbi;
use rustc_target::callconv::FnAbi;
use crate::builder::Builder;
use crate::context::CodegenCx;
@ -113,15 +113,15 @@ fn make_mir_scope<'gcc, 'tcx>(
let scope_data = &mir.source_scopes[scope];
let parent_scope = if let Some(parent) = scope_data.parent_scope {
make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent);
debug_context.scopes[parent].unwrap()
debug_context.scopes[parent]
} else {
// The root is the function itself.
let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
debug_context.scopes[scope] = Some(DebugScope {
debug_context.scopes[scope] = DebugScope {
file_start_pos: file.start_pos,
file_end_pos: file.end_position(),
..debug_context.scopes[scope].unwrap()
});
..debug_context.scopes[scope]
};
instantiated.insert(scope);
return;
};
@ -130,7 +130,7 @@ fn make_mir_scope<'gcc, 'tcx>(
if !vars.contains(scope) && scope_data.inlined.is_none() {
// Do not create a DIScope if there are no variables defined in this
// MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
debug_context.scopes[scope] = Some(parent_scope);
debug_context.scopes[scope] = parent_scope;
instantiated.insert(scope);
return;
}
@ -157,12 +157,12 @@ fn make_mir_scope<'gcc, 'tcx>(
// TODO(tempdragon): dbg_scope: Add support for scope extension here.
inlined_at.or(p_inlined_at);
debug_context.scopes[scope] = Some(DebugScope {
debug_context.scopes[scope] = DebugScope {
dbg_scope,
inlined_at,
file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_position(),
});
};
instantiated.insert(scope);
}
@ -172,7 +172,7 @@ fn make_mir_scope<'gcc, 'tcx>(
// `lookup_char_pos` return the right information instead.
pub struct DebugLoc {
/// Information about the original source file.
pub file: Lrc<SourceFile>,
pub file: Arc<SourceFile>,
/// The (1-based) line number.
pub line: u32,
/// The (1-based) column number.
@ -214,7 +214,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn create_vtable_debuginfo(
&self,
_ty: Ty<'tcx>,
_trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
_trait_ref: Option<ExistentialTraitRef<'tcx>>,
_vtable: Self::Value,
) {
// TODO(antoyo)
@ -232,12 +232,12 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
// Initialize fn debug context (including scopes).
let empty_scope = Some(DebugScope {
let empty_scope = DebugScope {
dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)),
inlined_at: None,
file_start_pos: BytePos(0),
file_end_pos: BytePos(0),
});
};
let mut fn_debug_context = FunctionDebugContext {
scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()),
inlined_function_scopes: Default::default(),

View file

@ -4,7 +4,7 @@ use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type};
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::abi::call::FnAbi;
use rustc_target::callconv::FnAbi;
use crate::abi::{FnAbiGcc, FnAbiGccExt};
use crate::context::CodegenCx;

View file

@ -1,10 +1,8 @@
use std::iter::FromIterator;
#[cfg(feature = "master")]
use gccjit::Context;
use rustc_codegen_ssa::codegen_attrs::check_tied_features;
use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unord::UnordSet;
use rustc_session::Session;
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
@ -45,18 +43,12 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
let known_features = sess.target.rust_target_features();
let mut featsmap = FxHashMap::default();
// Ensure that all ABI-required features are enabled, and the ABI-forbidden ones
// are disabled.
let abi_feature_constraints = sess.target.abi_required_features();
let abi_incompatible_set =
FxHashSet::from_iter(abi_feature_constraints.incompatible.iter().copied());
// Compute implied features
let mut all_rust_features = vec![];
for feature in sess.opts.cg.target_feature.split(',') {
if let Some(feature) = feature.strip_prefix('+') {
all_rust_features.extend(
UnordSet::from(sess.target.implied_target_features(std::iter::once(feature)))
UnordSet::from(sess.target.implied_target_features(feature))
.to_sorted_stable_ord()
.iter()
.map(|&&s| (true, s)),
@ -117,51 +109,11 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
}
}
// Ensure that the features we enable/disable are compatible with the ABI.
if enable {
if abi_incompatible_set.contains(feature) {
sess.dcx().emit_warn(ForbiddenCTargetFeature {
feature,
enabled: "enabled",
reason: "this feature is incompatible with the target ABI",
});
}
} else {
// FIXME: we have to request implied features here since
// negative features do not handle implied features above.
for &required in abi_feature_constraints.required.iter() {
let implied = sess.target.implied_target_features(std::iter::once(required));
if implied.contains(feature) {
sess.dcx().emit_warn(ForbiddenCTargetFeature {
feature,
enabled: "disabled",
reason: "this feature is required by the target ABI",
});
}
}
}
// FIXME(nagisa): figure out how to not allocate a full hashset here.
featsmap.insert(feature, enable);
}
}
// To be sure the ABI-relevant features are all in the right state, we explicitly
// (un)set them here. This means if the target spec sets those features wrong,
// we will silently correct them rather than silently producing wrong code.
// (The target sanity check tries to catch this, but we can't know which features are
// enabled in GCC by default so we can't be fully sure about that check.)
// We add these at the beginning of the list so that `-Ctarget-features` can
// still override it... that's unsound, but more compatible with past behavior.
all_rust_features.splice(
0..0,
abi_feature_constraints
.required
.iter()
.map(|&f| (true, f))
.chain(abi_feature_constraints.incompatible.iter().map(|&f| (false, f))),
);
// Translate this into GCC features.
let feats =
all_rust_features.iter().flat_map(|&(enable, feature)| {

View file

@ -3,12 +3,11 @@
//! 128-bit integers on 32-bit platforms and thus require to be handled manually.
use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp};
use rustc_abi::{Endian, ExternAbi};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp};
use rustc_middle::ty::{self, Ty};
use rustc_target::abi::Endian;
use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
use rustc_target::spec;
use rustc_target::callconv::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
use crate::builder::{Builder, ToGccComp};
use crate::common::{SignType, TypeReflection};
@ -322,36 +321,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
},
}
} else {
match new_kind {
Int(I128) | Uint(U128) => {
let func_name = match oop {
OverflowOp::Add => match new_kind {
Int(I128) => "__rust_i128_addo",
Uint(U128) => "__rust_u128_addo",
_ => unreachable!(),
},
OverflowOp::Sub => match new_kind {
Int(I128) => "__rust_i128_subo",
Uint(U128) => "__rust_u128_subo",
_ => unreachable!(),
},
OverflowOp::Mul => match new_kind {
Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead?
Uint(U128) => "__rust_u128_mulo",
_ => unreachable!(),
},
};
return self.operation_with_overflow(func_name, lhs, rhs);
}
_ => match oop {
OverflowOp::Mul => match new_kind {
Int(I32) => "__mulosi4",
Int(I64) => "__mulodi4",
_ => unreachable!(),
},
_ => unimplemented!("overflow operation for {:?}", new_kind),
let (func_name, width) = match oop {
OverflowOp::Add => match new_kind {
Int(I128) => ("__rust_i128_addo", 128),
Uint(U128) => ("__rust_u128_addo", 128),
_ => unreachable!(),
},
}
OverflowOp::Sub => match new_kind {
Int(I128) => ("__rust_i128_subo", 128),
Uint(U128) => ("__rust_u128_subo", 128),
_ => unreachable!(),
},
OverflowOp::Mul => match new_kind {
Int(I32) => ("__mulosi4", 32),
Int(I64) => ("__mulodi4", 64),
Int(I128) => ("__rust_i128_mulo", 128), // TODO(antoyo): use __muloti4d instead?
Uint(U128) => ("__rust_u128_mulo", 128),
_ => unreachable!(),
},
};
return self.operation_with_overflow(func_name, lhs, rhs, width);
};
let intrinsic = self.context.get_builtin_function(name);
@ -364,80 +353,96 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
(res.dereference(self.location).to_rvalue(), overflow)
}
/// Non-`__builtin_*` overflow operations with a `fn(T, T, &mut i32) -> T` signature.
pub fn operation_with_overflow(
&self,
func_name: &str,
lhs: RValue<'gcc>,
rhs: RValue<'gcc>,
width: u64,
) -> (RValue<'gcc>, RValue<'gcc>) {
let a_type = lhs.get_type();
let b_type = rhs.get_type();
debug_assert!(a_type.dyncast_array().is_some());
debug_assert!(b_type.dyncast_array().is_some());
let overflow_type = self.i32_type;
let overflow_param_type = overflow_type.make_pointer();
let res_type = a_type;
let overflow_value =
self.current_func().new_local(self.location, overflow_type, "overflow");
let overflow_addr = overflow_value.get_address(self.location);
let param_a = self.context.new_parameter(self.location, a_type, "a");
let param_b = self.context.new_parameter(self.location, b_type, "b");
let result_field = self.context.new_field(self.location, a_type, "result");
let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow");
let param_overflow =
self.context.new_parameter(self.location, overflow_param_type, "overflow");
let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
let a_elem_type = a_type.dyncast_array().expect("non-array a value");
debug_assert!(a_elem_type.is_integral());
let res_ty = match width {
32 => self.tcx.types.i32,
64 => self.tcx.types.i64,
128 => self.tcx.types.i128,
_ => unreachable!("unexpected integer size"),
};
let layout = self
.tcx
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty))
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(res_ty))
.unwrap();
let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
let mut fn_abi = FnAbi {
args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
args: vec![arg_abi.clone(), arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
ret: arg_abi,
c_variadic: false,
fixed_count: 2,
fixed_count: 3,
conv: Conv::C,
can_unwind: false,
};
fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap();
fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false });
let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
let call = if ret_indirect {
let res_value = self.current_func().new_local(self.location, res_type, "result_value");
let res_addr = res_value.get_address(self.location);
let res_param_type = res_type.make_pointer();
let param_res = self.context.new_parameter(self.location, res_param_type, "result");
let return_type = self
.context
.new_struct_type(self.location, "result_overflow", &[result_field, overflow_field]);
let result = if indirect {
let return_value =
self.current_func().new_local(self.location, return_type.as_type(), "return_value");
let return_param_type = return_type.as_type().make_pointer();
let return_param =
self.context.new_parameter(self.location, return_param_type, "return_value");
let func = self.context.new_function(
self.location,
FunctionType::Extern,
self.type_void(),
&[return_param, param_a, param_b],
&[param_res, param_a, param_b, param_overflow],
func_name,
false,
);
self.llbb().add_eval(
self.location,
self.context.new_call(self.location, func, &[
return_value.get_address(self.location),
lhs,
rhs,
]),
);
return_value.to_rvalue()
let _void =
self.context.new_call(self.location, func, &[res_addr, lhs, rhs, overflow_addr]);
res_value.to_rvalue()
} else {
let func = self.context.new_function(
self.location,
FunctionType::Extern,
return_type.as_type(),
&[param_a, param_b],
res_type,
&[param_a, param_b, param_overflow],
func_name,
false,
);
self.context.new_call(self.location, func, &[lhs, rhs])
self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr])
};
let overflow = result.access_field(self.location, overflow_field);
let int_result = result.access_field(self.location, result_field);
(int_result, overflow)
// NOTE: we must assign the result of the operation to a variable at this point to make
// sure it will be evaluated by libgccjit now.
// Otherwise, it will only be evaluated when the rvalue for the call is used somewhere else
// and overflow_value will not be initialized at the correct point in the program.
let result = self.current_func().new_local(self.location, res_type, "result");
self.block.add_assignment(self.location, result, call);
(
result.to_rvalue(),
self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue(),
)
}
pub fn gcc_icmp(
@ -869,6 +874,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let value_type = value.get_type();
if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type)
{
// TODO: use self.location.
self.context.new_cast(None, value, dest_typ)
} else if self.is_native_int_type_or_bool(dest_typ) {
self.context.new_cast(None, self.low(value), dest_typ)
@ -909,6 +915,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let name_suffix = match self.type_kind(dest_typ) {
TypeKind::Float => "tisf",
TypeKind::Double => "tidf",
TypeKind::FP128 => "tixf",
kind => panic!("cannot cast a non-native integer to type {:?}", kind),
};
let sign = if signed { "" } else { "un" };

View file

@ -1,11 +1,90 @@
use std::borrow::Cow;
use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue};
use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type};
use rustc_codegen_ssa::traits::BuilderMethods;
use crate::builder::Builder;
use crate::context::CodegenCx;
fn encode_key_128_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let field1 = builder.context.new_field(None, builder.u32_type, "field1");
let field2 = builder.context.new_field(None, m128i, "field2");
let field3 = builder.context.new_field(None, m128i, "field3");
let field4 = builder.context.new_field(None, m128i, "field4");
let field5 = builder.context.new_field(None, m128i, "field5");
let field6 = builder.context.new_field(None, m128i, "field6");
let field7 = builder.context.new_field(None, m128i, "field7");
let encode_type = builder.context.new_struct_type(
None,
"EncodeKey128Output",
&[field1, field2, field3, field4, field5, field6, field7],
);
#[cfg(feature = "master")]
encode_type.as_type().set_packed();
(encode_type.as_type(), field1, field2)
}
fn encode_key_256_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let field1 = builder.context.new_field(None, builder.u32_type, "field1");
let field2 = builder.context.new_field(None, m128i, "field2");
let field3 = builder.context.new_field(None, m128i, "field3");
let field4 = builder.context.new_field(None, m128i, "field4");
let field5 = builder.context.new_field(None, m128i, "field5");
let field6 = builder.context.new_field(None, m128i, "field6");
let field7 = builder.context.new_field(None, m128i, "field7");
let field8 = builder.context.new_field(None, m128i, "field8");
let encode_type = builder.context.new_struct_type(
None,
"EncodeKey256Output",
&[field1, field2, field3, field4, field5, field6, field7, field8],
);
#[cfg(feature = "master")]
encode_type.as_type().set_packed();
(encode_type.as_type(), field1, field2)
}
fn aes_output_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let field1 = builder.context.new_field(None, builder.u8_type, "field1");
let field2 = builder.context.new_field(None, m128i, "field2");
let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]);
let typ = aes_output_type.as_type();
#[cfg(feature = "master")]
typ.set_packed();
(typ, field1, field2)
}
fn wide_aes_output_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let field1 = builder.context.new_field(None, builder.u8_type, "field1");
let field2 = builder.context.new_field(None, m128i, "field2");
let field3 = builder.context.new_field(None, m128i, "field3");
let field4 = builder.context.new_field(None, m128i, "field4");
let field5 = builder.context.new_field(None, m128i, "field5");
let field6 = builder.context.new_field(None, m128i, "field6");
let field7 = builder.context.new_field(None, m128i, "field7");
let field8 = builder.context.new_field(None, m128i, "field8");
let field9 = builder.context.new_field(None, m128i, "field9");
let aes_output_type = builder.context.new_struct_type(
None,
"WideAesOutput",
&[field1, field2, field3, field4, field5, field6, field7, field8, field9],
);
#[cfg(feature = "master")]
aes_output_type.as_type().set_packed();
(aes_output_type.as_type(), field1, field2)
}
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
pub fn adjust_function<'gcc>(
context: &'gcc Context<'gcc>,
@ -503,6 +582,72 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
let arg4 = builder.context.new_rvalue_from_int(arg4_type, -1);
args = vec![a, b, c, arg4, new_args[3]].into();
}
"__builtin_ia32_encodekey128_u32" => {
let mut new_args = args.to_vec();
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let array_type = builder.context.new_array_type(None, m128i, 6);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
args = new_args.into();
}
"__builtin_ia32_encodekey256_u32" => {
let mut new_args = args.to_vec();
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let array_type = builder.context.new_array_type(None, m128i, 7);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
args = new_args.into();
}
"__builtin_ia32_aesenc128kl_u8"
| "__builtin_ia32_aesdec128kl_u8"
| "__builtin_ia32_aesenc256kl_u8"
| "__builtin_ia32_aesdec256kl_u8" => {
let mut new_args = vec![];
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let result = builder.current_func().new_local(None, m128i, "result");
new_args.push(result.get_address(None));
new_args.extend(args.to_vec());
args = new_args.into();
}
"__builtin_ia32_aesencwide128kl_u8"
| "__builtin_ia32_aesdecwide128kl_u8"
| "__builtin_ia32_aesencwide256kl_u8"
| "__builtin_ia32_aesdecwide256kl_u8" => {
let mut new_args = vec![];
let mut old_args = args.to_vec();
let handle = old_args.swap_remove(0); // Called __P in GCC.
let first_value = old_args.swap_remove(0);
let element_type = first_value.get_type();
let array_type = builder.context.new_array_type(None, element_type, 8);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
let array = builder.current_func().new_local(None, array_type, "array");
let input = builder.context.new_array_constructor(
None,
array_type,
&[
first_value,
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
],
);
builder.llbb().add_assignment(None, array, input);
let input_ptr = array.get_address(None);
let arg2_type = gcc_func.get_param_type(1);
let input_ptr = builder.context.new_cast(None, input_ptr, arg2_type);
new_args.push(input_ptr);
new_args.push(handle);
args = new_args.into();
}
_ => (),
}
} else {
@ -659,11 +804,12 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
let field2 = builder.context.new_field(None, args[1].get_type(), "carryResult");
let struct_type =
builder.context.new_struct_type(None, "addcarryResult", &[field1, field2]);
return_value =
builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[
return_value,
last_arg.dereference(None).to_rvalue(),
]);
return_value = builder.context.new_struct_constructor(
None,
struct_type.as_type(),
None,
&[return_value, last_arg.dereference(None).to_rvalue()],
);
}
}
"__builtin_ia32_stmxcsr" => {
@ -688,16 +834,107 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
let field2 = builder.context.new_field(None, return_value.get_type(), "success");
let struct_type =
builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]);
return_value =
builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[
random_number,
success_variable.to_rvalue(),
]);
return_value = builder.context.new_struct_constructor(
None,
struct_type.as_type(),
None,
&[random_number, success_variable.to_rvalue()],
);
}
"fma" => {
let f16_type = builder.context.new_c_type(CType::Float16);
return_value = builder.context.new_cast(None, return_value, f16_type);
}
"__builtin_ia32_encodekey128_u32" => {
// The builtin __builtin_ia32_encodekey128_u32 writes the result in its pointer argument while
// llvm.x86.encodekey128 returns a value.
// We added a result pointer argument and now need to assign its value to the return_value expected by
// the LLVM intrinsic.
let (encode_type, field1, field2) = encode_key_128_type(builder);
let result = builder.current_func().new_local(None, encode_type, "result");
let field1 = result.access_field(None, field1);
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 6);
let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
builder.llbb().add_assignment(
None,
field2_ptr.dereference(None),
ptr.dereference(None),
);
return_value = result.to_rvalue();
}
"__builtin_ia32_encodekey256_u32" => {
// The builtin __builtin_ia32_encodekey256_u32 writes the result in its pointer argument while
// llvm.x86.encodekey256 returns a value.
// We added a result pointer argument and now need to assign its value to the return_value expected by
// the LLVM intrinsic.
let (encode_type, field1, field2) = encode_key_256_type(builder);
let result = builder.current_func().new_local(None, encode_type, "result");
let field1 = result.access_field(None, field1);
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 7);
let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
builder.llbb().add_assignment(
None,
field2_ptr.dereference(None),
ptr.dereference(None),
);
return_value = result.to_rvalue();
}
"__builtin_ia32_aesdec128kl_u8"
| "__builtin_ia32_aesenc128kl_u8"
| "__builtin_ia32_aesdec256kl_u8"
| "__builtin_ia32_aesenc256kl_u8" => {
// The builtin for aesdec/aesenc writes the result in its pointer argument while
// llvm.x86.aesdec128kl returns a value.
// We added a result pointer argument and now need to assign its value to the return_value expected by
// the LLVM intrinsic.
let (aes_output_type, field1, field2) = aes_output_type(builder);
let result = builder.current_func().new_local(None, aes_output_type, "result");
let field1 = result.access_field(None, field1);
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let ptr = builder.context.new_cast(
None,
args[0],
field2.to_rvalue().get_type().make_pointer(),
);
builder.llbb().add_assignment(None, field2, ptr.dereference(None));
return_value = result.to_rvalue();
}
"__builtin_ia32_aesencwide128kl_u8"
| "__builtin_ia32_aesdecwide128kl_u8"
| "__builtin_ia32_aesencwide256kl_u8"
| "__builtin_ia32_aesdecwide256kl_u8" => {
// The builtin for aesdecwide/aesencwide writes the result in its pointer argument while
// llvm.x86.aesencwide128kl returns a value.
// We added a result pointer argument and now need to assign its value to the return_value expected by
// the LLVM intrinsic.
let (aes_output_type, field1, field2) = wide_aes_output_type(builder);
let result = builder.current_func().new_local(None, aes_output_type, "result");
let field1 = result.access_field(None, field1);
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 8);
let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
builder.llbb().add_assignment(
None,
field2_ptr.dereference(None),
ptr.dereference(None),
);
return_value = result.to_rvalue();
}
_ => (),
}
@ -1282,6 +1519,16 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.x86.avx512fp16.mask.vfmadd.cph.256" => "__builtin_ia32_vfmaddcph256_mask3",
"llvm.x86.avx512fp16.mask.vfcmadd.cph.128" => "__builtin_ia32_vfcmaddcph128_mask3",
"llvm.x86.avx512fp16.mask.vfmadd.cph.128" => "__builtin_ia32_vfmaddcph128_mask3",
"llvm.x86.encodekey128" => "__builtin_ia32_encodekey128_u32",
"llvm.x86.encodekey256" => "__builtin_ia32_encodekey256_u32",
"llvm.x86.aesenc128kl" => "__builtin_ia32_aesenc128kl_u8",
"llvm.x86.aesdec128kl" => "__builtin_ia32_aesdec128kl_u8",
"llvm.x86.aesenc256kl" => "__builtin_ia32_aesenc256kl_u8",
"llvm.x86.aesdec256kl" => "__builtin_ia32_aesdec256kl_u8",
"llvm.x86.aesencwide128kl" => "__builtin_ia32_aesencwide128kl_u8",
"llvm.x86.aesdecwide128kl" => "__builtin_ia32_aesdecwide128kl_u8",
"llvm.x86.aesencwide256kl" => "__builtin_ia32_aesencwide256kl_u8",
"llvm.x86.aesdecwide256kl" => "__builtin_ia32_aesdecwide256kl_u8",
// TODO: support the tile builtins:
"llvm.x86.ldtilecfg" => "__builtin_trap",

View file

@ -7,6 +7,9 @@ use std::iter;
#[cfg(feature = "master")]
use gccjit::FunctionType;
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
#[cfg(feature = "master")]
use rustc_abi::ExternAbi;
use rustc_abi::{BackendRepr, HasDataLayout};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::common::IntPredicate;
@ -25,11 +28,8 @@ 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;
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
use rustc_target::spec::PanicStrategy;
#[cfg(feature = "master")]
use rustc_target::spec::abi::Abi;
#[cfg(feature = "master")]
use crate::abi::FnAbiGccExt;
@ -78,20 +78,18 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
sym::maxnumf64 => "fmax",
sym::copysignf32 => "copysignf",
sym::copysignf64 => "copysign",
sym::copysignf128 => "copysignl",
sym::floorf32 => "floorf",
sym::floorf64 => "floor",
sym::ceilf32 => "ceilf",
sym::ceilf64 => "ceil",
sym::truncf32 => "truncf",
sym::truncf64 => "trunc",
sym::rintf32 => "rintf",
sym::rintf64 => "rint",
sym::nearbyintf32 => "nearbyintf",
sym::nearbyintf64 => "nearbyint",
// We match the LLVM backend and lower this to `rint`.
sym::round_ties_even_f32 => "rintf",
sym::round_ties_even_f64 => "rint",
sym::roundf32 => "roundf",
sym::roundf64 => "round",
sym::roundevenf32 => "roundevenf",
sym::roundevenf64 => "roundeven",
sym::abort => "abort",
_ => return None,
};
@ -181,14 +179,19 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
sym::volatile_load | sym::unaligned_volatile_load => {
let tp_ty = fn_args.type_at(0);
let ptr = args[0].immediate();
let layout = self.layout_of(tp_ty);
let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode {
let gcc_ty = ty.gcc_type(self);
self.volatile_load(gcc_ty, ptr)
} else {
self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
self.volatile_load(layout.gcc_type(self), ptr)
};
// TODO(antoyo): set alignment.
self.to_immediate(load, self.layout_of(tp_ty))
if let BackendRepr::Scalar(scalar) = layout.backend_repr {
self.to_immediate_scalar(load, scalar)
} else {
load
}
}
sym::volatile_store => {
let dst = args[0].deref(self.cx());
@ -310,7 +313,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
let layout = self.layout_of(tp_ty).layout;
let _use_integer_compare = match layout.backend_repr() {
Scalar(_) | ScalarPair(_, _) => true,
Uninhabited | Vector { .. } => false,
SimdVector { .. } => false,
Memory { .. } => {
// For rusty ABIs, small aggregates are actually passed
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
@ -1001,7 +1004,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
128 => "__rust_i128_addo",
_ => unreachable!(),
};
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
let (int_result, overflow) =
self.operation_with_overflow(func_name, lhs, rhs, width);
self.llbb().add_assignment(self.location, res, int_result);
overflow
};
@ -1071,7 +1075,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
128 => "__rust_i128_subo",
_ => unreachable!(),
};
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
let (int_result, overflow) =
self.operation_with_overflow(func_name, lhs, rhs, width);
self.llbb().add_assignment(self.location, res, int_result);
overflow
};
@ -1236,7 +1241,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(
tcx.types.unit,
false,
rustc_hir::Safety::Unsafe,
Abi::Rust,
ExternAbi::Rust,
)),
);
// `unsafe fn(*mut i8, *mut i8) -> ()`
@ -1247,7 +1252,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(
tcx.types.unit,
false,
rustc_hir::Safety::Unsafe,
Abi::Rust,
ExternAbi::Rust,
)),
);
// `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
@ -1256,7 +1261,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(
tcx.types.i32,
false,
rustc_hir::Safety::Unsafe,
Abi::Rust,
ExternAbi::Rust,
));
let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen);
cx.rust_try_fn.set(Some(rust_try));

View file

@ -3,6 +3,7 @@ use std::iter::FromIterator;
use gccjit::{BinaryOp, RValue, ToRValue, Type};
#[cfg(feature = "master")]
use gccjit::{ComparisonOp, UnaryOp};
use rustc_abi::{Align, Size};
use rustc_codegen_ssa::base::compare_simd_types;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
#[cfg(feature = "master")]
@ -17,7 +18,6 @@ use rustc_middle::mir::BinOp;
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{self, Ty};
use rustc_span::{Span, Symbol, sym};
use rustc_target::abi::{Align, Size};
use crate::builder::Builder;
#[cfg(not(feature = "master"))]
@ -62,11 +62,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let arg_tys = sig.inputs();
if name == sym::simd_select_bitmask {
require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument {
span,
name,
ty: arg_tys[1]
});
require_simd!(
arg_tys[1],
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
);
let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
let expected_int_bits = (len.max(8) - 1).next_power_of_two();
@ -140,14 +139,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
});
require!(
in_len == out_len,
InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
);
require!(
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty }
@ -269,23 +271,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let lo_nibble =
bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &lo_nibble_elements);
let mask = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &vec![
bx.context
.new_rvalue_from_int(
bx.u8_type, 0x0f
);
byte_vector_type_size
as _
]);
let mask = bx.context.new_rvalue_from_vector(
None,
long_byte_vector_type,
&vec![bx.context.new_rvalue_from_int(bx.u8_type, 0x0f); byte_vector_type_size as _],
);
let four_vec = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &vec![
bx.context
.new_rvalue_from_int(
bx.u8_type, 4
);
byte_vector_type_size
as _
]);
let four_vec = bx.context.new_rvalue_from_vector(
None,
long_byte_vector_type,
&vec![bx.context.new_rvalue_from_int(bx.u8_type, 4); byte_vector_type_size as _],
);
// Step 2: Byte-swap the input.
let swapped = simd_bswap(bx, args[0].immediate());
@ -388,21 +384,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!(out_len == n, InvalidMonomorphization::ReturnLength {
span,
name,
in_len: n,
ret_ty,
out_len
});
require!(in_elem == out_ty, InvalidMonomorphization::ReturnElement {
span,
name,
in_elem,
in_ty,
ret_ty,
out_ty
});
require!(
out_len == n,
InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len }
);
require!(
in_elem == out_ty,
InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
);
let vector = args[2].immediate();
@ -410,14 +399,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
}
#[cfg(feature = "master")]
if name == sym::simd_insert {
require!(in_elem == arg_tys[2], InvalidMonomorphization::InsertedType {
span,
name,
in_elem,
in_ty,
out_ty: arg_tys[2]
});
if name == sym::simd_insert || name == sym::simd_insert_dyn {
require!(
in_elem == arg_tys[2],
InvalidMonomorphization::InsertedType {
span,
name,
in_elem,
in_ty,
out_ty: arg_tys[2]
}
);
// TODO(antoyo): For simd_insert, check if the index is a constant of the correct size.
let vector = args[0].immediate();
let index = args[1].immediate();
let value = args[2].immediate();
@ -430,33 +424,29 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
}
#[cfg(feature = "master")]
if name == sym::simd_extract {
require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType {
span,
name,
in_elem,
in_ty,
ret_ty
});
if name == sym::simd_extract || name == sym::simd_extract_dyn {
require!(
ret_ty == in_elem,
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
);
// TODO(antoyo): For simd_extract, check if the index is a constant of the correct size.
let vector = args[0].immediate();
return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
let index = args[1].immediate();
return Ok(bx.context.new_vector_access(None, vector, index).to_rvalue());
}
if name == sym::simd_select {
let m_elem_ty = in_elem;
let m_len = in_len;
require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument {
span,
name,
ty: arg_tys[1]
});
require_simd!(
arg_tys[1],
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
);
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
require!(m_len == v_len, InvalidMonomorphization::MismatchedLengths {
span,
name,
m_len,
v_len
});
require!(
m_len == v_len,
InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
);
match *m_elem_ty.kind() {
ty::Int(_) => {}
_ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }),
@ -468,25 +458,27 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
});
require!(
in_len == out_len,
InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
);
match *in_elem.kind() {
ty::RawPtr(p_ty, _) => {
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
});
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
span,
name,
ty: in_elem
});
require!(
metadata.is_unit(),
InvalidMonomorphization::CastWidePointer { span, name, ty: in_elem }
);
}
_ => {
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem })
@ -497,11 +489,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
});
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
span,
name,
ty: out_elem
});
require!(
metadata.is_unit(),
InvalidMonomorphization::CastWidePointer { span, name, ty: out_elem }
);
}
_ => {
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem })
@ -524,14 +515,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
});
require!(
in_len == out_len,
InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
);
match *in_elem.kind() {
ty::RawPtr(_, _) => {}
@ -560,14 +554,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
});
require!(
in_len == out_len,
InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
);
match *in_elem.kind() {
ty::Uint(ty::UintTy::Usize) => {}
@ -596,14 +593,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
if name == sym::simd_cast || name == sym::simd_as {
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
});
require!(
in_len == out_len,
InvalidMonomorphization::ReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
);
// casting cares about nominal type, not just structural type
if in_elem == out_elem {
return Ok(args[0].immediate());
@ -629,14 +629,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
match (in_style, out_style) {
(Style::Unsupported, Style::Unsupported) => {
require!(false, InvalidMonomorphization::UnsupportedCast {
span,
name,
in_ty,
in_elem,
ret_ty,
out_elem
});
require!(
false,
InvalidMonomorphization::UnsupportedCast {
span,
name,
in_ty,
in_elem,
ret_ty,
out_elem
}
);
}
_ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)),
}
@ -773,8 +776,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
sym::simd_floor => "floor",
sym::simd_fma => "fma",
sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary
sym::simd_fpowi => "__builtin_powi",
sym::simd_fpow => "pow",
sym::simd_fsin => "sin",
sym::simd_fsqrt => "sqrt",
sym::simd_round => "round",
@ -789,24 +790,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
let mut vector_elements = vec![];
for i in 0..in_len {
let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64);
// we have to treat fpowi specially, since fpowi's second argument is always an i32
let mut arguments = vec![];
if name == sym::simd_fpowi {
arguments = vec![
bx.extract_element(args[0].immediate(), index).to_rvalue(),
args[1].immediate(),
];
} else {
for arg in args {
let mut element = bx.extract_element(arg.immediate(), index).to_rvalue();
// FIXME: it would probably be better to not have casts here and use the proper
// instructions.
if let Some(typ) = cast_type {
element = bx.context.new_cast(None, element, typ);
}
arguments.push(element);
for arg in args {
let mut element = bx.extract_element(arg.immediate(), index).to_rvalue();
// FIXME: it would probably be better to not have casts here and use the proper
// instructions.
if let Some(typ) = cast_type {
element = bx.context.new_cast(None, element, typ);
}
};
arguments.push(element);
}
let mut result = bx.context.new_call(None, function, &arguments);
if cast_type.is_some() {
result = bx.context.new_cast(None, result, elem_ty);
@ -830,8 +823,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
| sym::simd_floor
| sym::simd_fma
| sym::simd_relaxed_fma
| sym::simd_fpow
| sym::simd_fpowi
| sym::simd_fsin
| sym::simd_fsqrt
| sym::simd_round
@ -914,45 +905,47 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
// All types must be simd vector types
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond {
span,
name,
ty: arg_tys[1]
});
require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird {
span,
name,
ty: arg_tys[2]
});
require_simd!(
arg_tys[1],
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
);
require_simd!(
arg_tys[2],
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
);
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
// Of the same length:
let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
require!(in_len == out_len, InvalidMonomorphization::SecondArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[1],
out_len
});
require!(in_len == out_len2, InvalidMonomorphization::ThirdArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[2],
out_len: out_len2
});
require!(
in_len == out_len,
InvalidMonomorphization::SecondArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[1],
out_len
}
);
require!(
in_len == out_len2,
InvalidMonomorphization::ThirdArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[2],
out_len: out_len2
}
);
// The return type must match the first argument type
require!(ret_ty == in_ty, InvalidMonomorphization::ExpectedReturnType {
span,
name,
in_ty,
ret_ty
});
require!(
ret_ty == in_ty,
InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty }
);
// This counts how many pointers
fn ptr_count(t: Ty<'_>) -> usize {
@ -979,15 +972,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
(ptr_count(element_ty1), non_ptr(element_ty1))
}
_ => {
require!(false, InvalidMonomorphization::ExpectedElementType {
span,
name,
expected_element: element_ty1,
second_arg: arg_tys[1],
in_elem,
in_ty,
mutability: ExpectedPointerMutability::Not,
});
require!(
false,
InvalidMonomorphization::ExpectedElementType {
span,
name,
expected_element: element_ty1,
second_arg: arg_tys[1],
in_elem,
in_ty,
mutability: ExpectedPointerMutability::Not,
}
);
unreachable!();
}
};
@ -1000,12 +996,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
match *element_ty2.kind() {
ty::Int(_) => (),
_ => {
require!(false, InvalidMonomorphization::ThirdArgElementType {
span,
name,
expected_element: element_ty2,
third_arg: arg_tys[2]
});
require!(
false,
InvalidMonomorphization::ThirdArgElementType {
span,
name,
expected_element: element_ty2,
third_arg: arg_tys[2]
}
);
}
}
@ -1029,36 +1028,40 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
// All types must be simd vector types
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond {
span,
name,
ty: arg_tys[1]
});
require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird {
span,
name,
ty: arg_tys[2]
});
require_simd!(
arg_tys[1],
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
);
require_simd!(
arg_tys[2],
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
);
// Of the same length:
let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
require!(in_len == element_len1, InvalidMonomorphization::SecondArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[1],
out_len: element_len1
});
require!(in_len == element_len2, InvalidMonomorphization::ThirdArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[2],
out_len: element_len2
});
require!(
in_len == element_len1,
InvalidMonomorphization::SecondArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[1],
out_len: element_len1
}
);
require!(
in_len == element_len2,
InvalidMonomorphization::ThirdArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[2],
out_len: element_len2
}
);
// This counts how many pointers
fn ptr_count(t: Ty<'_>) -> usize {
@ -1086,15 +1089,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
(ptr_count(element_ty1), non_ptr(element_ty1))
}
_ => {
require!(false, InvalidMonomorphization::ExpectedElementType {
span,
name,
expected_element: element_ty1,
second_arg: arg_tys[1],
in_elem,
in_ty,
mutability: ExpectedPointerMutability::Mut,
});
require!(
false,
InvalidMonomorphization::ExpectedElementType {
span,
name,
expected_element: element_ty1,
second_arg: arg_tys[1],
in_elem,
in_ty,
mutability: ExpectedPointerMutability::Mut,
}
);
unreachable!();
}
};
@ -1106,12 +1112,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
match *element_ty2.kind() {
ty::Int(_) => (),
_ => {
require!(false, InvalidMonomorphization::ThirdArgElementType {
span,
name,
expected_element: element_ty2,
third_arg: arg_tys[2]
});
require!(
false,
InvalidMonomorphization::ThirdArgElementType {
span,
name,
expected_element: element_ty2,
third_arg: arg_tys[2]
}
);
}
}
@ -1278,13 +1287,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
($name:ident : $vec_op:expr, $float_reduce:ident, $ordered:expr, $op:ident,
$identity:expr) => {
if name == sym::$name {
require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType {
span,
name,
in_elem,
in_ty,
ret_ty
});
require!(
ret_ty == in_elem,
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
);
return match *in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {
let r = bx.vector_reduce_op(args[0].immediate(), $vec_op);
@ -1350,13 +1356,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
macro_rules! minmax_red {
($name:ident: $int_red:ident, $float_red:ident) => {
if name == sym::$name {
require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType {
span,
name,
in_elem,
in_ty,
ret_ty
});
require!(
ret_ty == in_elem,
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
);
return match *in_elem.kind() {
ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())),
ty::Float(_) => Ok(bx.$float_red(args[0].immediate())),
@ -1380,13 +1383,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
($name:ident : $op:expr, $boolean:expr) => {
if name == sym::$name {
let input = if !$boolean {
require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType {
span,
name,
in_elem,
in_ty,
ret_ty
});
require!(
ret_ty == in_elem,
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
);
args[0].immediate()
} else {
match *in_elem.kind() {

View file

@ -16,7 +16,7 @@
#![allow(internal_features)]
#![doc(rust_logo)]
#![feature(rustdoc_internals)]
#![feature(rustc_private, decl_macro, never_type, trusted_len, hash_raw_entry, let_chains)]
#![feature(rustc_private, decl_macro, never_type, trusted_len, let_chains)]
#![allow(broken_intra_doc_links)]
#![recursion_limit = "256"]
#![warn(rust_2018_idioms)]
@ -52,6 +52,7 @@ extern crate rustc_metadata;
extern crate rustc_middle;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target;
// This prevents duplicating functions and statics that are already part of the host rustc process.
@ -259,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend {
.join(sess)
}
fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
target_features_cfg(sess, allow_unstable, &self.target_info)
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
target_features_cfg(sess, &self.target_info)
}
}
@ -393,7 +394,7 @@ impl WriteBackendMethods for GccCodegenBackend {
unsafe fn optimize(
_cgcx: &CodegenContext<Self>,
_dcx: DiagCtxtHandle<'_>,
module: &ModuleCodegen<Self::Module>,
module: &mut ModuleCodegen<Self::Module>,
config: &ModuleConfig,
) -> Result<(), FatalError> {
module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
@ -444,7 +445,6 @@ impl WriteBackendMethods for GccCodegenBackend {
}
fn autodiff(
_cgcx: &CodegenContext<Self>,
_tcx: TyCtxt<'_>,
_module: &ModuleCodegen<Self::Module>,
_diff_fncs: Vec<AutoDiffItem>,
_config: &ModuleConfig,
@ -477,7 +477,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
Some(level) => match level {
OptLevel::No => OptimizationLevel::None,
OptLevel::Less => OptimizationLevel::Limited,
OptLevel::Default => OptimizationLevel::Standard,
OptLevel::More => OptimizationLevel::Standard,
OptLevel::Aggressive => OptimizationLevel::Aggressive,
OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
},
@ -487,34 +487,41 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
/// Returns the features that should be set in `cfg(target_feature)`.
fn target_features_cfg(
sess: &Session,
allow_unstable: bool,
target_info: &LockedTargetInfo,
) -> Vec<Symbol> {
) -> (Vec<Symbol>, Vec<Symbol>) {
// TODO(antoyo): use global_gcc_features.
sess.target
.rust_target_features()
.iter()
.filter(|&&(_, gate, _)| gate.in_cfg())
.filter_map(|&(feature, gate, _)| {
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
Some(feature)
} else {
None
}
})
.filter(|feature| {
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
if *feature == "neon" {
return false;
}
target_info.cpu_supports(feature)
/*
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, 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
*/
})
.map(Symbol::intern)
.collect()
let f = |allow_unstable| {
sess.target
.rust_target_features()
.iter()
.filter_map(|&(feature, gate, _)| {
if allow_unstable
|| (gate.in_cfg()
&& (sess.is_nightly_build() || gate.requires_nightly().is_none()))
{
Some(feature)
} else {
None
}
})
.filter(|feature| {
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
if *feature == "neon" {
return false;
}
target_info.cpu_supports(feature)
/*
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, 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
*/
})
.map(Symbol::intern)
.collect()
};
let target_features = f(false);
let unstable_target_features = f(true);
(target_features, unstable_target_features)
}

View file

@ -61,10 +61,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
// compiler-rt, then we want to implicitly compile everything with hidden
// visibility as we're going to link this object all over the place but
// don't want the symbols to get exported.
if linkage != Linkage::Internal
&& linkage != Linkage::Private
&& self.tcx.is_compiler_builtins(LOCAL_CRATE)
{
if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) {
#[cfg(feature = "master")]
decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
} else {

View file

@ -4,13 +4,13 @@ use std::convert::TryInto;
#[cfg(feature = "master")]
use gccjit::CType;
use gccjit::{RValue, Struct, Type};
use rustc_abi::{AddressSpace, Align, Integer, Size};
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, DerivedTypeCodegenMethods, TypeMembershipCodegenMethods,
};
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{bug, ty};
use rustc_target::abi::{AddressSpace, Align, Integer, Size};
use crate::common::TypeReflection;
use crate::context::CodegenCx;
@ -123,7 +123,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
}
impl<'gcc, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> {
fn type_i8(&self) -> Type<'gcc> {
self.i8_type
}

View file

@ -3,7 +3,9 @@ use std::fmt::Write;
use gccjit::{Struct, Type};
use rustc_abi as abi;
use rustc_abi::Primitive::*;
use rustc_abi::{BackendRepr, FieldsShape, Integer, PointeeInfo, Size, Variants};
use rustc_abi::{
BackendRepr, FieldsShape, Integer, PointeeInfo, Reg, Size, TyAbiInterface, Variants,
};
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods,
};
@ -11,8 +13,7 @@ use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
use rustc_target::abi::TyAbiInterface;
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
use rustc_target::callconv::{CastTarget, FnAbi};
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
use crate::context::CodegenCx;
@ -62,7 +63,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
) -> Type<'gcc> {
match layout.backend_repr {
BackendRepr::Scalar(_) => bug!("handled elsewhere"),
BackendRepr::Vector { ref element, count } => {
BackendRepr::SimdVector { ref element, count } => {
let element = layout.scalar_gcc_type_at(cx, element, Size::ZERO);
let element =
// NOTE: gcc doesn't allow pointer types in vectors.
@ -83,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
false,
);
}
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {}
BackendRepr::Memory { .. } => {}
}
let name = match *layout.ty.kind() {
@ -177,19 +178,16 @@ pub trait LayoutGccExt<'tcx> {
impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
fn is_gcc_immediate(&self) -> bool {
match self.backend_repr {
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
false
}
BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true,
BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
}
}
fn is_gcc_scalar_pair(&self) -> bool {
match self.backend_repr {
BackendRepr::ScalarPair(..) => true,
BackendRepr::Uninhabited
| BackendRepr::Scalar(_)
| BackendRepr::Vector { .. }
BackendRepr::Scalar(_)
| BackendRepr::SimdVector { .. }
| BackendRepr::Memory { .. } => false,
}
}

View file

@ -31,7 +31,6 @@ tests/ui/unwind-no-uwtable.rs
tests/ui/parser/unclosed-delimiter-in-dep.rs
tests/ui/consts/missing_span_in_backtrace.rs
tests/ui/drop/dynamic-drop.rs
tests/ui/issues/issue-40883.rs
tests/ui/issues/issue-43853.rs
tests/ui/issues/issue-47364.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
@ -100,14 +99,12 @@ tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs
@ -115,8 +112,9 @@ tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs
tests/ui/simd/simd-bitmask-notpow2.rs
tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs
tests/ui/uninhabited/uninhabited-transparent-return-abi.rs

View file

@ -3,9 +3,10 @@
// Run-time:
// status: signal
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -14,7 +15,7 @@ fn test_fail() -> ! {
unsafe { intrinsics::abort() };
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
test_fail();
}

View file

@ -3,9 +3,10 @@
// Run-time:
// status: signal
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -15,8 +16,8 @@ fn fail() -> i32 {
0
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
fail();
0
}

View file

@ -7,9 +7,10 @@
// 5
// 10
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -20,8 +21,8 @@ fn make_array() -> [u8; 3] {
[42, 10, 5]
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let array = [42, 7, 5];
let array2 = make_array();
unsafe {

View file

@ -5,9 +5,10 @@
// 7 8
// 10
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -21,8 +22,8 @@ fn inc(num: isize) -> isize {
num + 1
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
argc = inc(argc);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);

View file

@ -8,15 +8,16 @@
// Int argument: 2
// Both args: 11
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 {
let string = "Arg: %d\n\0";
let mut closure = || unsafe {
libc::printf(string as *const str as *const i8, argc);

View file

@ -5,15 +5,16 @@
// stdout: true
// 1
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
if argc == 1 {
libc::printf(b"true\n\0" as *const u8 as *const i8);

View file

@ -3,14 +3,15 @@
// Run-time:
// status: 0
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
0
}

View file

@ -3,15 +3,16 @@
// Run-time:
// status: 2
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
libc::exit(2);
}

View file

@ -3,14 +3,15 @@
// Run-time:
// status: 1
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
1
}

View file

@ -4,9 +4,10 @@
// status: 0
// stdout: 1
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -19,8 +20,8 @@ fn call_func(func: fn(i16) -> i8, param: i16) -> i8 {
func(param)
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
let result = call_func(i16_as_i8, argc as i16) as isize;
libc::printf(b"%ld\n\0" as *const u8 as *const i8, result);

View file

@ -6,9 +6,10 @@
// 6
// 11
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -25,8 +26,8 @@ fn update_num(num: &mut isize) {
*num = *num + 5;
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
let mut test = test(argc);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);

View file

@ -5,15 +5,16 @@
// 39
// 10
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 + argc);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 - argc);

View file

@ -4,9 +4,10 @@
// status: 0
// stdout: 1
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -17,8 +18,8 @@ fn make_array() -> [u8; 3] {
[42, 10, 5]
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
unsafe {
let ptr = ONE as *mut usize;
let value = ptr as usize;

View file

@ -6,9 +6,10 @@
// 10
// 42
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -20,8 +21,8 @@ fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u3
)
}
#[start]
fn main(argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
unsafe {
libc::printf(b"%d\n\0" as *const u8 as *const i8, c);

View file

@ -4,9 +4,10 @@
// status: 0
// stdout: 5
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -17,8 +18,8 @@ fn index_slice(s: &[u32]) -> u32 {
unsafe { s[TWO] }
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let array = [42, 7, 5];
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, index_slice(&array));

View file

@ -9,9 +9,10 @@
// 12
// 1
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -32,8 +33,8 @@ static mut TEST2: Test = Test { field: 14 };
static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST } };
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 {
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field);

View file

@ -5,9 +5,10 @@
// stdout: 1
// 2
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
@ -24,10 +25,14 @@ fn one() -> isize {
1
}
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
let test = Test { field: one() };
let two = Two { two: 2 };
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let test = Test {
field: one(),
};
let two = Two {
two: 2,
};
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, two.two);

View file

@ -4,15 +4,16 @@
// status: 0
// stdout: 3
#![feature(no_core, start)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
#[start]
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let test: (isize, isize, isize) = (3, 1, 4);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.0);