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