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))?; run_command_with_env(&command, None, Some(env))?;
maybe_run_command_in_vm(&[&cargo_target_dir.join("track-caller-attribute")], env, args)?; 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(()) Ok(())
} }
@ -691,25 +678,12 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
fn test_libcore(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. // FIXME: create a function "display_if_not_quiet" or something along the line.
println!("[TEST] libcore"); 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")); let _ = remove_dir_all(path.join("target"));
run_cargo_command(&[&"test"], Some(&path), env, args)?; run_cargo_command(&[&"test"], Some(&path), env, args)?;
Ok(()) 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> { fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> {
if !args.is_using_gcc_master_branch() { if !args.is_using_gcc_master_branch() {
println!("Not using GCC master branch. Skipping `extended_rand_tests`."); 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_std]
#![no_main]
#![allow(internal_features)] #![allow(internal_features)]
extern crate alloc; extern crate alloc;
@ -37,8 +38,8 @@ unsafe extern "C" fn _Unwind_Resume() {
core::intrinsics::unreachable(); core::intrinsics::unreachable();
} }
#[start] #[no_mangle]
fn main(_argc: isize, _argv: *const *const u8) -> isize { 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"); let world: Box<&str> = Box::new("Hello World!\0");
unsafe { unsafe {
puts(*world as *const str as *const u8); puts(*world as *const str as *const u8);

View file

@ -58,6 +58,9 @@ trait Receiver {
#[lang = "copy"] #[lang = "copy"]
pub trait Copy {} pub trait Copy {}
#[lang = "bikeshed_guaranteed_no_drop"]
pub trait BikeshedGuaranteedNoDrop {}
impl Copy for bool {} impl Copy for bool {}
impl Copy for u8 {} impl Copy for u8 {}
impl Copy for u16 {} 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 { impl Mul for usize {
type Output = Self; 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"] #[lang = "rem"]
pub trait Rem<RHS = Self> { pub trait Rem<RHS = Self> {
type Output; type Output;
@ -617,40 +636,28 @@ pub union MaybeUninit<T> {
pub mod intrinsics { pub mod intrinsics {
#[rustc_intrinsic] #[rustc_intrinsic]
pub fn abort() -> !; pub fn abort() -> !;
#[rustc_intrinsic] #[rustc_intrinsic]
pub fn size_of<T>() -> usize; pub fn size_of<T>() -> usize;
#[rustc_intrinsic] #[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] #[rustc_intrinsic]
pub fn min_align_of<T>() -> usize; pub fn min_align_of<T>() -> usize;
#[rustc_intrinsic] #[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] #[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] #[rustc_intrinsic]
pub unsafe fn transmute<T, U>(_e: T) -> U; pub unsafe fn transmute<T, U>(e: T) -> U;
#[rustc_intrinsic] #[rustc_intrinsic]
pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32; pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
#[rustc_intrinsic] #[rustc_intrinsic]
pub fn needs_drop<T: ?::Sized>() -> bool; pub fn needs_drop<T: ?::Sized>() -> bool;
#[rustc_intrinsic] #[rustc_intrinsic]
pub fn bitreverse<T>(_x: T) -> T; pub fn bitreverse<T>(x: T) -> T;
#[rustc_intrinsic] #[rustc_intrinsic]
pub fn bswap<T>(_x: T) -> T; pub fn bswap<T>(x: T) -> T;
#[rustc_intrinsic] #[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] #[rustc_intrinsic]
pub unsafe fn unreachable() -> !; pub unsafe fn unreachable() -> !;
} }
@ -694,7 +701,7 @@ impl<T> Index<usize> for [T] {
} }
} }
extern { extern "C" {
type VaListImpl; type VaListImpl;
} }

View file

@ -1,7 +1,7 @@
// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs // Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
#![feature( #![feature(
no_core, unboxed_closures, start, lang_items, never_type, linkage, no_core, unboxed_closures, lang_items, never_type, linkage,
extern_types, thread_local extern_types, thread_local
)] )]
#![no_core] #![no_core]
@ -258,13 +258,13 @@ fn main() {
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42); assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
extern { extern "C" {
#[linkage = "weak"] #[linkage = "weak"]
static ABC: *const u8; static ABC: *const u8;
} }
{ {
extern { extern "C" {
#[linkage = "weak"] #[linkage = "weak"]
static ABC: *const u8; 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::io::Write;
use std::ops::Coroutine; use std::ops::Coroutine;
extern { extern "C" {
pub fn printf(format: *const i8, ...) -> i32; 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 ec2d0dc77fb484d926b45bb626b0db6a4bb0ab5c Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com> From: None <none@example.com>
Date: Fri, 3 Dec 2021 12:16:30 +0100 Date: Thu, 27 Mar 2025 09:20:41 -0400
Subject: [PATCH] Disable long running tests Subject: [PATCH] Disable long running tests
--- ---
library/core/tests/slice.rs | 2 ++ library/coretests/tests/slice.rs | 2 ++
1 file changed, 2 insertions(+) 1 file changed, 2 insertions(+)
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs
index 8402833..84592e0 100644 index d17e681..fba5cd6 100644
--- a/library/core/tests/slice.rs --- a/library/coretests/tests/slice.rs
+++ b/library/core/tests/slice.rs +++ b/library/coretests/tests/slice.rs
@@ -2462,6 +2462,7 @@ take_tests! { @@ -2486,6 +2486,7 @@ split_off_tests! {
#[cfg(not(miri))] // unused in Miri #[cfg(not(miri))] // unused in Miri
const EMPTY_MAX: &'static [()] = &[(); usize::MAX]; const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
@ -19,14 +19,14 @@ index 8402833..84592e0 100644
// can't be a constant due to const mutability rules // can't be a constant due to const mutability rules
#[cfg(not(miri))] // unused in Miri #[cfg(not(miri))] // unused in Miri
macro_rules! empty_max_mut { macro_rules! empty_max_mut {
@@ -2485,6 +2486,7 @@ take_tests! { @@ -2509,6 +2510,7 @@ split_off_tests! {
(take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), (split_off_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!()), (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
} }
+*/ +*/
#[test] #[test]
fn test_slice_from_ptr_range() { 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> 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 Subject: [PATCH] Disable libstd and libtest dylib
--- ---
library/std/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +-
library/test/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml 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 --- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml +++ b/library/std/Cargo.toml
@@ -9,7 +9,7 @@ description = "The Rust Standard Library" @@ -10,7 +10,7 @@ edition = "2024"
edition = "2021" autobenches = false
[lib] [lib]
-crate-type = ["dylib", "rlib"] -crate-type = ["dylib", "rlib"]
@ -21,3 +20,6 @@ index 5b21355..cb0c49b 100644
[dependencies] [dependencies]
alloc = { path = "../alloc", public = true } 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> From: None <none@example.com>
Date: Sat, 18 Nov 2023 10:50:36 -0500 Date: Thu, 27 Mar 2025 14:32:14 -0400
Subject: [PATCH] [core] Disable portable-simd test Subject: [PATCH] Disable portable-simd test
--- ---
library/core/tests/lib.rs | 2 -- library/coretests/tests/lib.rs | 1 -
1 file changed, 2 deletions(-) 1 file changed, 1 deletion(-)
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index b71786c..cf484d5 100644 index 79022fe..9223b2f 100644
--- a/library/core/tests/lib.rs --- a/library/coretests/tests/lib.rs
+++ b/library/core/tests/lib.rs +++ b/library/coretests/tests/lib.rs
@@ -87,7 +87,6 @@ @@ -165,7 +165,6 @@ mod pin;
#![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;
mod pin_macro; mod pin_macro;
mod ptr; mod ptr;
mod result; mod result;
@ -27,4 +19,6 @@ index b71786c..cf484d5 100644
mod slice; mod slice;
mod str; mod str;
mod str_lossy; mod str_lossy;
-- 2.45.2 --
2.49.0

View file

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

View file

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

View file

@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_session::config::OomStrategy; use rustc_session::config::OomStrategy;
use rustc_symbol_mangling::mangle_internal_symbol;
use crate::GccContext; use crate::GccContext;
#[cfg(feature = "master")] #[cfg(feature = "master")]
@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
panic!("invalid allocator output") panic!("invalid allocator output")
} }
}; };
let from_name = global_fn_name(method.name); let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
let to_name = default_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); create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
} }
@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen(
create_wrapper_function( create_wrapper_function(
tcx, tcx,
context, context,
"__rust_alloc_error_handler", &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
alloc_error_handler_name(alloc_error_handler_kind), &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
&[usize, usize], &[usize, usize],
None, 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); let global = context.new_global(None, GlobalKind::Exported, i8, name);
#[cfg(feature = "master")] #[cfg(feature = "master")]
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc( 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); let value = context.new_rvalue_from_int(i8, value as i32);
global.global_set_initializer_rvalue(value); 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); let global = context.new_global(None, GlobalKind::Exported, i8, name);
#[cfg(feature = "master")] #[cfg(feature = "master")]
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc( 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)) Arc::new(SyncContext::new(context))
} }
}; };
let module = ModuleCodegen { let module = ModuleCodegen::new_regular(
module_llvm: GccContext { thin_module.name().to_string(),
GccContext {
context, context,
should_combine_object_files, should_combine_object_files,
// TODO(antoyo): use the correct relocation model here. // TODO(antoyo): use the correct relocation model here.
relocation_model: RelocModel::Pic, relocation_model: RelocModel::Pic,
temp_dir: None, temp_dir: None,
}, },
name: thin_module.name().to_string(), );
kind: ModuleKind::Regular,
};
/*{ /*{
let target = &*module.module_llvm.tm; let target = &*module.module_llvm.tm;
let llmod = module.module_llvm.llmod(); let llmod = module.module_llvm.llmod();
@ -710,10 +709,6 @@ pub struct ThinBuffer {
context: Arc<SyncContext>, 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 { impl ThinBuffer {
pub(crate) fn new(context: &Arc<SyncContext>) -> Self { pub(crate) fn new(context: &Arc<SyncContext>) -> Self {
Self { context: Arc::clone(context) } Self { context: Arc::clone(context) }

View file

@ -24,19 +24,23 @@ pub(crate) unsafe fn codegen(
{ {
let context = &module.module_llvm.context; 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 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 // 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). // now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit).
// TODO(antoyo): remove this environment variable. // TODO(antoyo): remove this environment variable.
let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1"); 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 bc_out = cgcx.output_filenames.temp_path_for_cgu(
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); 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 config.bitcode_needed() {
if fat_lto { if fat_lto {
@ -117,14 +121,22 @@ pub(crate) unsafe fn codegen(
} }
if config.emit_ir { 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"); std::fs::write(out, "").expect("write file");
} }
if config.emit_asm { if config.emit_asm {
let _timer = let _timer =
cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); 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")); 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_asm,
config.emit_ir, config.emit_ir,
&cgcx.output_filenames, &cgcx.output_filenames,
cgcx.invocation_temp.as_deref(),
)) ))
} }

View file

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

View file

@ -29,7 +29,7 @@ use rustc_middle::ty::layout::{
use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_span::Span; use rustc_span::Span;
use rustc_span::def_id::DefId; 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 rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi};
use crate::common::{SignType, TypeReflection, type_is_pointer}; 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. // NOTE: not sure why, but we have the wrong type here.
let int_type = compare_exchange.get_param(2).to_rvalue().get_type(); let int_type = compare_exchange.get_param(2).to_rvalue().get_type();
let src = self.context.new_bitcast(self.location, src, int_type); let src = self.context.new_bitcast(self.location, src, int_type);
self.context.new_call(self.location, compare_exchange, &[ self.context.new_call(
dst, self.location,
expected, compare_exchange,
src, &[dst, expected, src, weak, order, failure_order],
weak, )
order,
failure_order,
])
} }
pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) { 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 a + b
} }
// TODO(antoyo): should we also override the `unchecked_` versions?
fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
self.gcc_sub(a, b) 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)) 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> { 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. // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
set_rvalue_location(self, lhs + rhs) 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) OperandValue::Ref(place.val)
} else if place.layout.is_gcc_immediate() { } else if place.layout.is_gcc_immediate() {
let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align); 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 { OperandValue::Immediate(
scalar_load_metadata(self, load, scalar); 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)) self.to_immediate_scalar(load, *scalar)
} else {
load
},
)
} else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr { } 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); 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); 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)); 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(), &[ let next = self.inbounds_gep(
self.const_usize(1), self.backend_type(cg_elem.layout),
]); current.to_rvalue(),
&[self.const_usize(1)],
);
self.llbb().add_assignment(self.location, current, next); self.llbb().add_assignment(self.location, current, next);
self.br(header_bb); 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 { fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
if scalar.is_bool() { if scalar.is_bool() {
return self.trunc(val, self.cx().type_i1()); return self.unchecked_utrunc(val, self.cx().type_i1());
} }
val val
} }
@ -2495,9 +2474,5 @@ fn get_maybe_pointer_size(value: RValue<'_>) -> u32 {
#[cfg(not(feature = "master"))] #[cfg(not(feature = "master"))]
fn get_maybe_pointer_size(value: RValue<'_>) -> u32 { fn get_maybe_pointer_size(value: RValue<'_>) -> u32 {
let type_ = value.get_type(); let type_ = value.get_type();
if type_.get_pointee().is_some() { if type_.get_pointee().is_some() { size_of::<*const ()>() as _ } else { type_.get_size() }
std::mem::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() 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> { 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) } 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>) { fn const_str(&self, s: &str) -> (RValue<'gcc>, RValue<'gcc>) {
let str_global = *self let mut const_str_cache = self.const_str_cache.borrow_mut();
.const_str_cache let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
.borrow_mut() let g = self.global_string(s);
.raw_entry_mut() const_str_cache.insert(s.to_owned(), g);
.from_key(s) g
.or_insert_with(|| (s.to_owned(), self.global_string(s))) });
.1;
let len = s.len(); let len = s.len();
let cs = self.const_ptrcast( let cs = self.const_ptrcast(
str_global.get_address(None), str_global.get_address(None),
@ -229,7 +228,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
GlobalAlloc::VTable(ty, dyn_ty) => { GlobalAlloc::VTable(ty, dyn_ty) => {
let alloc = self let alloc = self
.tcx .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(); .unwrap_memory();
let init = const_alloc_to_gcc(self, alloc); let init = const_alloc_to_gcc(self, alloc);
self.static_addr_of(init, alloc.inner().align, None) 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) const_alloc_to_gcc(self, alloc)
} }

View file

@ -1,6 +1,7 @@
#[cfg(feature = "master")] #[cfg(feature = "master")]
use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{FnAttribute, VarAttribute, Visibility};
use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type};
use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange};
use rustc_codegen_ssa::traits::{ use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
}; };
@ -14,7 +15,6 @@ use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Instance}; use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
use crate::base; use crate::base;
use crate::context::CodegenCx; 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. // 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. // 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 // The `inspect` method is okay here because we checked for provenance, and
// because we are doing this access to inspect the final interpreter state // because we are doing this access to inspect the final interpreter state
// (not as part of the interpreter execution). // (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>( pub fn const_alloc_to_gcc<'gcc>(
cx: &CodegenCx<'gcc, 'tcx>, cx: &CodegenCx<'gcc, '_>,
alloc: ConstAllocation<'tcx>, alloc: ConstAllocation<'_>,
) -> RValue<'gcc> { ) -> RValue<'gcc> {
let alloc = alloc.inner(); let alloc = alloc.inner();
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); 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)); 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) cx.const_struct(&llvals, true)
} }

View file

@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell};
use gccjit::{ use gccjit::{
Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type, 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::base::wants_msvc_seh;
use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::errors as ssa_errors;
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods};
@ -14,11 +15,10 @@ use rustc_middle::ty::layout::{
FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
LayoutOfHelpers, 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_session::Session;
use rustc_span::source_map::respan; use rustc_span::source_map::respan;
use rustc_span::{DUMMY_SP, Span}; use rustc_span::{DUMMY_SP, Span};
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_target::spec::{ use rustc_target::spec::{
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi, 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>>>, pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
/// Cache generated vtables /// Cache generated vtables
pub 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. // TODO(antoyo): improve the SSA API to not require those.
/// Mapping from function pointer type to indexes of on stack parameters. /// 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 bool_type = context.new_type::<bool>();
let mut functions = FxHashMap::default(); let mut functions = FxHashMap::default();
let builtins = [ let builtins = ["abort"];
"__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",
];
for builtin in builtins.iter() { for builtin in builtins.iter() {
functions.insert(builtin.to_string(), context.get_builtin_function(builtin)); 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> { impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn vtables( fn vtables(
&self, &self,
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> { ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
&self.vtables &self.vtables
} }
@ -519,7 +493,6 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
} else { } else {
// If the symbol already exists, it is an error: for example, the user wrote // If the symbol already exists, it is an error: for example, the user wrote
// #[no_mangle] extern "C" fn main(..) {..} // #[no_mangle] extern "C" fn main(..) {..}
// instead of #[start]
None None
} }
} }

View file

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

View file

@ -1,10 +1,8 @@
use std::iter::FromIterator;
#[cfg(feature = "master")] #[cfg(feature = "master")]
use gccjit::Context; use gccjit::Context;
use rustc_codegen_ssa::codegen_attrs::check_tied_features; use rustc_codegen_ssa::codegen_attrs::check_tied_features;
use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; 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_data_structures::unord::UnordSet;
use rustc_session::Session; use rustc_session::Session;
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; 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 known_features = sess.target.rust_target_features();
let mut featsmap = FxHashMap::default(); 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 // Compute implied features
let mut all_rust_features = vec![]; let mut all_rust_features = vec![];
for feature in sess.opts.cg.target_feature.split(',') { for feature in sess.opts.cg.target_feature.split(',') {
if let Some(feature) = feature.strip_prefix('+') { if let Some(feature) = feature.strip_prefix('+') {
all_rust_features.extend( 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() .to_sorted_stable_ord()
.iter() .iter()
.map(|&&s| (true, s)), .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. // FIXME(nagisa): figure out how to not allocate a full hashset here.
featsmap.insert(feature, enable); 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. // Translate this into GCC features.
let feats = let feats =
all_rust_features.iter().flat_map(|&(enable, feature)| { 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. //! 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 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::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp};
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_target::abi::Endian; use rustc_target::callconv::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
use rustc_target::spec;
use crate::builder::{Builder, ToGccComp}; use crate::builder::{Builder, ToGccComp};
use crate::common::{SignType, TypeReflection}; use crate::common::{SignType, TypeReflection};
@ -322,36 +321,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
}, },
} }
} else { } else {
match new_kind { let (func_name, width) = match oop {
Int(I128) | Uint(U128) => { OverflowOp::Add => match new_kind {
let func_name = match oop { Int(I128) => ("__rust_i128_addo", 128),
OverflowOp::Add => match new_kind { Uint(U128) => ("__rust_u128_addo", 128),
Int(I128) => "__rust_i128_addo", _ => unreachable!(),
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),
}, },
} 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); 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) (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( pub fn operation_with_overflow(
&self, &self,
func_name: &str, func_name: &str,
lhs: RValue<'gcc>, lhs: RValue<'gcc>,
rhs: RValue<'gcc>, rhs: RValue<'gcc>,
width: u64,
) -> (RValue<'gcc>, RValue<'gcc>) { ) -> (RValue<'gcc>, RValue<'gcc>) {
let a_type = lhs.get_type(); let a_type = lhs.get_type();
let b_type = rhs.get_type(); let b_type = rhs.get_type();
debug_assert!(a_type.dyncast_array().is_some()); debug_assert!(a_type.dyncast_array().is_some());
debug_assert!(b_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_a = self.context.new_parameter(self.location, a_type, "a");
let param_b = self.context.new_parameter(self.location, b_type, "b"); 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 param_overflow =
let overflow_field = self.context.new_field(self.location, self.bool_type, "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 let layout = self
.tcx .tcx
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty)) .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(res_ty))
.unwrap(); .unwrap();
let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) }; let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
let mut fn_abi = FnAbi { 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, ret: arg_abi,
c_variadic: false, c_variadic: false,
fixed_count: 2, fixed_count: 3,
conv: Conv::C, conv: Conv::C,
can_unwind: false, 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( let func = self.context.new_function(
self.location, self.location,
FunctionType::Extern, FunctionType::Extern,
self.type_void(), self.type_void(),
&[return_param, param_a, param_b], &[param_res, param_a, param_b, param_overflow],
func_name, func_name,
false, false,
); );
self.llbb().add_eval( let _void =
self.location, self.context.new_call(self.location, func, &[res_addr, lhs, rhs, overflow_addr]);
self.context.new_call(self.location, func, &[ res_value.to_rvalue()
return_value.get_address(self.location),
lhs,
rhs,
]),
);
return_value.to_rvalue()
} else { } else {
let func = self.context.new_function( let func = self.context.new_function(
self.location, self.location,
FunctionType::Extern, FunctionType::Extern,
return_type.as_type(), res_type,
&[param_a, param_b], &[param_a, param_b, param_overflow],
func_name, func_name,
false, 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); // NOTE: we must assign the result of the operation to a variable at this point to make
let int_result = result.access_field(self.location, result_field); // sure it will be evaluated by libgccjit now.
(int_result, overflow) // 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( pub fn gcc_icmp(
@ -869,6 +874,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let value_type = value.get_type(); 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) 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) self.context.new_cast(None, value, dest_typ)
} else if self.is_native_int_type_or_bool(dest_typ) { } else if self.is_native_int_type_or_bool(dest_typ) {
self.context.new_cast(None, self.low(value), 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) { let name_suffix = match self.type_kind(dest_typ) {
TypeKind::Float => "tisf", TypeKind::Float => "tisf",
TypeKind::Double => "tidf", TypeKind::Double => "tidf",
TypeKind::FP128 => "tixf",
kind => panic!("cannot cast a non-native integer to type {:?}", kind), kind => panic!("cannot cast a non-native integer to type {:?}", kind),
}; };
let sign = if signed { "" } else { "un" }; let sign = if signed { "" } else { "un" };

View file

@ -1,11 +1,90 @@
use std::borrow::Cow; 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 rustc_codegen_ssa::traits::BuilderMethods;
use crate::builder::Builder; use crate::builder::Builder;
use crate::context::CodegenCx; 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))] #[cfg_attr(not(feature = "master"), allow(unused_variables))]
pub fn adjust_function<'gcc>( pub fn adjust_function<'gcc>(
context: &'gcc Context<'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); let arg4 = builder.context.new_rvalue_from_int(arg4_type, -1);
args = vec![a, b, c, arg4, new_args[3]].into(); 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 { } 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 field2 = builder.context.new_field(None, args[1].get_type(), "carryResult");
let struct_type = let struct_type =
builder.context.new_struct_type(None, "addcarryResult", &[field1, field2]); builder.context.new_struct_type(None, "addcarryResult", &[field1, field2]);
return_value = return_value = builder.context.new_struct_constructor(
builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[ None,
return_value, struct_type.as_type(),
last_arg.dereference(None).to_rvalue(), None,
]); &[return_value, last_arg.dereference(None).to_rvalue()],
);
} }
} }
"__builtin_ia32_stmxcsr" => { "__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 field2 = builder.context.new_field(None, return_value.get_type(), "success");
let struct_type = let struct_type =
builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]); builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]);
return_value = return_value = builder.context.new_struct_constructor(
builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[ None,
random_number, struct_type.as_type(),
success_variable.to_rvalue(), None,
]); &[random_number, success_variable.to_rvalue()],
);
} }
"fma" => { "fma" => {
let f16_type = builder.context.new_c_type(CType::Float16); let f16_type = builder.context.new_c_type(CType::Float16);
return_value = builder.context.new_cast(None, return_value, f16_type); 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.vfmadd.cph.256" => "__builtin_ia32_vfmaddcph256_mask3",
"llvm.x86.avx512fp16.mask.vfcmadd.cph.128" => "__builtin_ia32_vfcmaddcph128_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.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: // TODO: support the tile builtins:
"llvm.x86.ldtilecfg" => "__builtin_trap", "llvm.x86.ldtilecfg" => "__builtin_trap",

View file

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

View file

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

View file

@ -16,7 +16,7 @@
#![allow(internal_features)] #![allow(internal_features)]
#![doc(rust_logo)] #![doc(rust_logo)]
#![feature(rustdoc_internals)] #![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)] #![allow(broken_intra_doc_links)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
@ -52,6 +52,7 @@ extern crate rustc_metadata;
extern crate rustc_middle; extern crate rustc_middle;
extern crate rustc_session; extern crate rustc_session;
extern crate rustc_span; extern crate rustc_span;
extern crate rustc_symbol_mangling;
extern crate rustc_target; extern crate rustc_target;
// This prevents duplicating functions and statics that are already part of the host rustc process. // 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) .join(sess)
} }
fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> { fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
target_features_cfg(sess, allow_unstable, &self.target_info) target_features_cfg(sess, &self.target_info)
} }
} }
@ -393,7 +394,7 @@ impl WriteBackendMethods for GccCodegenBackend {
unsafe fn optimize( unsafe fn optimize(
_cgcx: &CodegenContext<Self>, _cgcx: &CodegenContext<Self>,
_dcx: DiagCtxtHandle<'_>, _dcx: DiagCtxtHandle<'_>,
module: &ModuleCodegen<Self::Module>, module: &mut ModuleCodegen<Self::Module>,
config: &ModuleConfig, config: &ModuleConfig,
) -> Result<(), FatalError> { ) -> Result<(), FatalError> {
module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level)); module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
@ -444,7 +445,6 @@ impl WriteBackendMethods for GccCodegenBackend {
} }
fn autodiff( fn autodiff(
_cgcx: &CodegenContext<Self>, _cgcx: &CodegenContext<Self>,
_tcx: TyCtxt<'_>,
_module: &ModuleCodegen<Self::Module>, _module: &ModuleCodegen<Self::Module>,
_diff_fncs: Vec<AutoDiffItem>, _diff_fncs: Vec<AutoDiffItem>,
_config: &ModuleConfig, _config: &ModuleConfig,
@ -477,7 +477,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
Some(level) => match level { Some(level) => match level {
OptLevel::No => OptimizationLevel::None, OptLevel::No => OptimizationLevel::None,
OptLevel::Less => OptimizationLevel::Limited, OptLevel::Less => OptimizationLevel::Limited,
OptLevel::Default => OptimizationLevel::Standard, OptLevel::More => OptimizationLevel::Standard,
OptLevel::Aggressive => OptimizationLevel::Aggressive, OptLevel::Aggressive => OptimizationLevel::Aggressive,
OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited, 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)`. /// Returns the features that should be set in `cfg(target_feature)`.
fn target_features_cfg( fn target_features_cfg(
sess: &Session, sess: &Session,
allow_unstable: bool,
target_info: &LockedTargetInfo, target_info: &LockedTargetInfo,
) -> Vec<Symbol> { ) -> (Vec<Symbol>, Vec<Symbol>) {
// TODO(antoyo): use global_gcc_features. // TODO(antoyo): use global_gcc_features.
sess.target let f = |allow_unstable| {
.rust_target_features() sess.target
.iter() .rust_target_features()
.filter(|&&(_, gate, _)| gate.in_cfg()) .iter()
.filter_map(|&(feature, gate, _)| { .filter_map(|&(feature, gate, _)| {
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() { if allow_unstable
Some(feature) || (gate.in_cfg()
} else { && (sess.is_nightly_build() || gate.requires_nightly().is_none()))
None {
} Some(feature)
}) } else {
.filter(|feature| { None
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it. }
if *feature == "neon" { })
return false; .filter(|feature| {
} // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
target_info.cpu_supports(feature) if *feature == "neon" {
/* return false;
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, }
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, target_info.cpu_supports(feature)
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 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,
.map(Symbol::intern) sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
.collect() */
})
.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 // 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 // visibility as we're going to link this object all over the place but
// don't want the symbols to get exported. // don't want the symbols to get exported.
if linkage != Linkage::Internal if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) {
&& linkage != Linkage::Private
&& self.tcx.is_compiler_builtins(LOCAL_CRATE)
{
#[cfg(feature = "master")] #[cfg(feature = "master")]
decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
} else { } else {

View file

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

View file

@ -3,7 +3,9 @@ use std::fmt::Write;
use gccjit::{Struct, Type}; use gccjit::{Struct, Type};
use rustc_abi as abi; use rustc_abi as abi;
use rustc_abi::Primitive::*; 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::{ use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods, BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods,
}; };
@ -11,8 +13,7 @@ use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
use rustc_target::abi::TyAbiInterface; use rustc_target::callconv::{CastTarget, FnAbi};
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
use crate::context::CodegenCx; use crate::context::CodegenCx;
@ -62,7 +63,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
) -> Type<'gcc> { ) -> Type<'gcc> {
match layout.backend_repr { match layout.backend_repr {
BackendRepr::Scalar(_) => bug!("handled elsewhere"), 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 = layout.scalar_gcc_type_at(cx, element, Size::ZERO);
let element = let element =
// NOTE: gcc doesn't allow pointer types in vectors. // NOTE: gcc doesn't allow pointer types in vectors.
@ -83,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
false, false,
); );
} }
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} BackendRepr::Memory { .. } => {}
} }
let name = match *layout.ty.kind() { let name = match *layout.ty.kind() {
@ -177,19 +178,16 @@ pub trait LayoutGccExt<'tcx> {
impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
fn is_gcc_immediate(&self) -> bool { fn is_gcc_immediate(&self) -> bool {
match self.backend_repr { match self.backend_repr {
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true,
BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
false
}
} }
} }
fn is_gcc_scalar_pair(&self) -> bool { fn is_gcc_scalar_pair(&self) -> bool {
match self.backend_repr { match self.backend_repr {
BackendRepr::ScalarPair(..) => true, BackendRepr::ScalarPair(..) => true,
BackendRepr::Uninhabited BackendRepr::Scalar(_)
| BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. }
| BackendRepr::Vector { .. }
| BackendRepr::Memory { .. } => false, | 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/parser/unclosed-delimiter-in-dep.rs
tests/ui/consts/missing_span_in_backtrace.rs tests/ui/consts/missing_span_in_backtrace.rs
tests/ui/drop/dynamic-drop.rs tests/ui/drop/dynamic-drop.rs
tests/ui/issues/issue-40883.rs
tests/ui/issues/issue-43853.rs tests/ui/issues/issue-43853.rs
tests/ui/issues/issue-47364.rs tests/ui/issues/issue-47364.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.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/inline1.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/print.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/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/as-cast/segfault.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.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/exposed-provenance/basic.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/zero.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/inline1.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.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/inline2.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.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/function.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.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/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/inline2.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs
tests/ui/simd/simd-bitmask-notpow2.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: // Run-time:
// status: signal // status: signal
#![feature(no_core, start)] #![feature(no_core)]
#![no_std] #![no_std]
#![no_core] #![no_core]
#![no_main]
extern crate mini_core; extern crate mini_core;
use mini_core::*; use mini_core::*;
@ -14,7 +15,7 @@ fn test_fail() -> ! {
unsafe { intrinsics::abort() }; unsafe { intrinsics::abort() };
} }
#[start] #[no_mangle]
fn main(mut argc: isize, _argv: *const *const u8) -> isize { extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
test_fail(); test_fail();
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,9 +6,10 @@
// 6 // 6
// 11 // 11
#![feature(no_core, start)] #![feature(no_core)]
#![no_std] #![no_std]
#![no_core] #![no_core]
#![no_main]
extern crate mini_core; extern crate mini_core;
use mini_core::*; use mini_core::*;
@ -25,8 +26,8 @@ fn update_num(num: &mut isize) {
*num = *num + 5; *num = *num + 5;
} }
#[start] #[no_mangle]
fn main(mut argc: isize, _argv: *const *const u8) -> isize { extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
let mut test = test(argc); let mut test = test(argc);
unsafe { 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, test.field);

View file

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

View file

@ -6,9 +6,10 @@
// 10 // 10
// 42 // 42
#![feature(no_core, start)] #![feature(no_core)]
#![no_std] #![no_std]
#![no_core] #![no_core]
#![no_main]
extern crate mini_core; extern crate mini_core;
use 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] #[no_mangle]
fn main(argc: isize, _argv: *const *const u8) -> isize { 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); let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
unsafe { unsafe {
libc::printf(b"%d\n\0" as *const u8 as *const i8, c); libc::printf(b"%d\n\0" as *const u8 as *const i8, c);

View file

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

View file

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

View file

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

View file

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