Merge pull request #650 from rust-lang/sync_from_rust_2025_04_17
Sync from rust 2025/04/17
This commit is contained in:
commit
db1a31c243
51 changed files with 929 additions and 839 deletions
|
@ -426,19 +426,6 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> {
|
|||
run_command_with_env(&command, None, Some(env))?;
|
||||
maybe_run_command_in_vm(&[&cargo_target_dir.join("track-caller-attribute")], env, args)?;
|
||||
|
||||
// FIXME: create a function "display_if_not_quiet" or something along the line.
|
||||
println!("[AOT] mod_bench");
|
||||
let mut command = args.config_info.rustc_command_vec();
|
||||
command.extend_from_slice(&[
|
||||
&"example/mod_bench.rs",
|
||||
&"--crate-type",
|
||||
&"bin",
|
||||
&"--target",
|
||||
&args.config_info.target_triple,
|
||||
]);
|
||||
run_command_with_env(&command, None, Some(env))?;
|
||||
// FIXME: the compiled binary is not run.
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -691,25 +678,12 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
|
|||
fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
|
||||
// FIXME: create a function "display_if_not_quiet" or something along the line.
|
||||
println!("[TEST] libcore");
|
||||
let path = get_sysroot_dir().join("sysroot_src/library/core/tests");
|
||||
let path = get_sysroot_dir().join("sysroot_src/library/coretests");
|
||||
let _ = remove_dir_all(path.join("target"));
|
||||
run_cargo_command(&[&"test"], Some(&path), env, args)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// echo "[BENCH COMPILE] mod_bench"
|
||||
//
|
||||
// COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline"
|
||||
// COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort"
|
||||
// COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort"
|
||||
// COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort"
|
||||
// COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort"
|
||||
//
|
||||
// Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow
|
||||
// hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3"
|
||||
// echo "[BENCH RUN] mod_bench"
|
||||
// hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_*
|
||||
|
||||
fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> {
|
||||
if !args.is_using_gcc_master_branch() {
|
||||
println!("Not using GCC master branch. Skipping `extended_rand_tests`.");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
|
||||
#![feature(core_intrinsics, alloc_error_handler, lang_items)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![allow(internal_features)]
|
||||
|
||||
extern crate alloc;
|
||||
|
@ -37,8 +38,8 @@ unsafe extern "C" fn _Unwind_Resume() {
|
|||
core::intrinsics::unreachable();
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int {
|
||||
let world: Box<&str> = Box::new("Hello World!\0");
|
||||
unsafe {
|
||||
puts(*world as *const str as *const u8);
|
||||
|
|
|
@ -58,6 +58,9 @@ trait Receiver {
|
|||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
|
||||
#[lang = "bikeshed_guaranteed_no_drop"]
|
||||
pub trait BikeshedGuaranteedNoDrop {}
|
||||
|
||||
impl Copy for bool {}
|
||||
impl Copy for u8 {}
|
||||
impl Copy for u16 {}
|
||||
|
@ -135,6 +138,14 @@ impl Mul for u8 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Mul for i32 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
self * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for usize {
|
||||
type Output = Self;
|
||||
|
||||
|
@ -245,6 +256,14 @@ impl Sub for i16 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Sub for i32 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self {
|
||||
self - rhs
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "rem"]
|
||||
pub trait Rem<RHS = Self> {
|
||||
type Output;
|
||||
|
@ -617,40 +636,28 @@ pub union MaybeUninit<T> {
|
|||
pub mod intrinsics {
|
||||
#[rustc_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
|
||||
#[rustc_intrinsic]
|
||||
pub fn size_of<T>() -> usize;
|
||||
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn size_of_val<T: ?::Sized>(_val: *const T) -> usize;
|
||||
|
||||
pub unsafe fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
|
||||
#[rustc_intrinsic]
|
||||
pub fn min_align_of<T>() -> usize;
|
||||
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn min_align_of_val<T: ?::Sized>(_val: *const T) -> usize;
|
||||
|
||||
pub unsafe fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize);
|
||||
|
||||
pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn transmute<T, U>(_e: T) -> U;
|
||||
|
||||
pub unsafe fn transmute<T, U>(e: T) -> U;
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32;
|
||||
|
||||
pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
|
||||
#[rustc_intrinsic]
|
||||
pub fn needs_drop<T: ?::Sized>() -> bool;
|
||||
|
||||
#[rustc_intrinsic]
|
||||
pub fn bitreverse<T>(_x: T) -> T;
|
||||
|
||||
pub fn bitreverse<T>(x: T) -> T;
|
||||
#[rustc_intrinsic]
|
||||
pub fn bswap<T>(_x: T) -> T;
|
||||
|
||||
pub fn bswap<T>(x: T) -> T;
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize);
|
||||
|
||||
pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn unreachable() -> !;
|
||||
}
|
||||
|
@ -694,7 +701,7 @@ impl<T> Index<usize> for [T] {
|
|||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type VaListImpl;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
|
||||
|
||||
#![feature(
|
||||
no_core, unboxed_closures, start, lang_items, never_type, linkage,
|
||||
no_core, unboxed_closures, lang_items, never_type, linkage,
|
||||
extern_types, thread_local
|
||||
)]
|
||||
#![no_core]
|
||||
|
@ -258,13 +258,13 @@ fn main() {
|
|||
|
||||
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
#[linkage = "weak"]
|
||||
static ABC: *const u8;
|
||||
}
|
||||
|
||||
{
|
||||
extern {
|
||||
extern "C" {
|
||||
#[linkage = "weak"]
|
||||
static ABC: *const u8;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ use std::arch::x86_64::*;
|
|||
use std::io::Write;
|
||||
use std::ops::Coroutine;
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
pub fn printf(format: *const i8, ...) -> i32;
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
d6f5a708104a98199ac0f01a3b6b279a0f7c66d3
|
||||
0ea98a1365b81f7488073512c850e8ee951a4afd
|
||||
|
|
|
@ -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
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
||||
Date: Fri, 3 Dec 2021 12:16:30 +0100
|
||||
From ec2d0dc77fb484d926b45bb626b0db6a4bb0ab5c Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Thu, 27 Mar 2025 09:20:41 -0400
|
||||
Subject: [PATCH] Disable long running tests
|
||||
|
||||
---
|
||||
library/core/tests/slice.rs | 2 ++
|
||||
library/coretests/tests/slice.rs | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
|
||||
index 8402833..84592e0 100644
|
||||
--- a/library/core/tests/slice.rs
|
||||
+++ b/library/core/tests/slice.rs
|
||||
@@ -2462,6 +2462,7 @@ take_tests! {
|
||||
diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs
|
||||
index d17e681..fba5cd6 100644
|
||||
--- a/library/coretests/tests/slice.rs
|
||||
+++ b/library/coretests/tests/slice.rs
|
||||
@@ -2486,6 +2486,7 @@ split_off_tests! {
|
||||
#[cfg(not(miri))] // unused in Miri
|
||||
const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
|
||||
|
||||
|
@ -19,14 +19,14 @@ index 8402833..84592e0 100644
|
|||
// can't be a constant due to const mutability rules
|
||||
#[cfg(not(miri))] // unused in Miri
|
||||
macro_rules! empty_max_mut {
|
||||
@@ -2485,6 +2486,7 @@ take_tests! {
|
||||
(take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
|
||||
(take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
|
||||
@@ -2509,6 +2510,7 @@ split_off_tests! {
|
||||
(split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
|
||||
(split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
|
||||
}
|
||||
+*/
|
||||
|
||||
#[test]
|
||||
fn test_slice_from_ptr_range() {
|
||||
--
|
||||
2.26.2.7.g19db9cfb68
|
||||
2.49.0
|
||||
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
From 966beefe08be6045bfcca26079b76a7a80413080 Mon Sep 17 00:00:00 2001
|
||||
From b2911e732d1bf0e28872495c4c47af1dad3c7911 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Thu, 28 Sep 2023 17:37:38 -0400
|
||||
Date: Thu, 27 Mar 2025 14:30:10 -0400
|
||||
Subject: [PATCH] Disable libstd and libtest dylib
|
||||
|
||||
---
|
||||
library/std/Cargo.toml | 2 +-
|
||||
library/test/Cargo.toml | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
library/std/Cargo.toml | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
|
||||
index 5b21355..cb0c49b 100644
|
||||
index 176da60..c183cdb 100644
|
||||
--- a/library/std/Cargo.toml
|
||||
+++ b/library/std/Cargo.toml
|
||||
@@ -9,7 +9,7 @@ description = "The Rust Standard Library"
|
||||
edition = "2021"
|
||||
@@ -10,7 +10,7 @@ edition = "2024"
|
||||
autobenches = false
|
||||
|
||||
[lib]
|
||||
-crate-type = ["dylib", "rlib"]
|
||||
|
@ -21,3 +20,6 @@ index 5b21355..cb0c49b 100644
|
|||
|
||||
[dependencies]
|
||||
alloc = { path = "../alloc", public = true }
|
||||
--
|
||||
2.49.0
|
||||
|
||||
|
|
|
@ -1,25 +1,17 @@
|
|||
From 124a11ce086952a5794d5cfbaa45175809497b81 Mon Sep 17 00:00:00 2001
|
||||
From 1a8f6b8e39f343959d4d2e6b6957a6d780ac3fc0 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Sat, 18 Nov 2023 10:50:36 -0500
|
||||
Subject: [PATCH] [core] Disable portable-simd test
|
||||
Date: Thu, 27 Mar 2025 14:32:14 -0400
|
||||
Subject: [PATCH] Disable portable-simd test
|
||||
|
||||
---
|
||||
library/core/tests/lib.rs | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
library/coretests/tests/lib.rs | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
|
||||
index b71786c..cf484d5 100644
|
||||
--- a/library/core/tests/lib.rs
|
||||
+++ b/library/core/tests/lib.rs
|
||||
@@ -87,7 +87,6 @@
|
||||
#![feature(numfmt)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pointer_is_aligned_to)]
|
||||
-#![feature(portable_simd)]
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(slice_from_ptr_range)]
|
||||
#![feature(slice_internals)]
|
||||
@@ -155,7 +154,6 @@ mod pin;
|
||||
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
|
||||
index 79022fe..9223b2f 100644
|
||||
--- a/library/coretests/tests/lib.rs
|
||||
+++ b/library/coretests/tests/lib.rs
|
||||
@@ -165,7 +165,6 @@ mod pin;
|
||||
mod pin_macro;
|
||||
mod ptr;
|
||||
mod result;
|
||||
|
@ -27,4 +19,6 @@ index b71786c..cf484d5 100644
|
|||
mod slice;
|
||||
mod str;
|
||||
mod str_lossy;
|
||||
-- 2.45.2
|
||||
--
|
||||
2.49.0
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-01-12"
|
||||
channel = "nightly-2025-04-17"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
24
src/abi.rs
24
src/abi.rs
|
@ -1,6 +1,7 @@
|
|||
#[cfg(feature = "master")]
|
||||
use gccjit::FnAttribute;
|
||||
use gccjit::{ToLValue, ToRValue, Type};
|
||||
use rustc_abi::{Reg, RegKind};
|
||||
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::bug;
|
||||
|
@ -8,16 +9,16 @@ use rustc_middle::ty::Ty;
|
|||
use rustc_middle::ty::layout::LayoutOf;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_session::config;
|
||||
use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind};
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_target::callconv::Conv;
|
||||
use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::intrinsic::ArgAbiExt;
|
||||
use crate::type_of::LayoutGccExt;
|
||||
|
||||
impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
impl AbiBuilderMethods for Builder<'_, '_, '_> {
|
||||
fn get_param(&mut self, index: usize) -> Self::Value {
|
||||
let func = self.current_func();
|
||||
let param = func.get_param(index as i32);
|
||||
|
@ -136,10 +137,10 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
if cx.sess().opts.optimize == config::OptLevel::No {
|
||||
return ty;
|
||||
}
|
||||
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) {
|
||||
if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) {
|
||||
ty = ty.make_restrict()
|
||||
}
|
||||
if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) {
|
||||
if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) {
|
||||
non_null_args.push(arg_index as i32 + 1);
|
||||
}
|
||||
ty
|
||||
|
@ -238,7 +239,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
pub fn conv_to_fn_attribute<'gcc>(conv: Conv, _arch: &str) -> Option<FnAttribute<'gcc>> {
|
||||
pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute<'gcc>> {
|
||||
// TODO: handle the calling conventions returning None.
|
||||
let attribute = match conv {
|
||||
Conv::C
|
||||
|
@ -249,20 +250,21 @@ pub fn conv_to_fn_attribute<'gcc>(conv: Conv, _arch: &str) -> Option<FnAttribute
|
|||
Conv::Cold => return None,
|
||||
Conv::PreserveMost => return None,
|
||||
Conv::PreserveAll => return None,
|
||||
/*Conv::GpuKernel => {
|
||||
Conv::GpuKernel => {
|
||||
// TODO(antoyo): remove clippy allow attribute when this is implemented.
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
if arch == "amdgpu" {
|
||||
return None
|
||||
return None;
|
||||
} else if arch == "nvptx64" {
|
||||
return None
|
||||
return None;
|
||||
} else {
|
||||
panic!("Architecture {arch} does not support GpuKernel calling convention");
|
||||
panic!("Architecture {} does not support GpuKernel calling convention", arch);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
Conv::AvrInterrupt => return None,
|
||||
Conv::AvrNonBlockingInterrupt => return None,
|
||||
Conv::ArmAapcs => return None,
|
||||
Conv::Msp430Intr => return None,
|
||||
Conv::PtxKernel => return None,
|
||||
Conv::X86Fastcall => return None,
|
||||
Conv::X86Intr => return None,
|
||||
Conv::X86Stdcall => return None,
|
||||
|
|
|
@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::OomStrategy;
|
||||
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||
|
||||
use crate::GccContext;
|
||||
#[cfg(feature = "master")]
|
||||
|
@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen(
|
|||
panic!("invalid allocator output")
|
||||
}
|
||||
};
|
||||
let from_name = global_fn_name(method.name);
|
||||
let to_name = default_fn_name(method.name);
|
||||
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
|
||||
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
|
||||
|
||||
create_wrapper_function(tcx, context, &from_name, &to_name, &types, output);
|
||||
}
|
||||
|
@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen(
|
|||
create_wrapper_function(
|
||||
tcx,
|
||||
context,
|
||||
"__rust_alloc_error_handler",
|
||||
alloc_error_handler_name(alloc_error_handler_kind),
|
||||
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
|
||||
&[usize, usize],
|
||||
None,
|
||||
);
|
||||
|
||||
let name = OomStrategy::SYMBOL.to_string();
|
||||
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
|
||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||
#[cfg(feature = "master")]
|
||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
|
@ -80,7 +81,7 @@ pub(crate) unsafe fn codegen(
|
|||
let value = context.new_rvalue_from_int(i8, value as i32);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
|
||||
let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE);
|
||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||
#[cfg(feature = "master")]
|
||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
|
|
|
@ -632,17 +632,16 @@ pub unsafe fn optimize_thin_module(
|
|||
Arc::new(SyncContext::new(context))
|
||||
}
|
||||
};
|
||||
let module = ModuleCodegen {
|
||||
module_llvm: GccContext {
|
||||
let module = ModuleCodegen::new_regular(
|
||||
thin_module.name().to_string(),
|
||||
GccContext {
|
||||
context,
|
||||
should_combine_object_files,
|
||||
// TODO(antoyo): use the correct relocation model here.
|
||||
relocation_model: RelocModel::Pic,
|
||||
temp_dir: None,
|
||||
},
|
||||
name: thin_module.name().to_string(),
|
||||
kind: ModuleKind::Regular,
|
||||
};
|
||||
);
|
||||
/*{
|
||||
let target = &*module.module_llvm.tm;
|
||||
let llmod = module.module_llvm.llmod();
|
||||
|
@ -710,10 +709,6 @@ pub struct ThinBuffer {
|
|||
context: Arc<SyncContext>,
|
||||
}
|
||||
|
||||
// TODO: check if this makes sense to make ThinBuffer Send and Sync.
|
||||
unsafe impl Send for ThinBuffer {}
|
||||
unsafe impl Sync for ThinBuffer {}
|
||||
|
||||
impl ThinBuffer {
|
||||
pub(crate) fn new(context: &Arc<SyncContext>) -> Self {
|
||||
Self { context: Arc::clone(context) }
|
||||
|
|
|
@ -24,19 +24,23 @@ pub(crate) unsafe fn codegen(
|
|||
{
|
||||
let context = &module.module_llvm.context;
|
||||
|
||||
let module_name = module.name.clone();
|
||||
|
||||
let should_combine_object_files = module.module_llvm.should_combine_object_files;
|
||||
|
||||
let module_name = Some(&module_name[..]);
|
||||
|
||||
// NOTE: Only generate object files with GIMPLE when this environment variable is set for
|
||||
// now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit).
|
||||
// TODO(antoyo): remove this environment variable.
|
||||
let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1");
|
||||
|
||||
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
|
||||
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
|
||||
let bc_out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Bitcode,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
let obj_out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Object,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
|
||||
if config.bitcode_needed() {
|
||||
if fat_lto {
|
||||
|
@ -117,14 +121,22 @@ pub(crate) unsafe fn codegen(
|
|||
}
|
||||
|
||||
if config.emit_ir {
|
||||
let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
|
||||
let out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::LlvmAssembly,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
std::fs::write(out, "").expect("write file");
|
||||
}
|
||||
|
||||
if config.emit_asm {
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name);
|
||||
let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
||||
let path = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Assembly,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str"));
|
||||
}
|
||||
|
||||
|
@ -238,6 +250,7 @@ pub(crate) unsafe fn codegen(
|
|||
config.emit_asm,
|
||||
config.emit_ir,
|
||||
&cgcx.output_filenames,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
15
src/base.rs
15
src/base.rs
|
@ -4,10 +4,10 @@ use std::sync::Arc;
|
|||
use std::time::Instant;
|
||||
|
||||
use gccjit::{CType, Context, FunctionType, GlobalKind};
|
||||
use rustc_codegen_ssa::ModuleCodegen;
|
||||
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
||||
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
||||
use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
|
||||
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
|
||||
use rustc_middle::dep_graph;
|
||||
use rustc_middle::mir::mono::Linkage;
|
||||
#[cfg(feature = "master")]
|
||||
|
@ -49,9 +49,7 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
|
|||
Linkage::LinkOnceODR => unimplemented!(),
|
||||
Linkage::WeakAny => unimplemented!(),
|
||||
Linkage::WeakODR => unimplemented!(),
|
||||
Linkage::Appending => unimplemented!(),
|
||||
Linkage::Internal => GlobalKind::Internal,
|
||||
Linkage::Private => GlobalKind::Internal,
|
||||
Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage.
|
||||
Linkage::Common => unimplemented!(),
|
||||
}
|
||||
|
@ -66,9 +64,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
|
|||
Linkage::LinkOnceODR => unimplemented!(),
|
||||
Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce.
|
||||
Linkage::WeakODR => unimplemented!(),
|
||||
Linkage::Appending => unimplemented!(),
|
||||
Linkage::Internal => FunctionType::Internal,
|
||||
Linkage::Private => FunctionType::Internal,
|
||||
Linkage::ExternalWeak => unimplemented!(),
|
||||
Linkage::Common => unimplemented!(),
|
||||
}
|
||||
|
@ -241,16 +237,15 @@ pub fn compile_codegen_unit(
|
|||
}
|
||||
}
|
||||
|
||||
ModuleCodegen {
|
||||
name: cgu_name.to_string(),
|
||||
module_llvm: GccContext {
|
||||
ModuleCodegen::new_regular(
|
||||
cgu_name.to_string(),
|
||||
GccContext {
|
||||
context: Arc::new(SyncContext::new(context)),
|
||||
relocation_model: tcx.sess.relocation_model(),
|
||||
should_combine_object_files: false,
|
||||
temp_dir: None,
|
||||
},
|
||||
kind: ModuleKind::Regular,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
(module, cost)
|
||||
|
|
|
@ -29,7 +29,7 @@ use rustc_middle::ty::layout::{
|
|||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi};
|
||||
|
||||
use crate::common::{SignType, TypeReflection, type_is_pointer};
|
||||
|
@ -155,14 +155,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
// NOTE: not sure why, but we have the wrong type here.
|
||||
let int_type = compare_exchange.get_param(2).to_rvalue().get_type();
|
||||
let src = self.context.new_bitcast(self.location, src, int_type);
|
||||
self.context.new_call(self.location, compare_exchange, &[
|
||||
dst,
|
||||
expected,
|
||||
src,
|
||||
weak,
|
||||
order,
|
||||
failure_order,
|
||||
])
|
||||
self.context.new_call(
|
||||
self.location,
|
||||
compare_exchange,
|
||||
&[dst, expected, src, weak, order, failure_order],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) {
|
||||
|
@ -660,6 +657,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
a + b
|
||||
}
|
||||
|
||||
// TODO(antoyo): should we also override the `unchecked_` versions?
|
||||
fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
self.gcc_sub(a, b)
|
||||
}
|
||||
|
@ -827,31 +825,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
set_rvalue_location(self, self.gcc_not(a))
|
||||
}
|
||||
|
||||
fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
set_rvalue_location(self, self.gcc_add(a, b))
|
||||
}
|
||||
|
||||
fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
set_rvalue_location(self, self.gcc_add(a, b))
|
||||
}
|
||||
|
||||
fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
set_rvalue_location(self, self.gcc_sub(a, b))
|
||||
}
|
||||
|
||||
fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
// TODO(antoyo): should generate poison value?
|
||||
set_rvalue_location(self, self.gcc_sub(a, b))
|
||||
}
|
||||
|
||||
fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
set_rvalue_location(self, self.gcc_mul(a, b))
|
||||
}
|
||||
|
||||
fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
set_rvalue_location(self, self.gcc_mul(a, b))
|
||||
}
|
||||
|
||||
fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
|
||||
// NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
|
||||
set_rvalue_location(self, lhs + rhs)
|
||||
|
@ -1008,10 +981,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
OperandValue::Ref(place.val)
|
||||
} else if place.layout.is_gcc_immediate() {
|
||||
let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align);
|
||||
if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
|
||||
scalar_load_metadata(self, load, scalar);
|
||||
}
|
||||
OperandValue::Immediate(self.to_immediate(load, place.layout))
|
||||
OperandValue::Immediate(
|
||||
if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
|
||||
scalar_load_metadata(self, load, scalar);
|
||||
self.to_immediate_scalar(load, *scalar)
|
||||
} else {
|
||||
load
|
||||
},
|
||||
)
|
||||
} else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr {
|
||||
let b_offset = a.size(self).align_to(b.align(self).abi);
|
||||
|
||||
|
@ -1068,9 +1045,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
let align = dest.val.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
|
||||
cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align));
|
||||
|
||||
let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[
|
||||
self.const_usize(1),
|
||||
]);
|
||||
let next = self.inbounds_gep(
|
||||
self.backend_type(cg_elem.layout),
|
||||
current.to_rvalue(),
|
||||
&[self.const_usize(1)],
|
||||
);
|
||||
self.llbb().add_assignment(self.location, current, next);
|
||||
self.br(header_bb);
|
||||
|
||||
|
@ -1754,7 +1733,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
|
||||
if scalar.is_bool() {
|
||||
return self.trunc(val, self.cx().type_i1());
|
||||
return self.unchecked_utrunc(val, self.cx().type_i1());
|
||||
}
|
||||
val
|
||||
}
|
||||
|
@ -2495,9 +2474,5 @@ fn get_maybe_pointer_size(value: RValue<'_>) -> u32 {
|
|||
#[cfg(not(feature = "master"))]
|
||||
fn get_maybe_pointer_size(value: RValue<'_>) -> u32 {
|
||||
let type_ = value.get_type();
|
||||
if type_.get_pointee().is_some() {
|
||||
std::mem::size_of::<*const ()>() as _
|
||||
} else {
|
||||
type_.get_size()
|
||||
}
|
||||
if type_.get_pointee().is_some() { size_of::<*const ()>() as _ } else { type_.get_size() }
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool {
|
|||
typ.get_pointee().is_some()
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
|
||||
fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
|
||||
}
|
||||
|
@ -141,13 +141,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
fn const_str(&self, s: &str) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
let str_global = *self
|
||||
.const_str_cache
|
||||
.borrow_mut()
|
||||
.raw_entry_mut()
|
||||
.from_key(s)
|
||||
.or_insert_with(|| (s.to_owned(), self.global_string(s)))
|
||||
.1;
|
||||
let mut const_str_cache = self.const_str_cache.borrow_mut();
|
||||
let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| {
|
||||
let g = self.global_string(s);
|
||||
const_str_cache.insert(s.to_owned(), g);
|
||||
g
|
||||
});
|
||||
let len = s.len();
|
||||
let cs = self.const_ptrcast(
|
||||
str_global.get_address(None),
|
||||
|
@ -229,7 +228,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
let alloc = self
|
||||
.tcx
|
||||
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
|
||||
.global_alloc(self.tcx.vtable_allocation((
|
||||
ty,
|
||||
dyn_ty.principal().map(|principal| {
|
||||
self.tcx.instantiate_bound_regions_with_erased(principal)
|
||||
}),
|
||||
)))
|
||||
.unwrap_memory();
|
||||
let init = const_alloc_to_gcc(self, alloc);
|
||||
self.static_addr_of(init, alloc.inner().align, None)
|
||||
|
@ -253,7 +257,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
|
||||
fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value {
|
||||
const_alloc_to_gcc(self, alloc)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#[cfg(feature = "master")]
|
||||
use gccjit::{FnAttribute, VarAttribute, Visibility};
|
||||
use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type};
|
||||
use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange};
|
||||
use rustc_codegen_ssa::traits::{
|
||||
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
|
||||
};
|
||||
|
@ -14,7 +15,6 @@ use rustc_middle::ty::layout::LayoutOf;
|
|||
use rustc_middle::ty::{self, Instance};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
|
||||
|
||||
use crate::base;
|
||||
use crate::context::CodegenCx;
|
||||
|
@ -131,7 +131,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
|
|||
// will use load-unaligned instructions instead, and thus avoiding the crash.
|
||||
//
|
||||
// We could remove this hack whenever we decide to drop macOS 10.10 support.
|
||||
if self.tcx.sess.target.options.is_like_osx {
|
||||
if self.tcx.sess.target.options.is_like_darwin {
|
||||
// The `inspect` method is okay here because we checked for provenance, and
|
||||
// because we are doing this access to inspect the final interpreter state
|
||||
// (not as part of the interpreter execution).
|
||||
|
@ -302,9 +302,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn const_alloc_to_gcc<'gcc, 'tcx>(
|
||||
cx: &CodegenCx<'gcc, 'tcx>,
|
||||
alloc: ConstAllocation<'tcx>,
|
||||
pub fn const_alloc_to_gcc<'gcc>(
|
||||
cx: &CodegenCx<'gcc, '_>,
|
||||
alloc: ConstAllocation<'_>,
|
||||
) -> RValue<'gcc> {
|
||||
let alloc = alloc.inner();
|
||||
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
|
||||
|
@ -364,6 +364,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(
|
|||
llvals.push(cx.const_bytes(bytes));
|
||||
}
|
||||
|
||||
// FIXME(bjorn3) avoid wrapping in a struct when there is only a single element.
|
||||
cx.const_struct(&llvals, true)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell};
|
|||
use gccjit::{
|
||||
Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type,
|
||||
};
|
||||
use rustc_abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
|
||||
use rustc_codegen_ssa::base::wants_msvc_seh;
|
||||
use rustc_codegen_ssa::errors as ssa_errors;
|
||||
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods};
|
||||
|
@ -14,11 +15,10 @@ use rustc_middle::ty::layout::{
|
|||
FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
|
||||
LayoutOfHelpers,
|
||||
};
|
||||
use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
|
||||
use rustc_target::spec::{
|
||||
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi,
|
||||
};
|
||||
|
@ -92,7 +92,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
|
|||
pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
|
||||
/// Cache generated vtables
|
||||
pub vtables:
|
||||
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
|
||||
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
|
||||
|
||||
// TODO(antoyo): improve the SSA API to not require those.
|
||||
/// Mapping from function pointer type to indexes of on stack parameters.
|
||||
|
@ -215,33 +215,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let bool_type = context.new_type::<bool>();
|
||||
|
||||
let mut functions = FxHashMap::default();
|
||||
let builtins = [
|
||||
"__builtin_unreachable",
|
||||
"abort",
|
||||
"__builtin_expect", /*"__builtin_expect_with_probability",*/
|
||||
"__builtin_constant_p",
|
||||
"__builtin_add_overflow",
|
||||
"__builtin_mul_overflow",
|
||||
"__builtin_saddll_overflow",
|
||||
/*"__builtin_sadd_overflow",*/
|
||||
"__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/
|
||||
"__builtin_ssubll_overflow",
|
||||
/*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow",
|
||||
"__builtin_uaddll_overflow",
|
||||
"__builtin_uadd_overflow",
|
||||
"__builtin_umulll_overflow",
|
||||
"__builtin_umul_overflow",
|
||||
"__builtin_usubll_overflow",
|
||||
"__builtin_usub_overflow",
|
||||
"__builtin_powif",
|
||||
"__builtin_powi",
|
||||
"fabsf",
|
||||
"fabs",
|
||||
"copysignf",
|
||||
"copysign",
|
||||
"nearbyintf",
|
||||
"nearbyint",
|
||||
];
|
||||
let builtins = ["abort"];
|
||||
|
||||
for builtin in builtins.iter() {
|
||||
functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
|
||||
|
@ -403,7 +377,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
|
|||
impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn vtables(
|
||||
&self,
|
||||
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
|
||||
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
|
||||
&self.vtables
|
||||
}
|
||||
|
||||
|
@ -519,7 +493,6 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
} else {
|
||||
// If the symbol already exists, it is an error: for example, the user wrote
|
||||
// #[no_mangle] extern "C" fn main(..) {..}
|
||||
// instead of #[start]
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
|
||||
use gccjit::{Location, RValue};
|
||||
use rustc_abi::Size;
|
||||
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
||||
use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_index::bit_set::DenseBitSet;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::mir::{self, Body, SourceScope};
|
||||
use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
|
||||
use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty};
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol};
|
||||
use rustc_target::abi::Size;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
|
@ -113,15 +113,15 @@ fn make_mir_scope<'gcc, 'tcx>(
|
|||
let scope_data = &mir.source_scopes[scope];
|
||||
let parent_scope = if let Some(parent) = scope_data.parent_scope {
|
||||
make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent);
|
||||
debug_context.scopes[parent].unwrap()
|
||||
debug_context.scopes[parent]
|
||||
} else {
|
||||
// The root is the function itself.
|
||||
let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
|
||||
debug_context.scopes[scope] = Some(DebugScope {
|
||||
debug_context.scopes[scope] = DebugScope {
|
||||
file_start_pos: file.start_pos,
|
||||
file_end_pos: file.end_position(),
|
||||
..debug_context.scopes[scope].unwrap()
|
||||
});
|
||||
..debug_context.scopes[scope]
|
||||
};
|
||||
instantiated.insert(scope);
|
||||
return;
|
||||
};
|
||||
|
@ -130,7 +130,7 @@ fn make_mir_scope<'gcc, 'tcx>(
|
|||
if !vars.contains(scope) && scope_data.inlined.is_none() {
|
||||
// Do not create a DIScope if there are no variables defined in this
|
||||
// MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
|
||||
debug_context.scopes[scope] = Some(parent_scope);
|
||||
debug_context.scopes[scope] = parent_scope;
|
||||
instantiated.insert(scope);
|
||||
return;
|
||||
}
|
||||
|
@ -157,12 +157,12 @@ fn make_mir_scope<'gcc, 'tcx>(
|
|||
// TODO(tempdragon): dbg_scope: Add support for scope extension here.
|
||||
inlined_at.or(p_inlined_at);
|
||||
|
||||
debug_context.scopes[scope] = Some(DebugScope {
|
||||
debug_context.scopes[scope] = DebugScope {
|
||||
dbg_scope,
|
||||
inlined_at,
|
||||
file_start_pos: loc.file.start_pos,
|
||||
file_end_pos: loc.file.end_position(),
|
||||
});
|
||||
};
|
||||
instantiated.insert(scope);
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ fn make_mir_scope<'gcc, 'tcx>(
|
|||
// `lookup_char_pos` return the right information instead.
|
||||
pub struct DebugLoc {
|
||||
/// Information about the original source file.
|
||||
pub file: Lrc<SourceFile>,
|
||||
pub file: Arc<SourceFile>,
|
||||
/// The (1-based) line number.
|
||||
pub line: u32,
|
||||
/// The (1-based) column number.
|
||||
|
@ -214,7 +214,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
fn create_vtable_debuginfo(
|
||||
&self,
|
||||
_ty: Ty<'tcx>,
|
||||
_trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
|
||||
_trait_ref: Option<ExistentialTraitRef<'tcx>>,
|
||||
_vtable: Self::Value,
|
||||
) {
|
||||
// TODO(antoyo)
|
||||
|
@ -232,12 +232,12 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
|
||||
// Initialize fn debug context (including scopes).
|
||||
let empty_scope = Some(DebugScope {
|
||||
let empty_scope = DebugScope {
|
||||
dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)),
|
||||
inlined_at: None,
|
||||
file_start_pos: BytePos(0),
|
||||
file_end_pos: BytePos(0),
|
||||
});
|
||||
};
|
||||
let mut fn_debug_context = FunctionDebugContext {
|
||||
scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()),
|
||||
inlined_function_scopes: Default::default(),
|
||||
|
|
|
@ -4,7 +4,7 @@ use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type};
|
|||
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt};
|
||||
use crate::context::CodegenCx;
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use std::iter::FromIterator;
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::Context;
|
||||
use rustc_codegen_ssa::codegen_attrs::check_tied_features;
|
||||
use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_session::Session;
|
||||
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
|
||||
|
@ -45,18 +43,12 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
|||
let known_features = sess.target.rust_target_features();
|
||||
let mut featsmap = FxHashMap::default();
|
||||
|
||||
// Ensure that all ABI-required features are enabled, and the ABI-forbidden ones
|
||||
// are disabled.
|
||||
let abi_feature_constraints = sess.target.abi_required_features();
|
||||
let abi_incompatible_set =
|
||||
FxHashSet::from_iter(abi_feature_constraints.incompatible.iter().copied());
|
||||
|
||||
// Compute implied features
|
||||
let mut all_rust_features = vec![];
|
||||
for feature in sess.opts.cg.target_feature.split(',') {
|
||||
if let Some(feature) = feature.strip_prefix('+') {
|
||||
all_rust_features.extend(
|
||||
UnordSet::from(sess.target.implied_target_features(std::iter::once(feature)))
|
||||
UnordSet::from(sess.target.implied_target_features(feature))
|
||||
.to_sorted_stable_ord()
|
||||
.iter()
|
||||
.map(|&&s| (true, s)),
|
||||
|
@ -117,51 +109,11 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure that the features we enable/disable are compatible with the ABI.
|
||||
if enable {
|
||||
if abi_incompatible_set.contains(feature) {
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature {
|
||||
feature,
|
||||
enabled: "enabled",
|
||||
reason: "this feature is incompatible with the target ABI",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// FIXME: we have to request implied features here since
|
||||
// negative features do not handle implied features above.
|
||||
for &required in abi_feature_constraints.required.iter() {
|
||||
let implied = sess.target.implied_target_features(std::iter::once(required));
|
||||
if implied.contains(feature) {
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature {
|
||||
feature,
|
||||
enabled: "disabled",
|
||||
reason: "this feature is required by the target ABI",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(nagisa): figure out how to not allocate a full hashset here.
|
||||
featsmap.insert(feature, enable);
|
||||
}
|
||||
}
|
||||
|
||||
// To be sure the ABI-relevant features are all in the right state, we explicitly
|
||||
// (un)set them here. This means if the target spec sets those features wrong,
|
||||
// we will silently correct them rather than silently producing wrong code.
|
||||
// (The target sanity check tries to catch this, but we can't know which features are
|
||||
// enabled in GCC by default so we can't be fully sure about that check.)
|
||||
// We add these at the beginning of the list so that `-Ctarget-features` can
|
||||
// still override it... that's unsound, but more compatible with past behavior.
|
||||
all_rust_features.splice(
|
||||
0..0,
|
||||
abi_feature_constraints
|
||||
.required
|
||||
.iter()
|
||||
.map(|&f| (true, f))
|
||||
.chain(abi_feature_constraints.incompatible.iter().map(|&f| (false, f))),
|
||||
);
|
||||
|
||||
// Translate this into GCC features.
|
||||
let feats =
|
||||
all_rust_features.iter().flat_map(|&(enable, feature)| {
|
||||
|
|
137
src/int.rs
137
src/int.rs
|
@ -3,12 +3,11 @@
|
|||
//! 128-bit integers on 32-bit platforms and thus require to be handled manually.
|
||||
|
||||
use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp};
|
||||
use rustc_abi::{Endian, ExternAbi};
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_target::abi::Endian;
|
||||
use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
|
||||
use rustc_target::spec;
|
||||
use rustc_target::callconv::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
|
||||
|
||||
use crate::builder::{Builder, ToGccComp};
|
||||
use crate::common::{SignType, TypeReflection};
|
||||
|
@ -322,36 +321,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
},
|
||||
}
|
||||
} else {
|
||||
match new_kind {
|
||||
Int(I128) | Uint(U128) => {
|
||||
let func_name = match oop {
|
||||
OverflowOp::Add => match new_kind {
|
||||
Int(I128) => "__rust_i128_addo",
|
||||
Uint(U128) => "__rust_u128_addo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Sub => match new_kind {
|
||||
Int(I128) => "__rust_i128_subo",
|
||||
Uint(U128) => "__rust_u128_subo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead?
|
||||
Uint(U128) => "__rust_u128_mulo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
return self.operation_with_overflow(func_name, lhs, rhs);
|
||||
}
|
||||
_ => match oop {
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I32) => "__mulosi4",
|
||||
Int(I64) => "__mulodi4",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => unimplemented!("overflow operation for {:?}", new_kind),
|
||||
let (func_name, width) = match oop {
|
||||
OverflowOp::Add => match new_kind {
|
||||
Int(I128) => ("__rust_i128_addo", 128),
|
||||
Uint(U128) => ("__rust_u128_addo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
}
|
||||
OverflowOp::Sub => match new_kind {
|
||||
Int(I128) => ("__rust_i128_subo", 128),
|
||||
Uint(U128) => ("__rust_u128_subo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I32) => ("__mulosi4", 32),
|
||||
Int(I64) => ("__mulodi4", 64),
|
||||
Int(I128) => ("__rust_i128_mulo", 128), // TODO(antoyo): use __muloti4d instead?
|
||||
Uint(U128) => ("__rust_u128_mulo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
return self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
};
|
||||
|
||||
let intrinsic = self.context.get_builtin_function(name);
|
||||
|
@ -364,80 +353,96 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
(res.dereference(self.location).to_rvalue(), overflow)
|
||||
}
|
||||
|
||||
/// Non-`__builtin_*` overflow operations with a `fn(T, T, &mut i32) -> T` signature.
|
||||
pub fn operation_with_overflow(
|
||||
&self,
|
||||
func_name: &str,
|
||||
lhs: RValue<'gcc>,
|
||||
rhs: RValue<'gcc>,
|
||||
width: u64,
|
||||
) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
debug_assert!(a_type.dyncast_array().is_some());
|
||||
debug_assert!(b_type.dyncast_array().is_some());
|
||||
let overflow_type = self.i32_type;
|
||||
let overflow_param_type = overflow_type.make_pointer();
|
||||
let res_type = a_type;
|
||||
|
||||
let overflow_value =
|
||||
self.current_func().new_local(self.location, overflow_type, "overflow");
|
||||
let overflow_addr = overflow_value.get_address(self.location);
|
||||
|
||||
let param_a = self.context.new_parameter(self.location, a_type, "a");
|
||||
let param_b = self.context.new_parameter(self.location, b_type, "b");
|
||||
let result_field = self.context.new_field(self.location, a_type, "result");
|
||||
let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow");
|
||||
let param_overflow =
|
||||
self.context.new_parameter(self.location, overflow_param_type, "overflow");
|
||||
|
||||
let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
|
||||
let a_elem_type = a_type.dyncast_array().expect("non-array a value");
|
||||
debug_assert!(a_elem_type.is_integral());
|
||||
let res_ty = match width {
|
||||
32 => self.tcx.types.i32,
|
||||
64 => self.tcx.types.i64,
|
||||
128 => self.tcx.types.i128,
|
||||
_ => unreachable!("unexpected integer size"),
|
||||
};
|
||||
let layout = self
|
||||
.tcx
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty))
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(res_ty))
|
||||
.unwrap();
|
||||
|
||||
let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
|
||||
let mut fn_abi = FnAbi {
|
||||
args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
|
||||
args: vec![arg_abi.clone(), arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
|
||||
ret: arg_abi,
|
||||
c_variadic: false,
|
||||
fixed_count: 2,
|
||||
fixed_count: 3,
|
||||
conv: Conv::C,
|
||||
can_unwind: false,
|
||||
};
|
||||
fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap();
|
||||
fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false });
|
||||
|
||||
let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
|
||||
let call = if ret_indirect {
|
||||
let res_value = self.current_func().new_local(self.location, res_type, "result_value");
|
||||
let res_addr = res_value.get_address(self.location);
|
||||
let res_param_type = res_type.make_pointer();
|
||||
let param_res = self.context.new_parameter(self.location, res_param_type, "result");
|
||||
|
||||
let return_type = self
|
||||
.context
|
||||
.new_struct_type(self.location, "result_overflow", &[result_field, overflow_field]);
|
||||
let result = if indirect {
|
||||
let return_value =
|
||||
self.current_func().new_local(self.location, return_type.as_type(), "return_value");
|
||||
let return_param_type = return_type.as_type().make_pointer();
|
||||
let return_param =
|
||||
self.context.new_parameter(self.location, return_param_type, "return_value");
|
||||
let func = self.context.new_function(
|
||||
self.location,
|
||||
FunctionType::Extern,
|
||||
self.type_void(),
|
||||
&[return_param, param_a, param_b],
|
||||
&[param_res, param_a, param_b, param_overflow],
|
||||
func_name,
|
||||
false,
|
||||
);
|
||||
self.llbb().add_eval(
|
||||
self.location,
|
||||
self.context.new_call(self.location, func, &[
|
||||
return_value.get_address(self.location),
|
||||
lhs,
|
||||
rhs,
|
||||
]),
|
||||
);
|
||||
return_value.to_rvalue()
|
||||
let _void =
|
||||
self.context.new_call(self.location, func, &[res_addr, lhs, rhs, overflow_addr]);
|
||||
res_value.to_rvalue()
|
||||
} else {
|
||||
let func = self.context.new_function(
|
||||
self.location,
|
||||
FunctionType::Extern,
|
||||
return_type.as_type(),
|
||||
&[param_a, param_b],
|
||||
res_type,
|
||||
&[param_a, param_b, param_overflow],
|
||||
func_name,
|
||||
false,
|
||||
);
|
||||
self.context.new_call(self.location, func, &[lhs, rhs])
|
||||
self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr])
|
||||
};
|
||||
let overflow = result.access_field(self.location, overflow_field);
|
||||
let int_result = result.access_field(self.location, result_field);
|
||||
(int_result, overflow)
|
||||
// NOTE: we must assign the result of the operation to a variable at this point to make
|
||||
// sure it will be evaluated by libgccjit now.
|
||||
// Otherwise, it will only be evaluated when the rvalue for the call is used somewhere else
|
||||
// and overflow_value will not be initialized at the correct point in the program.
|
||||
let result = self.current_func().new_local(self.location, res_type, "result");
|
||||
self.block.add_assignment(self.location, result, call);
|
||||
|
||||
(
|
||||
result.to_rvalue(),
|
||||
self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn gcc_icmp(
|
||||
|
@ -869,6 +874,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let value_type = value.get_type();
|
||||
if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type)
|
||||
{
|
||||
// TODO: use self.location.
|
||||
self.context.new_cast(None, value, dest_typ)
|
||||
} else if self.is_native_int_type_or_bool(dest_typ) {
|
||||
self.context.new_cast(None, self.low(value), dest_typ)
|
||||
|
@ -909,6 +915,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let name_suffix = match self.type_kind(dest_typ) {
|
||||
TypeKind::Float => "tisf",
|
||||
TypeKind::Double => "tidf",
|
||||
TypeKind::FP128 => "tixf",
|
||||
kind => panic!("cannot cast a non-native integer to type {:?}", kind),
|
||||
};
|
||||
let sign = if signed { "" } else { "un" };
|
||||
|
|
|
@ -1,11 +1,90 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue};
|
||||
use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type};
|
||||
use rustc_codegen_ssa::traits::BuilderMethods;
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
|
||||
fn encode_key_128_type<'a, 'gcc, 'tcx>(
|
||||
builder: &Builder<'a, 'gcc, 'tcx>,
|
||||
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
|
||||
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
|
||||
let field1 = builder.context.new_field(None, builder.u32_type, "field1");
|
||||
let field2 = builder.context.new_field(None, m128i, "field2");
|
||||
let field3 = builder.context.new_field(None, m128i, "field3");
|
||||
let field4 = builder.context.new_field(None, m128i, "field4");
|
||||
let field5 = builder.context.new_field(None, m128i, "field5");
|
||||
let field6 = builder.context.new_field(None, m128i, "field6");
|
||||
let field7 = builder.context.new_field(None, m128i, "field7");
|
||||
let encode_type = builder.context.new_struct_type(
|
||||
None,
|
||||
"EncodeKey128Output",
|
||||
&[field1, field2, field3, field4, field5, field6, field7],
|
||||
);
|
||||
#[cfg(feature = "master")]
|
||||
encode_type.as_type().set_packed();
|
||||
(encode_type.as_type(), field1, field2)
|
||||
}
|
||||
|
||||
fn encode_key_256_type<'a, 'gcc, 'tcx>(
|
||||
builder: &Builder<'a, 'gcc, 'tcx>,
|
||||
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
|
||||
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
|
||||
let field1 = builder.context.new_field(None, builder.u32_type, "field1");
|
||||
let field2 = builder.context.new_field(None, m128i, "field2");
|
||||
let field3 = builder.context.new_field(None, m128i, "field3");
|
||||
let field4 = builder.context.new_field(None, m128i, "field4");
|
||||
let field5 = builder.context.new_field(None, m128i, "field5");
|
||||
let field6 = builder.context.new_field(None, m128i, "field6");
|
||||
let field7 = builder.context.new_field(None, m128i, "field7");
|
||||
let field8 = builder.context.new_field(None, m128i, "field8");
|
||||
let encode_type = builder.context.new_struct_type(
|
||||
None,
|
||||
"EncodeKey256Output",
|
||||
&[field1, field2, field3, field4, field5, field6, field7, field8],
|
||||
);
|
||||
#[cfg(feature = "master")]
|
||||
encode_type.as_type().set_packed();
|
||||
(encode_type.as_type(), field1, field2)
|
||||
}
|
||||
|
||||
fn aes_output_type<'a, 'gcc, 'tcx>(
|
||||
builder: &Builder<'a, 'gcc, 'tcx>,
|
||||
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
|
||||
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
|
||||
let field1 = builder.context.new_field(None, builder.u8_type, "field1");
|
||||
let field2 = builder.context.new_field(None, m128i, "field2");
|
||||
let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]);
|
||||
let typ = aes_output_type.as_type();
|
||||
#[cfg(feature = "master")]
|
||||
typ.set_packed();
|
||||
(typ, field1, field2)
|
||||
}
|
||||
|
||||
fn wide_aes_output_type<'a, 'gcc, 'tcx>(
|
||||
builder: &Builder<'a, 'gcc, 'tcx>,
|
||||
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
|
||||
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
|
||||
let field1 = builder.context.new_field(None, builder.u8_type, "field1");
|
||||
let field2 = builder.context.new_field(None, m128i, "field2");
|
||||
let field3 = builder.context.new_field(None, m128i, "field3");
|
||||
let field4 = builder.context.new_field(None, m128i, "field4");
|
||||
let field5 = builder.context.new_field(None, m128i, "field5");
|
||||
let field6 = builder.context.new_field(None, m128i, "field6");
|
||||
let field7 = builder.context.new_field(None, m128i, "field7");
|
||||
let field8 = builder.context.new_field(None, m128i, "field8");
|
||||
let field9 = builder.context.new_field(None, m128i, "field9");
|
||||
let aes_output_type = builder.context.new_struct_type(
|
||||
None,
|
||||
"WideAesOutput",
|
||||
&[field1, field2, field3, field4, field5, field6, field7, field8, field9],
|
||||
);
|
||||
#[cfg(feature = "master")]
|
||||
aes_output_type.as_type().set_packed();
|
||||
(aes_output_type.as_type(), field1, field2)
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
|
||||
pub fn adjust_function<'gcc>(
|
||||
context: &'gcc Context<'gcc>,
|
||||
|
@ -503,6 +582,72 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
|
|||
let arg4 = builder.context.new_rvalue_from_int(arg4_type, -1);
|
||||
args = vec![a, b, c, arg4, new_args[3]].into();
|
||||
}
|
||||
"__builtin_ia32_encodekey128_u32" => {
|
||||
let mut new_args = args.to_vec();
|
||||
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
|
||||
let array_type = builder.context.new_array_type(None, m128i, 6);
|
||||
let result = builder.current_func().new_local(None, array_type, "result");
|
||||
new_args.push(result.get_address(None));
|
||||
args = new_args.into();
|
||||
}
|
||||
"__builtin_ia32_encodekey256_u32" => {
|
||||
let mut new_args = args.to_vec();
|
||||
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
|
||||
let array_type = builder.context.new_array_type(None, m128i, 7);
|
||||
let result = builder.current_func().new_local(None, array_type, "result");
|
||||
new_args.push(result.get_address(None));
|
||||
args = new_args.into();
|
||||
}
|
||||
"__builtin_ia32_aesenc128kl_u8"
|
||||
| "__builtin_ia32_aesdec128kl_u8"
|
||||
| "__builtin_ia32_aesenc256kl_u8"
|
||||
| "__builtin_ia32_aesdec256kl_u8" => {
|
||||
let mut new_args = vec![];
|
||||
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
|
||||
let result = builder.current_func().new_local(None, m128i, "result");
|
||||
new_args.push(result.get_address(None));
|
||||
new_args.extend(args.to_vec());
|
||||
args = new_args.into();
|
||||
}
|
||||
"__builtin_ia32_aesencwide128kl_u8"
|
||||
| "__builtin_ia32_aesdecwide128kl_u8"
|
||||
| "__builtin_ia32_aesencwide256kl_u8"
|
||||
| "__builtin_ia32_aesdecwide256kl_u8" => {
|
||||
let mut new_args = vec![];
|
||||
|
||||
let mut old_args = args.to_vec();
|
||||
let handle = old_args.swap_remove(0); // Called __P in GCC.
|
||||
let first_value = old_args.swap_remove(0);
|
||||
|
||||
let element_type = first_value.get_type();
|
||||
let array_type = builder.context.new_array_type(None, element_type, 8);
|
||||
let result = builder.current_func().new_local(None, array_type, "result");
|
||||
new_args.push(result.get_address(None));
|
||||
|
||||
let array = builder.current_func().new_local(None, array_type, "array");
|
||||
let input = builder.context.new_array_constructor(
|
||||
None,
|
||||
array_type,
|
||||
&[
|
||||
first_value,
|
||||
old_args.swap_remove(0),
|
||||
old_args.swap_remove(0),
|
||||
old_args.swap_remove(0),
|
||||
old_args.swap_remove(0),
|
||||
old_args.swap_remove(0),
|
||||
old_args.swap_remove(0),
|
||||
old_args.swap_remove(0),
|
||||
],
|
||||
);
|
||||
builder.llbb().add_assignment(None, array, input);
|
||||
let input_ptr = array.get_address(None);
|
||||
let arg2_type = gcc_func.get_param_type(1);
|
||||
let input_ptr = builder.context.new_cast(None, input_ptr, arg2_type);
|
||||
new_args.push(input_ptr);
|
||||
|
||||
new_args.push(handle);
|
||||
args = new_args.into();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
} else {
|
||||
|
@ -659,11 +804,12 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
|
|||
let field2 = builder.context.new_field(None, args[1].get_type(), "carryResult");
|
||||
let struct_type =
|
||||
builder.context.new_struct_type(None, "addcarryResult", &[field1, field2]);
|
||||
return_value =
|
||||
builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[
|
||||
return_value,
|
||||
last_arg.dereference(None).to_rvalue(),
|
||||
]);
|
||||
return_value = builder.context.new_struct_constructor(
|
||||
None,
|
||||
struct_type.as_type(),
|
||||
None,
|
||||
&[return_value, last_arg.dereference(None).to_rvalue()],
|
||||
);
|
||||
}
|
||||
}
|
||||
"__builtin_ia32_stmxcsr" => {
|
||||
|
@ -688,16 +834,107 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
|
|||
let field2 = builder.context.new_field(None, return_value.get_type(), "success");
|
||||
let struct_type =
|
||||
builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]);
|
||||
return_value =
|
||||
builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[
|
||||
random_number,
|
||||
success_variable.to_rvalue(),
|
||||
]);
|
||||
return_value = builder.context.new_struct_constructor(
|
||||
None,
|
||||
struct_type.as_type(),
|
||||
None,
|
||||
&[random_number, success_variable.to_rvalue()],
|
||||
);
|
||||
}
|
||||
"fma" => {
|
||||
let f16_type = builder.context.new_c_type(CType::Float16);
|
||||
return_value = builder.context.new_cast(None, return_value, f16_type);
|
||||
}
|
||||
"__builtin_ia32_encodekey128_u32" => {
|
||||
// The builtin __builtin_ia32_encodekey128_u32 writes the result in its pointer argument while
|
||||
// llvm.x86.encodekey128 returns a value.
|
||||
// We added a result pointer argument and now need to assign its value to the return_value expected by
|
||||
// the LLVM intrinsic.
|
||||
let (encode_type, field1, field2) = encode_key_128_type(builder);
|
||||
let result = builder.current_func().new_local(None, encode_type, "result");
|
||||
let field1 = result.access_field(None, field1);
|
||||
builder.llbb().add_assignment(None, field1, return_value);
|
||||
let field2 = result.access_field(None, field2);
|
||||
let field2_type = field2.to_rvalue().get_type();
|
||||
let array_type = builder.context.new_array_type(None, field2_type, 6);
|
||||
let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer());
|
||||
let field2_ptr =
|
||||
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
|
||||
builder.llbb().add_assignment(
|
||||
None,
|
||||
field2_ptr.dereference(None),
|
||||
ptr.dereference(None),
|
||||
);
|
||||
return_value = result.to_rvalue();
|
||||
}
|
||||
"__builtin_ia32_encodekey256_u32" => {
|
||||
// The builtin __builtin_ia32_encodekey256_u32 writes the result in its pointer argument while
|
||||
// llvm.x86.encodekey256 returns a value.
|
||||
// We added a result pointer argument and now need to assign its value to the return_value expected by
|
||||
// the LLVM intrinsic.
|
||||
let (encode_type, field1, field2) = encode_key_256_type(builder);
|
||||
let result = builder.current_func().new_local(None, encode_type, "result");
|
||||
let field1 = result.access_field(None, field1);
|
||||
builder.llbb().add_assignment(None, field1, return_value);
|
||||
let field2 = result.access_field(None, field2);
|
||||
let field2_type = field2.to_rvalue().get_type();
|
||||
let array_type = builder.context.new_array_type(None, field2_type, 7);
|
||||
let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer());
|
||||
let field2_ptr =
|
||||
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
|
||||
builder.llbb().add_assignment(
|
||||
None,
|
||||
field2_ptr.dereference(None),
|
||||
ptr.dereference(None),
|
||||
);
|
||||
return_value = result.to_rvalue();
|
||||
}
|
||||
"__builtin_ia32_aesdec128kl_u8"
|
||||
| "__builtin_ia32_aesenc128kl_u8"
|
||||
| "__builtin_ia32_aesdec256kl_u8"
|
||||
| "__builtin_ia32_aesenc256kl_u8" => {
|
||||
// The builtin for aesdec/aesenc writes the result in its pointer argument while
|
||||
// llvm.x86.aesdec128kl returns a value.
|
||||
// We added a result pointer argument and now need to assign its value to the return_value expected by
|
||||
// the LLVM intrinsic.
|
||||
let (aes_output_type, field1, field2) = aes_output_type(builder);
|
||||
let result = builder.current_func().new_local(None, aes_output_type, "result");
|
||||
let field1 = result.access_field(None, field1);
|
||||
builder.llbb().add_assignment(None, field1, return_value);
|
||||
let field2 = result.access_field(None, field2);
|
||||
let ptr = builder.context.new_cast(
|
||||
None,
|
||||
args[0],
|
||||
field2.to_rvalue().get_type().make_pointer(),
|
||||
);
|
||||
builder.llbb().add_assignment(None, field2, ptr.dereference(None));
|
||||
return_value = result.to_rvalue();
|
||||
}
|
||||
"__builtin_ia32_aesencwide128kl_u8"
|
||||
| "__builtin_ia32_aesdecwide128kl_u8"
|
||||
| "__builtin_ia32_aesencwide256kl_u8"
|
||||
| "__builtin_ia32_aesdecwide256kl_u8" => {
|
||||
// The builtin for aesdecwide/aesencwide writes the result in its pointer argument while
|
||||
// llvm.x86.aesencwide128kl returns a value.
|
||||
// We added a result pointer argument and now need to assign its value to the return_value expected by
|
||||
// the LLVM intrinsic.
|
||||
let (aes_output_type, field1, field2) = wide_aes_output_type(builder);
|
||||
let result = builder.current_func().new_local(None, aes_output_type, "result");
|
||||
let field1 = result.access_field(None, field1);
|
||||
builder.llbb().add_assignment(None, field1, return_value);
|
||||
let field2 = result.access_field(None, field2);
|
||||
let field2_type = field2.to_rvalue().get_type();
|
||||
let array_type = builder.context.new_array_type(None, field2_type, 8);
|
||||
let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer());
|
||||
let field2_ptr =
|
||||
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
|
||||
builder.llbb().add_assignment(
|
||||
None,
|
||||
field2_ptr.dereference(None),
|
||||
ptr.dereference(None),
|
||||
);
|
||||
return_value = result.to_rvalue();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
@ -1282,6 +1519,16 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
|
|||
"llvm.x86.avx512fp16.mask.vfmadd.cph.256" => "__builtin_ia32_vfmaddcph256_mask3",
|
||||
"llvm.x86.avx512fp16.mask.vfcmadd.cph.128" => "__builtin_ia32_vfcmaddcph128_mask3",
|
||||
"llvm.x86.avx512fp16.mask.vfmadd.cph.128" => "__builtin_ia32_vfmaddcph128_mask3",
|
||||
"llvm.x86.encodekey128" => "__builtin_ia32_encodekey128_u32",
|
||||
"llvm.x86.encodekey256" => "__builtin_ia32_encodekey256_u32",
|
||||
"llvm.x86.aesenc128kl" => "__builtin_ia32_aesenc128kl_u8",
|
||||
"llvm.x86.aesdec128kl" => "__builtin_ia32_aesdec128kl_u8",
|
||||
"llvm.x86.aesenc256kl" => "__builtin_ia32_aesenc256kl_u8",
|
||||
"llvm.x86.aesdec256kl" => "__builtin_ia32_aesdec256kl_u8",
|
||||
"llvm.x86.aesencwide128kl" => "__builtin_ia32_aesencwide128kl_u8",
|
||||
"llvm.x86.aesdecwide128kl" => "__builtin_ia32_aesdecwide128kl_u8",
|
||||
"llvm.x86.aesencwide256kl" => "__builtin_ia32_aesencwide256kl_u8",
|
||||
"llvm.x86.aesdecwide256kl" => "__builtin_ia32_aesdecwide256kl_u8",
|
||||
|
||||
// TODO: support the tile builtins:
|
||||
"llvm.x86.ldtilecfg" => "__builtin_trap",
|
||||
|
|
|
@ -7,6 +7,9 @@ use std::iter;
|
|||
#[cfg(feature = "master")]
|
||||
use gccjit::FunctionType;
|
||||
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_abi::{BackendRepr, HasDataLayout};
|
||||
use rustc_codegen_ssa::MemFlags;
|
||||
use rustc_codegen_ssa::base::wants_msvc_seh;
|
||||
use rustc_codegen_ssa::common::IntPredicate;
|
||||
|
@ -25,11 +28,8 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
|||
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_target::abi::HasDataLayout;
|
||||
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
|
||||
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
use crate::abi::FnAbiGccExt;
|
||||
|
@ -78,20 +78,18 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
|
|||
sym::maxnumf64 => "fmax",
|
||||
sym::copysignf32 => "copysignf",
|
||||
sym::copysignf64 => "copysign",
|
||||
sym::copysignf128 => "copysignl",
|
||||
sym::floorf32 => "floorf",
|
||||
sym::floorf64 => "floor",
|
||||
sym::ceilf32 => "ceilf",
|
||||
sym::ceilf64 => "ceil",
|
||||
sym::truncf32 => "truncf",
|
||||
sym::truncf64 => "trunc",
|
||||
sym::rintf32 => "rintf",
|
||||
sym::rintf64 => "rint",
|
||||
sym::nearbyintf32 => "nearbyintf",
|
||||
sym::nearbyintf64 => "nearbyint",
|
||||
// We match the LLVM backend and lower this to `rint`.
|
||||
sym::round_ties_even_f32 => "rintf",
|
||||
sym::round_ties_even_f64 => "rint",
|
||||
sym::roundf32 => "roundf",
|
||||
sym::roundf64 => "round",
|
||||
sym::roundevenf32 => "roundevenf",
|
||||
sym::roundevenf64 => "roundeven",
|
||||
sym::abort => "abort",
|
||||
_ => return None,
|
||||
};
|
||||
|
@ -181,14 +179,19 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
let ptr = args[0].immediate();
|
||||
let layout = self.layout_of(tp_ty);
|
||||
let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode {
|
||||
let gcc_ty = ty.gcc_type(self);
|
||||
self.volatile_load(gcc_ty, ptr)
|
||||
} else {
|
||||
self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
|
||||
self.volatile_load(layout.gcc_type(self), ptr)
|
||||
};
|
||||
// TODO(antoyo): set alignment.
|
||||
self.to_immediate(load, self.layout_of(tp_ty))
|
||||
if let BackendRepr::Scalar(scalar) = layout.backend_repr {
|
||||
self.to_immediate_scalar(load, scalar)
|
||||
} else {
|
||||
load
|
||||
}
|
||||
}
|
||||
sym::volatile_store => {
|
||||
let dst = args[0].deref(self.cx());
|
||||
|
@ -310,7 +313,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
|||
let layout = self.layout_of(tp_ty).layout;
|
||||
let _use_integer_compare = match layout.backend_repr() {
|
||||
Scalar(_) | ScalarPair(_, _) => true,
|
||||
Uninhabited | Vector { .. } => false,
|
||||
SimdVector { .. } => false,
|
||||
Memory { .. } => {
|
||||
// For rusty ABIs, small aggregates are actually passed
|
||||
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
|
||||
|
@ -1001,7 +1004,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
128 => "__rust_i128_addo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
let (int_result, overflow) =
|
||||
self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
self.llbb().add_assignment(self.location, res, int_result);
|
||||
overflow
|
||||
};
|
||||
|
@ -1071,7 +1075,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
128 => "__rust_i128_subo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
let (int_result, overflow) =
|
||||
self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
self.llbb().add_assignment(self.location, res, int_result);
|
||||
overflow
|
||||
};
|
||||
|
@ -1236,7 +1241,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(
|
|||
tcx.types.unit,
|
||||
false,
|
||||
rustc_hir::Safety::Unsafe,
|
||||
Abi::Rust,
|
||||
ExternAbi::Rust,
|
||||
)),
|
||||
);
|
||||
// `unsafe fn(*mut i8, *mut i8) -> ()`
|
||||
|
@ -1247,7 +1252,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(
|
|||
tcx.types.unit,
|
||||
false,
|
||||
rustc_hir::Safety::Unsafe,
|
||||
Abi::Rust,
|
||||
ExternAbi::Rust,
|
||||
)),
|
||||
);
|
||||
// `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
|
||||
|
@ -1256,7 +1261,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(
|
|||
tcx.types.i32,
|
||||
false,
|
||||
rustc_hir::Safety::Unsafe,
|
||||
Abi::Rust,
|
||||
ExternAbi::Rust,
|
||||
));
|
||||
let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen);
|
||||
cx.rust_try_fn.set(Some(rust_try));
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::iter::FromIterator;
|
|||
use gccjit::{BinaryOp, RValue, ToRValue, Type};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{ComparisonOp, UnaryOp};
|
||||
use rustc_abi::{Align, Size};
|
||||
use rustc_codegen_ssa::base::compare_simd_types;
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
#[cfg(feature = "master")]
|
||||
|
@ -17,7 +18,6 @@ use rustc_middle::mir::BinOp;
|
|||
use rustc_middle::ty::layout::HasTyCtxt;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_target::abi::{Align, Size};
|
||||
|
||||
use crate::builder::Builder;
|
||||
#[cfg(not(feature = "master"))]
|
||||
|
@ -62,11 +62,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let arg_tys = sig.inputs();
|
||||
|
||||
if name == sym::simd_select_bitmask {
|
||||
require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument {
|
||||
span,
|
||||
name,
|
||||
ty: arg_tys[1]
|
||||
});
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
|
||||
let expected_int_bits = (len.max(8) - 1).next_power_of_two();
|
||||
|
@ -140,14 +139,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
});
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
require!(
|
||||
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
|
||||
InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty }
|
||||
|
@ -269,23 +271,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let lo_nibble =
|
||||
bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &lo_nibble_elements);
|
||||
|
||||
let mask = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &vec![
|
||||
bx.context
|
||||
.new_rvalue_from_int(
|
||||
bx.u8_type, 0x0f
|
||||
);
|
||||
byte_vector_type_size
|
||||
as _
|
||||
]);
|
||||
let mask = bx.context.new_rvalue_from_vector(
|
||||
None,
|
||||
long_byte_vector_type,
|
||||
&vec![bx.context.new_rvalue_from_int(bx.u8_type, 0x0f); byte_vector_type_size as _],
|
||||
);
|
||||
|
||||
let four_vec = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &vec![
|
||||
bx.context
|
||||
.new_rvalue_from_int(
|
||||
bx.u8_type, 4
|
||||
);
|
||||
byte_vector_type_size
|
||||
as _
|
||||
]);
|
||||
let four_vec = bx.context.new_rvalue_from_vector(
|
||||
None,
|
||||
long_byte_vector_type,
|
||||
&vec![bx.context.new_rvalue_from_int(bx.u8_type, 4); byte_vector_type_size as _],
|
||||
);
|
||||
|
||||
// Step 2: Byte-swap the input.
|
||||
let swapped = simd_bswap(bx, args[0].immediate());
|
||||
|
@ -388,21 +384,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(out_len == n, InvalidMonomorphization::ReturnLength {
|
||||
span,
|
||||
name,
|
||||
in_len: n,
|
||||
ret_ty,
|
||||
out_len
|
||||
});
|
||||
require!(in_elem == out_ty, InvalidMonomorphization::ReturnElement {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_ty
|
||||
});
|
||||
require!(
|
||||
out_len == n,
|
||||
InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len }
|
||||
);
|
||||
require!(
|
||||
in_elem == out_ty,
|
||||
InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
|
||||
);
|
||||
|
||||
let vector = args[2].immediate();
|
||||
|
||||
|
@ -410,14 +399,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
if name == sym::simd_insert {
|
||||
require!(in_elem == arg_tys[2], InvalidMonomorphization::InsertedType {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
out_ty: arg_tys[2]
|
||||
});
|
||||
if name == sym::simd_insert || name == sym::simd_insert_dyn {
|
||||
require!(
|
||||
in_elem == arg_tys[2],
|
||||
InvalidMonomorphization::InsertedType {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
out_ty: arg_tys[2]
|
||||
}
|
||||
);
|
||||
|
||||
// TODO(antoyo): For simd_insert, check if the index is a constant of the correct size.
|
||||
let vector = args[0].immediate();
|
||||
let index = args[1].immediate();
|
||||
let value = args[2].immediate();
|
||||
|
@ -430,33 +424,29 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
if name == sym::simd_extract {
|
||||
require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty
|
||||
});
|
||||
if name == sym::simd_extract || name == sym::simd_extract_dyn {
|
||||
require!(
|
||||
ret_ty == in_elem,
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
// TODO(antoyo): For simd_extract, check if the index is a constant of the correct size.
|
||||
let vector = args[0].immediate();
|
||||
return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
|
||||
let index = args[1].immediate();
|
||||
return Ok(bx.context.new_vector_access(None, vector, index).to_rvalue());
|
||||
}
|
||||
|
||||
if name == sym::simd_select {
|
||||
let m_elem_ty = in_elem;
|
||||
let m_len = in_len;
|
||||
require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument {
|
||||
span,
|
||||
name,
|
||||
ty: arg_tys[1]
|
||||
});
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
require!(m_len == v_len, InvalidMonomorphization::MismatchedLengths {
|
||||
span,
|
||||
name,
|
||||
m_len,
|
||||
v_len
|
||||
});
|
||||
require!(
|
||||
m_len == v_len,
|
||||
InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
|
||||
);
|
||||
match *m_elem_ty.kind() {
|
||||
ty::Int(_) => {}
|
||||
_ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }),
|
||||
|
@ -468,25 +458,27 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
|
||||
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
});
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
|
||||
match *in_elem.kind() {
|
||||
ty::RawPtr(p_ty, _) => {
|
||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: in_elem
|
||||
});
|
||||
require!(
|
||||
metadata.is_unit(),
|
||||
InvalidMonomorphization::CastWidePointer { span, name, ty: in_elem }
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem })
|
||||
|
@ -497,11 +489,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: out_elem
|
||||
});
|
||||
require!(
|
||||
metadata.is_unit(),
|
||||
InvalidMonomorphization::CastWidePointer { span, name, ty: out_elem }
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem })
|
||||
|
@ -524,14 +515,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
|
||||
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
});
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
|
||||
match *in_elem.kind() {
|
||||
ty::RawPtr(_, _) => {}
|
||||
|
@ -560,14 +554,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
|
||||
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
});
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
|
||||
match *in_elem.kind() {
|
||||
ty::Uint(ty::UintTy::Usize) => {}
|
||||
|
@ -596,14 +593,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
if name == sym::simd_cast || name == sym::simd_as {
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
});
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::ReturnLengthInputType {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
ret_ty,
|
||||
out_len
|
||||
}
|
||||
);
|
||||
// casting cares about nominal type, not just structural type
|
||||
if in_elem == out_elem {
|
||||
return Ok(args[0].immediate());
|
||||
|
@ -629,14 +629,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
|
||||
match (in_style, out_style) {
|
||||
(Style::Unsupported, Style::Unsupported) => {
|
||||
require!(false, InvalidMonomorphization::UnsupportedCast {
|
||||
span,
|
||||
name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty,
|
||||
out_elem
|
||||
});
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::UnsupportedCast {
|
||||
span,
|
||||
name,
|
||||
in_ty,
|
||||
in_elem,
|
||||
ret_ty,
|
||||
out_elem
|
||||
}
|
||||
);
|
||||
}
|
||||
_ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)),
|
||||
}
|
||||
|
@ -773,8 +776,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
sym::simd_floor => "floor",
|
||||
sym::simd_fma => "fma",
|
||||
sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary
|
||||
sym::simd_fpowi => "__builtin_powi",
|
||||
sym::simd_fpow => "pow",
|
||||
sym::simd_fsin => "sin",
|
||||
sym::simd_fsqrt => "sqrt",
|
||||
sym::simd_round => "round",
|
||||
|
@ -789,24 +790,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let mut vector_elements = vec![];
|
||||
for i in 0..in_len {
|
||||
let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64);
|
||||
// we have to treat fpowi specially, since fpowi's second argument is always an i32
|
||||
let mut arguments = vec![];
|
||||
if name == sym::simd_fpowi {
|
||||
arguments = vec![
|
||||
bx.extract_element(args[0].immediate(), index).to_rvalue(),
|
||||
args[1].immediate(),
|
||||
];
|
||||
} else {
|
||||
for arg in args {
|
||||
let mut element = bx.extract_element(arg.immediate(), index).to_rvalue();
|
||||
// FIXME: it would probably be better to not have casts here and use the proper
|
||||
// instructions.
|
||||
if let Some(typ) = cast_type {
|
||||
element = bx.context.new_cast(None, element, typ);
|
||||
}
|
||||
arguments.push(element);
|
||||
for arg in args {
|
||||
let mut element = bx.extract_element(arg.immediate(), index).to_rvalue();
|
||||
// FIXME: it would probably be better to not have casts here and use the proper
|
||||
// instructions.
|
||||
if let Some(typ) = cast_type {
|
||||
element = bx.context.new_cast(None, element, typ);
|
||||
}
|
||||
};
|
||||
arguments.push(element);
|
||||
}
|
||||
let mut result = bx.context.new_call(None, function, &arguments);
|
||||
if cast_type.is_some() {
|
||||
result = bx.context.new_cast(None, result, elem_ty);
|
||||
|
@ -830,8 +823,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
| sym::simd_floor
|
||||
| sym::simd_fma
|
||||
| sym::simd_relaxed_fma
|
||||
| sym::simd_fpow
|
||||
| sym::simd_fpowi
|
||||
| sym::simd_fsin
|
||||
| sym::simd_fsqrt
|
||||
| sym::simd_round
|
||||
|
@ -914,45 +905,47 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
|
||||
// All types must be simd vector types
|
||||
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
|
||||
require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond {
|
||||
span,
|
||||
name,
|
||||
ty: arg_tys[1]
|
||||
});
|
||||
require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird {
|
||||
span,
|
||||
name,
|
||||
ty: arg_tys[2]
|
||||
});
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
require_simd!(
|
||||
arg_tys[2],
|
||||
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
|
||||
);
|
||||
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
|
||||
|
||||
// Of the same length:
|
||||
let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
require!(in_len == out_len, InvalidMonomorphization::SecondArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[1],
|
||||
out_len
|
||||
});
|
||||
require!(in_len == out_len2, InvalidMonomorphization::ThirdArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[2],
|
||||
out_len: out_len2
|
||||
});
|
||||
require!(
|
||||
in_len == out_len,
|
||||
InvalidMonomorphization::SecondArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[1],
|
||||
out_len
|
||||
}
|
||||
);
|
||||
require!(
|
||||
in_len == out_len2,
|
||||
InvalidMonomorphization::ThirdArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[2],
|
||||
out_len: out_len2
|
||||
}
|
||||
);
|
||||
|
||||
// The return type must match the first argument type
|
||||
require!(ret_ty == in_ty, InvalidMonomorphization::ExpectedReturnType {
|
||||
span,
|
||||
name,
|
||||
in_ty,
|
||||
ret_ty
|
||||
});
|
||||
require!(
|
||||
ret_ty == in_ty,
|
||||
InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty }
|
||||
);
|
||||
|
||||
// This counts how many pointers
|
||||
fn ptr_count(t: Ty<'_>) -> usize {
|
||||
|
@ -979,15 +972,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
(ptr_count(element_ty1), non_ptr(element_ty1))
|
||||
}
|
||||
_ => {
|
||||
require!(false, InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty1,
|
||||
second_arg: arg_tys[1],
|
||||
in_elem,
|
||||
in_ty,
|
||||
mutability: ExpectedPointerMutability::Not,
|
||||
});
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty1,
|
||||
second_arg: arg_tys[1],
|
||||
in_elem,
|
||||
in_ty,
|
||||
mutability: ExpectedPointerMutability::Not,
|
||||
}
|
||||
);
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
@ -1000,12 +996,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
match *element_ty2.kind() {
|
||||
ty::Int(_) => (),
|
||||
_ => {
|
||||
require!(false, InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
});
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1029,36 +1028,40 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
|
||||
// All types must be simd vector types
|
||||
require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
|
||||
require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond {
|
||||
span,
|
||||
name,
|
||||
ty: arg_tys[1]
|
||||
});
|
||||
require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird {
|
||||
span,
|
||||
name,
|
||||
ty: arg_tys[2]
|
||||
});
|
||||
require_simd!(
|
||||
arg_tys[1],
|
||||
InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }
|
||||
);
|
||||
require_simd!(
|
||||
arg_tys[2],
|
||||
InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }
|
||||
);
|
||||
|
||||
// Of the same length:
|
||||
let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||
let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||
require!(in_len == element_len1, InvalidMonomorphization::SecondArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[1],
|
||||
out_len: element_len1
|
||||
});
|
||||
require!(in_len == element_len2, InvalidMonomorphization::ThirdArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[2],
|
||||
out_len: element_len2
|
||||
});
|
||||
require!(
|
||||
in_len == element_len1,
|
||||
InvalidMonomorphization::SecondArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[1],
|
||||
out_len: element_len1
|
||||
}
|
||||
);
|
||||
require!(
|
||||
in_len == element_len2,
|
||||
InvalidMonomorphization::ThirdArgumentLength {
|
||||
span,
|
||||
name,
|
||||
in_len,
|
||||
in_ty,
|
||||
arg_ty: arg_tys[2],
|
||||
out_len: element_len2
|
||||
}
|
||||
);
|
||||
|
||||
// This counts how many pointers
|
||||
fn ptr_count(t: Ty<'_>) -> usize {
|
||||
|
@ -1086,15 +1089,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
(ptr_count(element_ty1), non_ptr(element_ty1))
|
||||
}
|
||||
_ => {
|
||||
require!(false, InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty1,
|
||||
second_arg: arg_tys[1],
|
||||
in_elem,
|
||||
in_ty,
|
||||
mutability: ExpectedPointerMutability::Mut,
|
||||
});
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::ExpectedElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty1,
|
||||
second_arg: arg_tys[1],
|
||||
in_elem,
|
||||
in_ty,
|
||||
mutability: ExpectedPointerMutability::Mut,
|
||||
}
|
||||
);
|
||||
unreachable!();
|
||||
}
|
||||
};
|
||||
|
@ -1106,12 +1112,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
match *element_ty2.kind() {
|
||||
ty::Int(_) => (),
|
||||
_ => {
|
||||
require!(false, InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
});
|
||||
require!(
|
||||
false,
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1278,13 +1287,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
($name:ident : $vec_op:expr, $float_reduce:ident, $ordered:expr, $op:ident,
|
||||
$identity:expr) => {
|
||||
if name == sym::$name {
|
||||
require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty
|
||||
});
|
||||
require!(
|
||||
ret_ty == in_elem,
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
return match *in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {
|
||||
let r = bx.vector_reduce_op(args[0].immediate(), $vec_op);
|
||||
|
@ -1350,13 +1356,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
macro_rules! minmax_red {
|
||||
($name:ident: $int_red:ident, $float_red:ident) => {
|
||||
if name == sym::$name {
|
||||
require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty
|
||||
});
|
||||
require!(
|
||||
ret_ty == in_elem,
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
return match *in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())),
|
||||
ty::Float(_) => Ok(bx.$float_red(args[0].immediate())),
|
||||
|
@ -1380,13 +1383,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
($name:ident : $op:expr, $boolean:expr) => {
|
||||
if name == sym::$name {
|
||||
let input = if !$boolean {
|
||||
require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType {
|
||||
span,
|
||||
name,
|
||||
in_elem,
|
||||
in_ty,
|
||||
ret_ty
|
||||
});
|
||||
require!(
|
||||
ret_ty == in_elem,
|
||||
InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
|
||||
);
|
||||
args[0].immediate()
|
||||
} else {
|
||||
match *in_elem.kind() {
|
||||
|
|
75
src/lib.rs
75
src/lib.rs
|
@ -16,7 +16,7 @@
|
|||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(rustc_private, decl_macro, never_type, trusted_len, hash_raw_entry, let_chains)]
|
||||
#![feature(rustc_private, decl_macro, never_type, trusted_len, let_chains)]
|
||||
#![allow(broken_intra_doc_links)]
|
||||
#![recursion_limit = "256"]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
@ -52,6 +52,7 @@ extern crate rustc_metadata;
|
|||
extern crate rustc_middle;
|
||||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
extern crate rustc_symbol_mangling;
|
||||
extern crate rustc_target;
|
||||
|
||||
// This prevents duplicating functions and statics that are already part of the host rustc process.
|
||||
|
@ -259,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend {
|
|||
.join(sess)
|
||||
}
|
||||
|
||||
fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
||||
target_features_cfg(sess, allow_unstable, &self.target_info)
|
||||
fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
|
||||
target_features_cfg(sess, &self.target_info)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,7 +394,7 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
unsafe fn optimize(
|
||||
_cgcx: &CodegenContext<Self>,
|
||||
_dcx: DiagCtxtHandle<'_>,
|
||||
module: &ModuleCodegen<Self::Module>,
|
||||
module: &mut ModuleCodegen<Self::Module>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<(), FatalError> {
|
||||
module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
|
||||
|
@ -444,7 +445,6 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
}
|
||||
fn autodiff(
|
||||
_cgcx: &CodegenContext<Self>,
|
||||
_tcx: TyCtxt<'_>,
|
||||
_module: &ModuleCodegen<Self::Module>,
|
||||
_diff_fncs: Vec<AutoDiffItem>,
|
||||
_config: &ModuleConfig,
|
||||
|
@ -477,7 +477,7 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
|
|||
Some(level) => match level {
|
||||
OptLevel::No => OptimizationLevel::None,
|
||||
OptLevel::Less => OptimizationLevel::Limited,
|
||||
OptLevel::Default => OptimizationLevel::Standard,
|
||||
OptLevel::More => OptimizationLevel::Standard,
|
||||
OptLevel::Aggressive => OptimizationLevel::Aggressive,
|
||||
OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
|
||||
},
|
||||
|
@ -487,34 +487,41 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
|
|||
/// Returns the features that should be set in `cfg(target_feature)`.
|
||||
fn target_features_cfg(
|
||||
sess: &Session,
|
||||
allow_unstable: bool,
|
||||
target_info: &LockedTargetInfo,
|
||||
) -> Vec<Symbol> {
|
||||
) -> (Vec<Symbol>, Vec<Symbol>) {
|
||||
// TODO(antoyo): use global_gcc_features.
|
||||
sess.target
|
||||
.rust_target_features()
|
||||
.iter()
|
||||
.filter(|&&(_, gate, _)| gate.in_cfg())
|
||||
.filter_map(|&(feature, gate, _)| {
|
||||
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
|
||||
Some(feature)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter(|feature| {
|
||||
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
|
||||
if *feature == "neon" {
|
||||
return false;
|
||||
}
|
||||
target_info.cpu_supports(feature)
|
||||
/*
|
||||
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
|
||||
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
|
||||
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
|
||||
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
|
||||
*/
|
||||
})
|
||||
.map(Symbol::intern)
|
||||
.collect()
|
||||
let f = |allow_unstable| {
|
||||
sess.target
|
||||
.rust_target_features()
|
||||
.iter()
|
||||
.filter_map(|&(feature, gate, _)| {
|
||||
if allow_unstable
|
||||
|| (gate.in_cfg()
|
||||
&& (sess.is_nightly_build() || gate.requires_nightly().is_none()))
|
||||
{
|
||||
Some(feature)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter(|feature| {
|
||||
// TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
|
||||
if *feature == "neon" {
|
||||
return false;
|
||||
}
|
||||
target_info.cpu_supports(feature)
|
||||
/*
|
||||
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
|
||||
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
|
||||
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
|
||||
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
|
||||
*/
|
||||
})
|
||||
.map(Symbol::intern)
|
||||
.collect()
|
||||
};
|
||||
|
||||
let target_features = f(false);
|
||||
let unstable_target_features = f(true);
|
||||
(target_features, unstable_target_features)
|
||||
}
|
||||
|
|
|
@ -61,10 +61,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
// compiler-rt, then we want to implicitly compile everything with hidden
|
||||
// visibility as we're going to link this object all over the place but
|
||||
// don't want the symbols to get exported.
|
||||
if linkage != Linkage::Internal
|
||||
&& linkage != Linkage::Private
|
||||
&& self.tcx.is_compiler_builtins(LOCAL_CRATE)
|
||||
{
|
||||
if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) {
|
||||
#[cfg(feature = "master")]
|
||||
decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
|
||||
} else {
|
||||
|
|
|
@ -4,13 +4,13 @@ use std::convert::TryInto;
|
|||
#[cfg(feature = "master")]
|
||||
use gccjit::CType;
|
||||
use gccjit::{RValue, Struct, Type};
|
||||
use rustc_abi::{AddressSpace, Align, Integer, Size};
|
||||
use rustc_codegen_ssa::common::TypeKind;
|
||||
use rustc_codegen_ssa::traits::{
|
||||
BaseTypeCodegenMethods, DerivedTypeCodegenMethods, TypeMembershipCodegenMethods,
|
||||
};
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_target::abi::{AddressSpace, Align, Integer, Size};
|
||||
|
||||
use crate::common::TypeReflection;
|
||||
use crate::context::CodegenCx;
|
||||
|
@ -123,7 +123,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'gcc, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> {
|
||||
fn type_i8(&self) -> Type<'gcc> {
|
||||
self.i8_type
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ use std::fmt::Write;
|
|||
use gccjit::{Struct, Type};
|
||||
use rustc_abi as abi;
|
||||
use rustc_abi::Primitive::*;
|
||||
use rustc_abi::{BackendRepr, FieldsShape, Integer, PointeeInfo, Size, Variants};
|
||||
use rustc_abi::{
|
||||
BackendRepr, FieldsShape, Integer, PointeeInfo, Reg, Size, TyAbiInterface, Variants,
|
||||
};
|
||||
use rustc_codegen_ssa::traits::{
|
||||
BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods,
|
||||
};
|
||||
|
@ -11,8 +13,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
|
||||
use rustc_target::abi::TyAbiInterface;
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||
use rustc_target::callconv::{CastTarget, FnAbi};
|
||||
|
||||
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
||||
use crate::context::CodegenCx;
|
||||
|
@ -62,7 +63,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
|
|||
) -> Type<'gcc> {
|
||||
match layout.backend_repr {
|
||||
BackendRepr::Scalar(_) => bug!("handled elsewhere"),
|
||||
BackendRepr::Vector { ref element, count } => {
|
||||
BackendRepr::SimdVector { ref element, count } => {
|
||||
let element = layout.scalar_gcc_type_at(cx, element, Size::ZERO);
|
||||
let element =
|
||||
// NOTE: gcc doesn't allow pointer types in vectors.
|
||||
|
@ -83,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(
|
|||
false,
|
||||
);
|
||||
}
|
||||
BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {}
|
||||
BackendRepr::Memory { .. } => {}
|
||||
}
|
||||
|
||||
let name = match *layout.ty.kind() {
|
||||
|
@ -177,19 +178,16 @@ pub trait LayoutGccExt<'tcx> {
|
|||
impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
||||
fn is_gcc_immediate(&self) -> bool {
|
||||
match self.backend_repr {
|
||||
BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true,
|
||||
BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {
|
||||
false
|
||||
}
|
||||
BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true,
|
||||
BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_gcc_scalar_pair(&self) -> bool {
|
||||
match self.backend_repr {
|
||||
BackendRepr::ScalarPair(..) => true,
|
||||
BackendRepr::Uninhabited
|
||||
| BackendRepr::Scalar(_)
|
||||
| BackendRepr::Vector { .. }
|
||||
BackendRepr::Scalar(_)
|
||||
| BackendRepr::SimdVector { .. }
|
||||
| BackendRepr::Memory { .. } => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ tests/ui/unwind-no-uwtable.rs
|
|||
tests/ui/parser/unclosed-delimiter-in-dep.rs
|
||||
tests/ui/consts/missing_span_in_backtrace.rs
|
||||
tests/ui/drop/dynamic-drop.rs
|
||||
tests/ui/issues/issue-40883.rs
|
||||
tests/ui/issues/issue-43853.rs
|
||||
tests/ui/issues/issue-47364.rs
|
||||
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
|
||||
|
@ -100,14 +99,12 @@ tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs
|
|||
tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs
|
||||
|
@ -115,8 +112,9 @@ tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs
|
|||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs
|
||||
tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs
|
||||
tests/ui/simd/simd-bitmask-notpow2.rs
|
||||
tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs
|
||||
tests/ui/uninhabited/uninhabited-transparent-return-abi.rs
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
// Run-time:
|
||||
// status: signal
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -14,7 +15,7 @@ fn test_fail() -> ! {
|
|||
unsafe { intrinsics::abort() };
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
test_fail();
|
||||
}
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
// Run-time:
|
||||
// status: signal
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -15,8 +16,8 @@ fn fail() -> i32 {
|
|||
0
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
fail();
|
||||
0
|
||||
}
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
// 5
|
||||
// 10
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -20,8 +21,8 @@ fn make_array() -> [u8; 3] {
|
|||
[42, 10, 5]
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
let array = [42, 7, 5];
|
||||
let array2 = make_array();
|
||||
unsafe {
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
// 7 8
|
||||
// 10
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -21,8 +22,8 @@ fn inc(num: isize) -> isize {
|
|||
num + 1
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
|
||||
argc = inc(argc);
|
||||
unsafe {
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);
|
||||
|
|
|
@ -8,15 +8,16 @@
|
|||
// Int argument: 2
|
||||
// Both args: 11
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 {
|
||||
let string = "Arg: %d\n\0";
|
||||
let mut closure = || unsafe {
|
||||
libc::printf(string as *const str as *const i8, argc);
|
||||
|
|
|
@ -5,15 +5,16 @@
|
|||
// stdout: true
|
||||
// 1
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
||||
#[start]
|
||||
fn main(argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
unsafe {
|
||||
if argc == 1 {
|
||||
libc::printf(b"true\n\0" as *const u8 as *const i8);
|
||||
|
|
|
@ -3,14 +3,15 @@
|
|||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
||||
#[start]
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
// Run-time:
|
||||
// status: 2
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
unsafe {
|
||||
libc::exit(2);
|
||||
}
|
||||
|
|
|
@ -3,14 +3,15 @@
|
|||
// Run-time:
|
||||
// status: 1
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
1
|
||||
}
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
// status: 0
|
||||
// stdout: 1
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -19,8 +20,8 @@ fn call_func(func: fn(i16) -> i8, param: i16) -> i8 {
|
|||
func(param)
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
unsafe {
|
||||
let result = call_func(i16_as_i8, argc as i16) as isize;
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, result);
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
// 6
|
||||
// 11
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -25,8 +26,8 @@ fn update_num(num: &mut isize) {
|
|||
*num = *num + 5;
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
|
||||
let mut test = test(argc);
|
||||
unsafe {
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
|
||||
|
|
|
@ -5,15 +5,16 @@
|
|||
// 39
|
||||
// 10
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
unsafe {
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 + argc);
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 - argc);
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
// status: 0
|
||||
// stdout: 1
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -17,8 +18,8 @@ fn make_array() -> [u8; 3] {
|
|||
[42, 10, 5]
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
unsafe {
|
||||
let ptr = ONE as *mut usize;
|
||||
let value = ptr as usize;
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
// 10
|
||||
// 42
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -20,8 +21,8 @@ fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u3
|
|||
)
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
|
||||
unsafe {
|
||||
libc::printf(b"%d\n\0" as *const u8 as *const i8, c);
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
// status: 0
|
||||
// stdout: 5
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -17,8 +18,8 @@ fn index_slice(s: &[u32]) -> u32 {
|
|||
unsafe { s[TWO] }
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
let array = [42, 7, 5];
|
||||
unsafe {
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, index_slice(&array));
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
// 12
|
||||
// 1
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -32,8 +33,8 @@ static mut TEST2: Test = Test { field: 14 };
|
|||
|
||||
static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST } };
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 {
|
||||
unsafe {
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT);
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field);
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
// stdout: 1
|
||||
// 2
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
@ -24,10 +25,14 @@ fn one() -> isize {
|
|||
1
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
let test = Test { field: one() };
|
||||
let two = Two { two: 2 };
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
let test = Test {
|
||||
field: one(),
|
||||
};
|
||||
let two = Two {
|
||||
two: 2,
|
||||
};
|
||||
unsafe {
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, two.two);
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
// status: 0
|
||||
// stdout: 3
|
||||
|
||||
#![feature(no_core, start)]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate mini_core;
|
||||
use mini_core::*;
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
#[no_mangle]
|
||||
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
|
||||
let test: (isize, isize, isize) = (3, 1, 4);
|
||||
unsafe {
|
||||
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue