Merge commit 'db1a31c243' into subtree-update_cg_gcc_2025-04-18

This commit is contained in:
Guillaume Gomez 2025-04-18 21:19:50 +02:00
commit e4ea67b3d7
52 changed files with 959 additions and 1241 deletions

View file

@ -1,8 +1,10 @@
name: CI
on:
- push
- pull_request
push:
branches:
- master
pull_request:
permissions:
contents: read
@ -121,3 +123,22 @@ jobs:
run: |
cd build_system
cargo test
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
success:
needs: [build, duplicates, build_system]
# We need to ensure this job does *not* get skipped if its dependencies fail,
# because a skipped job is considered a success by GitHub. So we have to
# overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
# when the workflow is canceled manually.
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
# Manually check the status of all dependencies. `if: failure()` does not work.
- name: Conclusion
run: |
# Print the dependent jobs to see them in the CI log
jq -C <<< '${{ toJson(needs) }}'
# Check if all jobs that we depend on (in the needs array) were successful.
jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'

View file

@ -2,7 +2,10 @@
name: Failures
on:
- pull_request
push:
branches:
- master
pull_request:
permissions:
contents: read
@ -108,3 +111,22 @@ jobs:
echo "Error: 'the compiler unexpectedly panicked' found in output logs. CI Error!!"
exit 1
fi
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
success_failures:
needs: [build]
# We need to ensure this job does *not* get skipped if its dependencies fail,
# because a skipped job is considered a success by GitHub. So we have to
# overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
# when the workflow is canceled manually.
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
# Manually check the status of all dependencies. `if: failure()` does not work.
- name: Conclusion
run: |
# Print the dependent jobs to see them in the CI log
jq -C <<< '${{ toJson(needs) }}'
# Check if all jobs that we depend on (in the needs array) were successful.
jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'

View file

@ -1,8 +1,10 @@
name: CI libgccjit 12
on:
- push
- pull_request
push:
branches:
- master
pull_request:
permissions:
contents: read
@ -85,3 +87,22 @@ jobs:
#- name: Run tests
#run: |
#./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
success_gcc12:
needs: [build]
# We need to ensure this job does *not* get skipped if its dependencies fail,
# because a skipped job is considered a success by GitHub. So we have to
# overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
# when the workflow is canceled manually.
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
# Manually check the status of all dependencies. `if: failure()` does not work.
- name: Conclusion
run: |
# Print the dependent jobs to see them in the CI log
jq -C <<< '${{ toJson(needs) }}'
# Check if all jobs that we depend on (in the needs array) were successful.
jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'

View file

@ -3,8 +3,10 @@
name: m68k CI
on:
- push
- pull_request
push:
branches:
- master
pull_request:
permissions:
contents: read
@ -105,3 +107,22 @@ jobs:
- name: Run tests
run: |
./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }}
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
success_m68k:
needs: [build]
# We need to ensure this job does *not* get skipped if its dependencies fail,
# because a skipped job is considered a success by GitHub. So we have to
# overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
# when the workflow is canceled manually.
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
# Manually check the status of all dependencies. `if: failure()` does not work.
- name: Conclusion
run: |
# Print the dependent jobs to see them in the CI log
jq -C <<< '${{ toJson(needs) }}'
# Check if all jobs that we depend on (in the needs array) were successful.
jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'

View file

@ -1,8 +1,10 @@
name: CI with sysroot compiled in release mode
on:
- push
- pull_request
push:
branches:
- master
pull_request:
permissions:
contents: read
@ -82,3 +84,22 @@ jobs:
echo "Test is done with LTO enabled, hence inlining should occur across crates"
exit 1
fi
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
success_release:
needs: [build]
# We need to ensure this job does *not* get skipped if its dependencies fail,
# because a skipped job is considered a success by GitHub. So we have to
# overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
# when the workflow is canceled manually.
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
# Manually check the status of all dependencies. `if: failure()` does not work.
- name: Conclusion
run: |
# Print the dependent jobs to see them in the CI log
jq -C <<< '${{ toJson(needs) }}'
# Check if all jobs that we depend on (in the needs array) were successful.
jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'

View file

@ -1,8 +1,10 @@
name: stdarch tests with sysroot compiled in release mode
on:
- push
- pull_request
push:
branches:
- master
pull_request:
permissions:
contents: read
@ -102,3 +104,22 @@ jobs:
# TODO: remove --skip test_mm512_stream_ps when stdarch is updated in rustc.
# TODO: remove --skip test_tile_ when it's implemented.
STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features --cfg stdarch_intel_sde" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_mm512_stream_ps --skip test_tile_
# Summary job for the merge queue.
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
success_stdarch:
needs: [build]
# We need to ensure this job does *not* get skipped if its dependencies fail,
# because a skipped job is considered a success by GitHub. So we have to
# overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run
# when the workflow is canceled manually.
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
# Manually check the status of all dependencies. `if: failure()` does not work.
- name: Conclusion
run: |
# Print the dependent jobs to see them in the CI log
jq -C <<< '${{ toJson(needs) }}'
# Check if all jobs that we depend on (in the needs array) were successful.
jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'

View file

@ -56,18 +56,18 @@ dependencies = [
[[package]]
name = "gccjit"
version = "2.4.0"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72fd91f4adbf02b53cfc73c97bc33c5f253009043f30c56a5ec08dd5c8094dc8"
checksum = "2895ddec764de7ac76fe6c056050c4801a80109c066f177a00a9cc8dee02b29b"
dependencies = [
"gccjit_sys",
]
[[package]]
name = "gccjit_sys"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fb7b8f48a75e2cfe78c3d9a980b32771c34ffd12d196021ab3f98c49fbd2f0d"
checksum = "ac133db68db8a6a8b2c51ef4b18d8ea16682d5814c4641272fe37bbbc223d5f3"
dependencies = [
"libc",
]

View file

@ -22,7 +22,7 @@ master = ["gccjit/master"]
default = ["master"]
[dependencies]
gccjit = "2.4"
gccjit = "2.5"
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
# Local copy.

View file

@ -23,7 +23,7 @@ A secondary goal is to check if using the gcc backend will provide any run-time
## Building
**This requires a patched libgccjit in order to work.
You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.**
You need to use my [fork of gcc](https://github.com/rust-lang/gcc) which already includes these patches.**
```bash
$ cp config.example.toml config.toml
@ -40,7 +40,7 @@ to do a few more things.
To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue):
```bash
$ git clone https://github.com/antoyo/gcc
$ git clone https://github.com/rust-lang/gcc
$ sudo apt install flex libmpfr-dev libgmp-dev libmpc3 libmpc-dev
$ mkdir gcc-build gcc-install
$ cd gcc-build

View file

@ -61,7 +61,7 @@ pub fn run() -> Result<(), String> {
return Ok(());
};
let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?;
let result = git_clone("https://github.com/rust-lang/gcc", Some(&args.out_path), false)?;
if result.ran_clone {
let gcc_commit = args.config_info.get_gcc_commit()?;
println!("Checking out GCC commit `{}`...", gcc_commit);

View file

@ -529,20 +529,21 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> {
env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string());
let extra =
if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" };
let rustc_args = &format!(
r#"-Zpanic-abort-tests \
-Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \
--sysroot "{sysroot_dir}" -Cpanic=abort{extra}"#,
let codegen_backend_path = format!(
"{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}",
pwd = std::env::current_dir()
.map_err(|error| format!("`current_dir` failed: {:?}", error))?
.display(),
channel = args.config_info.channel.as_str(),
dylib_ext = args.config_info.dylib_ext,
sysroot_dir = args.config_info.sysroot_path,
extra = extra,
);
let extra =
if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" };
let rustc_args = format!(
"-Zpanic-abort-tests -Zcodegen-backend={codegen_backend_path} --sysroot {} -Cpanic=abort{extra}",
args.config_info.sysroot_path
);
run_command_with_env(
@ -677,7 +678,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
// FIXME: create a function "display_if_not_quiet" or something along the line.
println!("[TEST] libcore");
let path = get_sysroot_dir().join("sysroot_src/library/core/tests");
let path = get_sysroot_dir().join("sysroot_src/library/coretests");
let _ = remove_dir_all(path.join("target"));
run_cargo_command(&[&"test"], Some(&path), env, args)?;
Ok(())

View file

@ -14,4 +14,4 @@ Finally, you need to update this repository by calling the relevant API you adde
To test it, build `gcc`, run `cargo update -p gccjit` and then you can test the generated output for a given Rust crate.
[gccjit.rs]: https://github.com/antoyo/gccjit.rs
[gccjit.rs]: https://github.com/rust-lang/gccjit.rs

View file

@ -51,6 +51,10 @@ impl<T: ?Sized> LegacyReceiver for &T {}
impl<T: ?Sized> LegacyReceiver for &mut T {}
impl<T: ?Sized, A: Allocator> LegacyReceiver for Box<T, A> {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "copy"]
pub trait Copy {}
@ -134,6 +138,14 @@ impl Mul for u8 {
}
}
impl Mul for i32 {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self * rhs
}
}
impl Mul for usize {
type Output = Self;
@ -142,6 +154,14 @@ impl Mul for usize {
}
}
impl Mul for isize {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self * rhs
}
}
#[lang = "add"]
pub trait Add<RHS = Self> {
type Output;
@ -165,6 +185,14 @@ impl Add for i8 {
}
}
impl Add for i32 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for usize {
type Output = Self;
@ -196,6 +224,14 @@ impl Sub for usize {
}
}
impl Sub for isize {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self - rhs
}
}
impl Sub for u8 {
type Output = Self;
@ -220,6 +256,14 @@ impl Sub for i16 {
}
}
impl Sub for i32 {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self - rhs
}
}
#[lang = "rem"]
pub trait Rem<RHS = Self> {
type Output;
@ -628,6 +672,10 @@ pub mod libc {
pub fn memcpy(dst: *mut u8, src: *const u8, size: usize);
pub fn memmove(dst: *mut u8, src: *const u8, size: usize);
pub fn strncpy(dst: *mut u8, src: *const u8, size: usize);
pub fn fflush(stream: *mut i32) -> i32;
pub fn exit(status: i32);
pub static stdout: *mut i32;
}
}

View file

@ -1 +1 @@
e607be166673a8de9fc07f6f02c60426e556c5f2
0ea98a1365b81f7488073512c850e8ee951a4afd

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -9,7 +9,8 @@ use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf;
#[cfg(feature = "master")]
use rustc_session::config;
use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
#[cfg(feature = "master")]
use rustc_target::callconv::{ArgAttributes, CastTarget, Conv, FnAbi, PassMode};
use crate::builder::Builder;
use crate::context::CodegenCx;
@ -105,6 +106,8 @@ pub trait FnAbiGccExt<'gcc, 'tcx> {
// TODO(antoyo): return a function pointer type instead?
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>;
fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
#[cfg(feature = "master")]
fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option<FnAttribute<'gcc>>;
}
impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
@ -227,4 +230,47 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
);
pointer_type
}
#[cfg(feature = "master")]
fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option<FnAttribute<'gcc>> {
conv_to_fn_attribute(self.conv, &cx.tcx.sess.target.arch)
}
}
#[cfg(feature = "master")]
pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute<'gcc>> {
// TODO: handle the calling conventions returning None.
let attribute = match conv {
Conv::C
| Conv::Rust
| Conv::CCmseNonSecureCall
| Conv::CCmseNonSecureEntry
| Conv::RiscvInterrupt { .. } => return None,
Conv::Cold => return None,
Conv::PreserveMost => return None,
Conv::PreserveAll => return None,
Conv::GpuKernel => {
// TODO(antoyo): remove clippy allow attribute when this is implemented.
#[allow(clippy::if_same_then_else)]
if arch == "amdgpu" {
return None;
} else if arch == "nvptx64" {
return None;
} else {
panic!("Architecture {} does not support GpuKernel calling convention", arch);
}
}
Conv::AvrInterrupt => return None,
Conv::AvrNonBlockingInterrupt => return None,
Conv::ArmAapcs => return None,
Conv::Msp430Intr => return None,
Conv::X86Fastcall => return None,
Conv::X86Intr => return None,
Conv::X86Stdcall => return None,
Conv::X86ThisCall => return None,
Conv::X86VectorCall => return None,
Conv::X86_64SysV => FnAttribute::SysvAbi,
Conv::X86_64Win64 => FnAttribute::MsAbi,
};
Some(attribute)
}

View file

@ -36,7 +36,8 @@ use crate::type_of::LayoutGccExt;
//
// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes.
// Contrary, Rust expresses clobbers through "out" operands that aren't tied to
// a variable (`_`), and such "clobbers" do have index.
// a variable (`_`), and such "clobbers" do have index. Input operands cannot also
// be clobbered.
//
// 4. Furthermore, GCC Extended Asm does not support explicit register constraints
// (like `out("eax")`) directly, offering so-called "local register variables"
@ -161,6 +162,16 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
// Also, we don't emit any asm operands immediately; we save them to
// the one of the buffers to be emitted later.
let mut input_registers = vec![];
for op in rust_operands {
if let InlineAsmOperandRef::In { reg, .. } = *op {
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
input_registers.push(reg_name);
}
}
}
// 1. Normal variables (and saving operands to buffers).
for (rust_idx, op) in rust_operands.iter().enumerate() {
match *op {
@ -183,25 +194,39 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
continue;
}
(Register(reg_name), None) => {
// `clobber_abi` can add lots of clobbers that are not supported by the target,
// such as AVX-512 registers, so we just ignore unsupported registers
let is_target_supported =
reg.reg_class().supported_types(asm_arch, true).iter().any(
|&(_, feature)| {
if let Some(feature) = feature {
self.tcx
.asm_target_features(instance.def_id())
.contains(&feature)
} else {
true // Register class is unconditionally supported
}
},
);
if input_registers.contains(&reg_name) {
// the `clobber_abi` operand is converted into a series of
// `lateout("reg") _` operands. Of course, a user could also
// explicitly define such an output operand.
//
// GCC does not allow input registers to be clobbered, so if this out register
// is also used as an in register, do not add it to the clobbers list.
// it will be treated as a lateout register with `out_place: None`
if !late {
bug!("input registers can only be used as lateout regisers");
}
("r", dummy_output_type(self.cx, reg.reg_class()))
} else {
// `clobber_abi` can add lots of clobbers that are not supported by the target,
// such as AVX-512 registers, so we just ignore unsupported registers
let is_target_supported =
reg.reg_class().supported_types(asm_arch, true).iter().any(
|&(_, feature)| {
if let Some(feature) = feature {
self.tcx
.asm_target_features(instance.def_id())
.contains(&feature)
} else {
true // Register class is unconditionally supported
}
},
);
if is_target_supported && !clobbers.contains(&reg_name) {
clobbers.push(reg_name);
if is_target_supported && !clobbers.contains(&reg_name) {
clobbers.push(reg_name);
}
continue;
}
continue;
}
};
@ -230,13 +255,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
}
InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => {
let constraint =
if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) {
constraint
} else {
// left for the next pass
continue;
};
let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) else {
// left for the next pass
continue;
};
// Rustc frontend guarantees that input and output types are "compatible",
// so we can just use input var's type for the output variable.
@ -589,114 +611,127 @@ fn estimate_template_length(
}
/// Converts a register class to a GCC constraint code.
fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
let constraint = match reg {
// For vector registers LLVM wants the register name to match the type size.
fn reg_to_gcc(reg_or_reg_class: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
match reg_or_reg_class {
InlineAsmRegOrRegClass::Reg(reg) => {
match reg {
InlineAsmReg::X86(_) => {
// TODO(antoyo): add support for vector register.
//
// // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
return ConstraintOrRegister::Register(match reg.name() {
// Some of registers' names does not map 1-1 from rust to gcc
"st(0)" => "st",
ConstraintOrRegister::Register(explicit_reg_to_gcc(reg))
}
InlineAsmRegOrRegClass::RegClass(reg_class) => {
ConstraintOrRegister::Constraint(reg_class_to_gcc(reg_class))
}
}
}
name => name,
});
fn explicit_reg_to_gcc(reg: InlineAsmReg) -> &'static str {
// For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
match reg {
InlineAsmReg::X86(reg) => {
// TODO(antoyo): add support for vector register.
match reg.reg_class() {
X86InlineAsmRegClass::reg_byte => {
// GCC does not support the `b` suffix, so we just strip it
// see https://github.com/rust-lang/rustc_codegen_gcc/issues/485
reg.name().trim_end_matches('b')
}
_ => match reg.name() {
// Some of registers' names does not map 1-1 from rust to gcc
"st(0)" => "st",
_ => unimplemented!(),
name => name,
},
}
}
// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
InlineAsmRegOrRegClass::RegClass(reg) => match reg {
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
// https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for
// "define_constraint".
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
InlineAsmRegClass::X86(
X86InlineAsmRegClass::kreg0
| X86InlineAsmRegClass::x87_reg
| X86InlineAsmRegClass::mmx_reg
| X86InlineAsmRegClass::tmm_reg,
) => unreachable!("clobber-only"),
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("GCC backend does not support SPIR-V")
}
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
InlineAsmRegClass::Err => unreachable!(),
},
};
_ => unimplemented!(),
}
}
ConstraintOrRegister::Constraint(constraint)
/// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
match reg_class {
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
// https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for
// "define_constraint".
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
InlineAsmRegClass::X86(
X86InlineAsmRegClass::kreg0
| X86InlineAsmRegClass::x87_reg
| X86InlineAsmRegClass::mmx_reg
| X86InlineAsmRegClass::tmm_reg,
) => unreachable!("clobber-only"),
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("GCC backend does not support SPIR-V")
}
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
InlineAsmRegClass::Err => unreachable!(),
}
}
/// Type to use for outputs that are discarded. It doesn't really matter what

View file

@ -368,16 +368,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let previous_arg_count = args.len();
let orig_args = args;
let args = {
let function_address_names = self.function_address_names.borrow();
let original_function_name = function_address_names.get(&func_ptr);
func_ptr = llvm::adjust_function(self.context, &func_name, func_ptr, args);
llvm::adjust_intrinsic_arguments(
self,
gcc_func,
args.into(),
&func_name,
original_function_name,
)
llvm::adjust_intrinsic_arguments(self, gcc_func, args.into(), &func_name)
};
let args_adjusted = args.len() != previous_arg_count;
let args = self.check_ptr_call("call", func_ptr, &args);
@ -1271,7 +1263,50 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs)
// LLVM has a concept of "unordered compares", where eg ULT returns true if either the two
// arguments are unordered (i.e. either is NaN), or the lhs is less than the rhs. GCC does
// not natively have this concept, so in some cases we must manually handle NaNs
let must_handle_nan = match op {
RealPredicate::RealPredicateFalse => unreachable!(),
RealPredicate::RealOEQ => false,
RealPredicate::RealOGT => false,
RealPredicate::RealOGE => false,
RealPredicate::RealOLT => false,
RealPredicate::RealOLE => false,
RealPredicate::RealONE => false,
RealPredicate::RealORD => unreachable!(),
RealPredicate::RealUNO => unreachable!(),
RealPredicate::RealUEQ => false,
RealPredicate::RealUGT => true,
RealPredicate::RealUGE => true,
RealPredicate::RealULT => true,
RealPredicate::RealULE => true,
RealPredicate::RealUNE => false,
RealPredicate::RealPredicateTrue => unreachable!(),
};
let cmp = self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs);
if must_handle_nan {
let is_nan = self.context.new_binary_op(
self.location,
BinaryOp::LogicalOr,
self.cx.bool_type,
// compare a value to itself to check whether it is NaN
self.context.new_comparison(self.location, ComparisonOp::NotEquals, lhs, lhs),
self.context.new_comparison(self.location, ComparisonOp::NotEquals, rhs, rhs),
);
self.context.new_binary_op(
self.location,
BinaryOp::LogicalOr,
self.cx.bool_type,
is_nan,
cmp,
)
} else {
cmp
}
}
/* Miscellaneous instructions */

View file

@ -23,6 +23,8 @@ use rustc_target::spec::{
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi,
};
#[cfg(feature = "master")]
use crate::abi::conv_to_fn_attribute;
use crate::callee::get_fn;
use crate::common::SignType;
@ -213,33 +215,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let bool_type = context.new_type::<bool>();
let mut functions = FxHashMap::default();
let builtins = [
"__builtin_unreachable",
"abort",
"__builtin_expect", /*"__builtin_expect_with_probability",*/
"__builtin_constant_p",
"__builtin_add_overflow",
"__builtin_mul_overflow",
"__builtin_saddll_overflow",
/*"__builtin_sadd_overflow",*/
"__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/
"__builtin_ssubll_overflow",
/*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow",
"__builtin_uaddll_overflow",
"__builtin_uadd_overflow",
"__builtin_umulll_overflow",
"__builtin_umul_overflow",
"__builtin_usubll_overflow",
"__builtin_usub_overflow",
"__builtin_powif",
"__builtin_powi",
"fabsf",
"fabs",
"copysignf",
"copysign",
"nearbyintf",
"nearbyint",
];
let builtins = ["abort"];
for builtin in builtins.iter() {
functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
@ -509,7 +485,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
let entry_name = self.sess().target.entry_name.as_ref();
if !self.functions.borrow().contains_key(entry_name) {
Some(self.declare_entry_fn(entry_name, fn_type, ()))
#[cfg(feature = "master")]
let conv = conv_to_fn_attribute(self.sess().target.entry_abi, &self.sess().target.arch);
#[cfg(not(feature = "master"))]
let conv = None;
Some(self.declare_entry_fn(entry_name, fn_type, conv))
} else {
// If the symbol already exists, it is an error: for example, the user wrote
// #[no_mangle] extern "C" fn main(..) {..}
@ -605,7 +585,10 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
let mut name = String::with_capacity(prefix.len() + 6);
name.push_str(prefix);
name.push('.');
name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
// Offset the index by the base so that always at least two characters
// are generated. This avoids cases where the suffix is interpreted as
// size by the assembler (for m68k: .b, .w, .l).
name.push_str(&(idx as u64 + ALPHANUMERIC_ONLY as u64).to_base(ALPHANUMERIC_ONLY));
name
}
}

View file

@ -58,7 +58,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
variadic: bool,
) -> Function<'gcc> {
self.linkage.set(FunctionType::Extern);
declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic)
declare_raw_fn(self, name, None, return_type, params, variadic)
}
pub fn declare_global(
@ -92,7 +92,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
&self,
name: &str,
_fn_type: Type<'gcc>,
callconv: (), /*llvm::CCallConv*/
#[cfg(feature = "master")] callconv: Option<FnAttribute<'gcc>>,
#[cfg(not(feature = "master"))] callconv: Option<()>,
) -> RValue<'gcc> {
// TODO(antoyo): use the fn_type parameter.
let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
@ -123,14 +124,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
#[cfg(feature = "master")]
fn_attributes,
} = fn_abi.gcc_type(self);
let func = declare_raw_fn(
self,
name,
(), /*fn_abi.llvm_cconv()*/
return_type,
&arguments_type,
is_c_variadic,
);
#[cfg(feature = "master")]
let conv = fn_abi.gcc_cconv(self);
#[cfg(not(feature = "master"))]
let conv = None;
let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic);
self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
#[cfg(feature = "master")]
for fn_attr in fn_attributes {
@ -162,7 +160,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
fn declare_raw_fn<'gcc>(
cx: &CodegenCx<'gcc, '_>,
name: &str,
_callconv: (), /*llvm::CallConv*/
#[cfg(feature = "master")] callconv: Option<FnAttribute<'gcc>>,
#[cfg(not(feature = "master"))] _callconv: Option<()>,
return_type: Type<'gcc>,
param_types: &[Type<'gcc>],
variadic: bool,
@ -192,6 +191,10 @@ fn declare_raw_fn<'gcc>(
let name = &mangle_name(name);
let func =
cx.context.new_function(None, cx.linkage.get(), return_type, &params, name, variadic);
#[cfg(feature = "master")]
if let Some(attribute) = callconv {
func.add_attribute(attribute);
}
cx.functions.borrow_mut().insert(name.to_string(), func);
#[cfg(feature = "master")]

View file

@ -194,6 +194,7 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]>
fn arch_to_gcc(name: &str) -> &str {
match name {
"M68000" => "68000",
"M68020" => "68020",
_ => name,
}

View file

@ -432,8 +432,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
);
self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr])
};
// NOTE: we must assign the result of the operation to a variable at this point to make
// sure it will be evaluated by libgccjit now.
// Otherwise, it will only be evaluated when the rvalue for the call is used somewhere else
// and overflow_value will not be initialized at the correct point in the program.
let result = self.current_func().new_local(self.location, res_type, "result");
self.block.add_assignment(self.location, result, call);
(result, self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue())
(
result.to_rvalue(),
self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue(),
)
}
pub fn gcc_icmp(
@ -865,6 +874,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let value_type = value.get_type();
if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type)
{
// TODO: use self.location.
self.context.new_cast(None, value, dest_typ)
} else if self.is_native_int_type_or_bool(dest_typ) {
self.context.new_cast(None, self.low(value), dest_typ)
@ -905,6 +915,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let name_suffix = match self.type_kind(dest_typ) {
TypeKind::Float => "tisf",
TypeKind::Double => "tidf",
TypeKind::FP128 => "tixf",
kind => panic!("cannot cast a non-native integer to type {:?}", kind),
};
let sign = if signed { "" } else { "un" };

View file

@ -1,11 +1,90 @@
use std::borrow::Cow;
use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue, UnaryOp};
use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type};
use rustc_codegen_ssa::traits::BuilderMethods;
use crate::builder::Builder;
use crate::context::CodegenCx;
fn encode_key_128_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let field1 = builder.context.new_field(None, builder.u32_type, "field1");
let field2 = builder.context.new_field(None, m128i, "field2");
let field3 = builder.context.new_field(None, m128i, "field3");
let field4 = builder.context.new_field(None, m128i, "field4");
let field5 = builder.context.new_field(None, m128i, "field5");
let field6 = builder.context.new_field(None, m128i, "field6");
let field7 = builder.context.new_field(None, m128i, "field7");
let encode_type = builder.context.new_struct_type(
None,
"EncodeKey128Output",
&[field1, field2, field3, field4, field5, field6, field7],
);
#[cfg(feature = "master")]
encode_type.as_type().set_packed();
(encode_type.as_type(), field1, field2)
}
fn encode_key_256_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let field1 = builder.context.new_field(None, builder.u32_type, "field1");
let field2 = builder.context.new_field(None, m128i, "field2");
let field3 = builder.context.new_field(None, m128i, "field3");
let field4 = builder.context.new_field(None, m128i, "field4");
let field5 = builder.context.new_field(None, m128i, "field5");
let field6 = builder.context.new_field(None, m128i, "field6");
let field7 = builder.context.new_field(None, m128i, "field7");
let field8 = builder.context.new_field(None, m128i, "field8");
let encode_type = builder.context.new_struct_type(
None,
"EncodeKey256Output",
&[field1, field2, field3, field4, field5, field6, field7, field8],
);
#[cfg(feature = "master")]
encode_type.as_type().set_packed();
(encode_type.as_type(), field1, field2)
}
fn aes_output_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let field1 = builder.context.new_field(None, builder.u8_type, "field1");
let field2 = builder.context.new_field(None, m128i, "field2");
let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]);
let typ = aes_output_type.as_type();
#[cfg(feature = "master")]
typ.set_packed();
(typ, field1, field2)
}
fn wide_aes_output_type<'a, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) {
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let field1 = builder.context.new_field(None, builder.u8_type, "field1");
let field2 = builder.context.new_field(None, m128i, "field2");
let field3 = builder.context.new_field(None, m128i, "field3");
let field4 = builder.context.new_field(None, m128i, "field4");
let field5 = builder.context.new_field(None, m128i, "field5");
let field6 = builder.context.new_field(None, m128i, "field6");
let field7 = builder.context.new_field(None, m128i, "field7");
let field8 = builder.context.new_field(None, m128i, "field8");
let field9 = builder.context.new_field(None, m128i, "field9");
let aes_output_type = builder.context.new_struct_type(
None,
"WideAesOutput",
&[field1, field2, field3, field4, field5, field6, field7, field8, field9],
);
#[cfg(feature = "master")]
aes_output_type.as_type().set_packed();
(aes_output_type.as_type(), field1, field2)
}
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
pub fn adjust_function<'gcc>(
context: &'gcc Context<'gcc>,
@ -43,7 +122,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
gcc_func: FunctionPtrType<'gcc>,
mut args: Cow<'b, [RValue<'gcc>]>,
func_name: &str,
original_function_name: Option<&String>,
) -> Cow<'b, [RValue<'gcc>]> {
// TODO: this might not be a good way to workaround the missing tile builtins.
if func_name == "__builtin_trap" {
@ -504,6 +582,72 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
let arg4 = builder.context.new_rvalue_from_int(arg4_type, -1);
args = vec![a, b, c, arg4, new_args[3]].into();
}
"__builtin_ia32_encodekey128_u32" => {
let mut new_args = args.to_vec();
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let array_type = builder.context.new_array_type(None, m128i, 6);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
args = new_args.into();
}
"__builtin_ia32_encodekey256_u32" => {
let mut new_args = args.to_vec();
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let array_type = builder.context.new_array_type(None, m128i, 7);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
args = new_args.into();
}
"__builtin_ia32_aesenc128kl_u8"
| "__builtin_ia32_aesdec128kl_u8"
| "__builtin_ia32_aesenc256kl_u8"
| "__builtin_ia32_aesdec256kl_u8" => {
let mut new_args = vec![];
let m128i = builder.context.new_vector_type(builder.i64_type, 2);
let result = builder.current_func().new_local(None, m128i, "result");
new_args.push(result.get_address(None));
new_args.extend(args.to_vec());
args = new_args.into();
}
"__builtin_ia32_aesencwide128kl_u8"
| "__builtin_ia32_aesdecwide128kl_u8"
| "__builtin_ia32_aesencwide256kl_u8"
| "__builtin_ia32_aesdecwide256kl_u8" => {
let mut new_args = vec![];
let mut old_args = args.to_vec();
let handle = old_args.swap_remove(0); // Called __P in GCC.
let first_value = old_args.swap_remove(0);
let element_type = first_value.get_type();
let array_type = builder.context.new_array_type(None, element_type, 8);
let result = builder.current_func().new_local(None, array_type, "result");
new_args.push(result.get_address(None));
let array = builder.current_func().new_local(None, array_type, "array");
let input = builder.context.new_array_constructor(
None,
array_type,
&[
first_value,
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
old_args.swap_remove(0),
],
);
builder.llbb().add_assignment(None, array, input);
let input_ptr = array.get_address(None);
let arg2_type = gcc_func.get_param_type(1);
let input_ptr = builder.context.new_cast(None, input_ptr, arg2_type);
new_args.push(input_ptr);
new_args.push(handle);
args = new_args.into();
}
_ => (),
}
} else {
@ -541,33 +685,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
let c = builder.context.new_rvalue_from_vector(None, arg3_type, &[new_args[2]; 2]);
args = vec![a, b, c, new_args[3]].into();
}
"__builtin_ia32_vfmaddsubpd256"
| "__builtin_ia32_vfmaddsubps"
| "__builtin_ia32_vfmaddsubps256"
| "__builtin_ia32_vfmaddsubpd" => {
if let Some(original_function_name) = original_function_name {
match &**original_function_name {
"llvm.x86.fma.vfmsubadd.pd.256"
| "llvm.x86.fma.vfmsubadd.ps"
| "llvm.x86.fma.vfmsubadd.ps.256"
| "llvm.x86.fma.vfmsubadd.pd" => {
// NOTE: since both llvm.x86.fma.vfmsubadd.ps and llvm.x86.fma.vfmaddsub.ps maps to
// __builtin_ia32_vfmaddsubps, only add minus if this comes from a
// subadd LLVM intrinsic, e.g. _mm256_fmsubadd_pd.
let mut new_args = args.to_vec();
let arg3 = &mut new_args[2];
*arg3 = builder.context.new_unary_op(
None,
UnaryOp::Minus,
arg3.get_type(),
*arg3,
);
args = new_args.into();
}
_ => (),
}
}
}
"__builtin_ia32_ldmxcsr" => {
// The builtin __builtin_ia32_ldmxcsr takes an integer value while llvm.x86.sse.ldmxcsr takes a pointer,
// so dereference the pointer.
@ -728,6 +845,96 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
let f16_type = builder.context.new_c_type(CType::Float16);
return_value = builder.context.new_cast(None, return_value, f16_type);
}
"__builtin_ia32_encodekey128_u32" => {
// The builtin __builtin_ia32_encodekey128_u32 writes the result in its pointer argument while
// llvm.x86.encodekey128 returns a value.
// We added a result pointer argument and now need to assign its value to the return_value expected by
// the LLVM intrinsic.
let (encode_type, field1, field2) = encode_key_128_type(builder);
let result = builder.current_func().new_local(None, encode_type, "result");
let field1 = result.access_field(None, field1);
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 6);
let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
builder.llbb().add_assignment(
None,
field2_ptr.dereference(None),
ptr.dereference(None),
);
return_value = result.to_rvalue();
}
"__builtin_ia32_encodekey256_u32" => {
// The builtin __builtin_ia32_encodekey256_u32 writes the result in its pointer argument while
// llvm.x86.encodekey256 returns a value.
// We added a result pointer argument and now need to assign its value to the return_value expected by
// the LLVM intrinsic.
let (encode_type, field1, field2) = encode_key_256_type(builder);
let result = builder.current_func().new_local(None, encode_type, "result");
let field1 = result.access_field(None, field1);
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 7);
let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
builder.llbb().add_assignment(
None,
field2_ptr.dereference(None),
ptr.dereference(None),
);
return_value = result.to_rvalue();
}
"__builtin_ia32_aesdec128kl_u8"
| "__builtin_ia32_aesenc128kl_u8"
| "__builtin_ia32_aesdec256kl_u8"
| "__builtin_ia32_aesenc256kl_u8" => {
// The builtin for aesdec/aesenc writes the result in its pointer argument while
// llvm.x86.aesdec128kl returns a value.
// We added a result pointer argument and now need to assign its value to the return_value expected by
// the LLVM intrinsic.
let (aes_output_type, field1, field2) = aes_output_type(builder);
let result = builder.current_func().new_local(None, aes_output_type, "result");
let field1 = result.access_field(None, field1);
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let ptr = builder.context.new_cast(
None,
args[0],
field2.to_rvalue().get_type().make_pointer(),
);
builder.llbb().add_assignment(None, field2, ptr.dereference(None));
return_value = result.to_rvalue();
}
"__builtin_ia32_aesencwide128kl_u8"
| "__builtin_ia32_aesdecwide128kl_u8"
| "__builtin_ia32_aesencwide256kl_u8"
| "__builtin_ia32_aesdecwide256kl_u8" => {
// The builtin for aesdecwide/aesencwide writes the result in its pointer argument while
// llvm.x86.aesencwide128kl returns a value.
// We added a result pointer argument and now need to assign its value to the return_value expected by
// the LLVM intrinsic.
let (aes_output_type, field1, field2) = wide_aes_output_type(builder);
let result = builder.current_func().new_local(None, aes_output_type, "result");
let field1 = result.access_field(None, field1);
builder.llbb().add_assignment(None, field1, return_value);
let field2 = result.access_field(None, field2);
let field2_type = field2.to_rvalue().get_type();
let array_type = builder.context.new_array_type(None, field2_type, 8);
let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer());
let field2_ptr =
builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer());
builder.llbb().add_assignment(
None,
field2_ptr.dereference(None),
ptr.dereference(None),
);
return_value = result.to_rvalue();
}
_ => (),
}
@ -915,16 +1122,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.ctlz.v4i64" => "__builtin_ia32_vplzcntq_256_mask",
"llvm.ctlz.v2i64" => "__builtin_ia32_vplzcntq_128_mask",
"llvm.ctpop.v32i16" => "__builtin_ia32_vpopcountw_v32hi",
"llvm.x86.fma.vfmsub.sd" => "__builtin_ia32_vfmsubsd3",
"llvm.x86.fma.vfmsub.ss" => "__builtin_ia32_vfmsubss3",
"llvm.x86.fma.vfmsubadd.pd" => "__builtin_ia32_vfmaddsubpd",
"llvm.x86.fma.vfmsubadd.pd.256" => "__builtin_ia32_vfmaddsubpd256",
"llvm.x86.fma.vfmsubadd.ps" => "__builtin_ia32_vfmaddsubps",
"llvm.x86.fma.vfmsubadd.ps.256" => "__builtin_ia32_vfmaddsubps256",
"llvm.x86.fma.vfnmadd.sd" => "__builtin_ia32_vfnmaddsd3",
"llvm.x86.fma.vfnmadd.ss" => "__builtin_ia32_vfnmaddss3",
"llvm.x86.fma.vfnmsub.sd" => "__builtin_ia32_vfnmsubsd3",
"llvm.x86.fma.vfnmsub.ss" => "__builtin_ia32_vfnmsubss3",
"llvm.x86.avx512.conflict.d.512" => "__builtin_ia32_vpconflictsi_512_mask",
"llvm.x86.avx512.conflict.d.256" => "__builtin_ia32_vpconflictsi_256_mask",
"llvm.x86.avx512.conflict.d.128" => "__builtin_ia32_vpconflictsi_128_mask",
@ -1002,8 +1199,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.fshr.v32i16" => "__builtin_ia32_vpshrdv_v32hi",
"llvm.fshr.v16i16" => "__builtin_ia32_vpshrdv_v16hi",
"llvm.fshr.v8i16" => "__builtin_ia32_vpshrdv_v8hi",
"llvm.x86.fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd3",
"llvm.x86.fma.vfmadd.ss" => "__builtin_ia32_vfmaddss3",
"llvm.x86.rdrand.64" => "__builtin_ia32_rdrand64_step",
// The above doc points to unknown builtins for the following, so override them:
@ -1324,6 +1519,16 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
"llvm.x86.avx512fp16.mask.vfmadd.cph.256" => "__builtin_ia32_vfmaddcph256_mask3",
"llvm.x86.avx512fp16.mask.vfcmadd.cph.128" => "__builtin_ia32_vfcmaddcph128_mask3",
"llvm.x86.avx512fp16.mask.vfmadd.cph.128" => "__builtin_ia32_vfmaddcph128_mask3",
"llvm.x86.encodekey128" => "__builtin_ia32_encodekey128_u32",
"llvm.x86.encodekey256" => "__builtin_ia32_encodekey256_u32",
"llvm.x86.aesenc128kl" => "__builtin_ia32_aesenc128kl_u8",
"llvm.x86.aesdec128kl" => "__builtin_ia32_aesdec128kl_u8",
"llvm.x86.aesenc256kl" => "__builtin_ia32_aesenc256kl_u8",
"llvm.x86.aesdec256kl" => "__builtin_ia32_aesdec256kl_u8",
"llvm.x86.aesencwide128kl" => "__builtin_ia32_aesencwide128kl_u8",
"llvm.x86.aesdecwide128kl" => "__builtin_ia32_aesdecwide128kl_u8",
"llvm.x86.aesencwide256kl" => "__builtin_ia32_aesencwide256kl_u8",
"llvm.x86.aesdecwide256kl" => "__builtin_ia32_aesdecwide256kl_u8",
// TODO: support the tile builtins:
"llvm.x86.ldtilecfg" => "__builtin_trap",

View file

@ -78,6 +78,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
sym::maxnumf64 => "fmax",
sym::copysignf32 => "copysignf",
sym::copysignf64 => "copysign",
sym::copysignf128 => "copysignl",
sym::floorf32 => "floorf",
sym::floorf64 => "floor",
sym::ceilf32 => "ceilf",

View file

@ -399,7 +399,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
}
#[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 {
@ -410,6 +410,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
out_ty: arg_tys[2]
}
);
// TODO(antoyo): For simd_insert, check if the index is a constant of the correct size.
let vector = args[0].immediate();
let index = args[1].immediate();
let value = args[2].immediate();
@ -422,13 +424,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
}
#[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 { span, name, in_elem, in_ty, ret_ty }
);
// TODO(antoyo): For simd_extract, check if the index is a constant of the correct size.
let vector = args[0].immediate();
return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
let index = args[1].immediate();
return Ok(bx.context.new_vector_access(None, vector, index).to_rvalue());
}
if name == sym::simd_select {

View file

@ -188,10 +188,10 @@ impl CodegenBackend for GccCodegenBackend {
crate::DEFAULT_LOCALE_RESOURCE
}
fn init(&self, sess: &Session) {
fn init(&self, _sess: &Session) {
#[cfg(feature = "master")]
{
let target_cpu = target_cpu(sess);
let target_cpu = target_cpu(_sess);
// Get the second TargetInfo with the correct CPU features by setting the arch.
let context = Context::default();

View file

@ -1,11 +1,9 @@
tests/ui/allocator/no_std-alloc-error-handler-custom.rs
tests/ui/allocator/no_std-alloc-error-handler-default.rs
tests/ui/asm/may_unwind.rs
tests/ui/asm/x86_64/multiple-clobber-abi.rs
tests/ui/functions-closures/parallel-codegen-closures.rs
tests/ui/linkage-attr/linkage1.rs
tests/ui/lto/dylib-works.rs
tests/ui/numbers-arithmetic/saturating-float-casts.rs
tests/ui/sepcomp/sepcomp-cci.rs
tests/ui/sepcomp/sepcomp-extern.rs
tests/ui/sepcomp/sepcomp-fns-backwards.rs
@ -33,7 +31,6 @@ tests/ui/unwind-no-uwtable.rs
tests/ui/parser/unclosed-delimiter-in-dep.rs
tests/ui/consts/missing_span_in_backtrace.rs
tests/ui/drop/dynamic-drop.rs
tests/ui/issues/issue-40883.rs
tests/ui/issues/issue-43853.rs
tests/ui/issues/issue-47364.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
@ -102,14 +99,12 @@ tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs
tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs
tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs
@ -117,8 +112,9 @@ tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs
tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs
tests/ui/simd/simd-bitmask-notpow2.rs
tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs
tests/ui/uninhabited/uninhabited-transparent-return-abi.rs

View file

@ -3,45 +3,13 @@
// Run-time:
// status: signal
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
#![allow(internal_features)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
mod intrinsics {
use super::Sized;
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn abort() -> !;
}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
fn test_fail() -> ! {
unsafe { intrinsics::abort() };

View file

@ -3,45 +3,13 @@
// Run-time:
// status: signal
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
#![allow(internal_features)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
mod intrinsics {
use super::Sized;
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn abort() -> !;
}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
fn fail() -> i32 {
unsafe { intrinsics::abort() };

View file

@ -8,20 +8,12 @@
// 10
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
pub fn puts(s: *const u8) -> i32;
}
}
use mini_core::*;
static mut ONE: usize = 1;

View file

@ -174,6 +174,59 @@ fn asm() {
mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3);
}
assert_eq!(array1, array2);
// in and clobber registers cannot overlap. This tests that the lateout register without an
// output place (indicated by the `_`) is not added to the list of clobbered registers
let x = 8;
let y: i32;
unsafe {
asm!(
"mov rax, rdi",
in("rdi") x,
lateout("rdi") _,
out("rax") y,
);
}
assert_eq!((x, y), (8, 8));
// sysv64 is the default calling convention on unix systems. The rdi register is
// used to pass arguments in the sysv64 calling convention, so this register will be clobbered
#[cfg(unix)]
{
let x = 16;
let y: i32;
unsafe {
asm!(
"mov rax, rdi",
in("rdi") x,
out("rax") y,
clobber_abi("sysv64"),
);
}
assert_eq!((x, y), (16, 16));
}
// the `b` suffix for registers in the `reg_byte` register class is not supported in GCC
// and needs to be stripped in order to use these registers.
unsafe {
core::arch::asm!(
"",
out("al") _,
out("bl") _,
out("cl") _,
out("dl") _,
out("sil") _,
out("dil") _,
out("r8b") _,
out("r9b") _,
out("r10b") _,
out("r11b") _,
out("r12b") _,
out("r13b") _,
out("r14b") _,
out("r15b") _,
);
}
}
#[cfg(not(target_arch = "x86_64"))]

View file

@ -5,130 +5,13 @@
// 7 8
// 10
#![allow(internal_features, unused_attributes)]
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
impl Copy for *mut i32 {}
impl Copy for usize {}
impl Copy for u8 {}
impl Copy for i8 {}
impl Copy for i32 {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
#[lang = "panic_location"]
struct PanicLocation {
file: &'static str,
line: u32,
column: u32,
}
mod libc {
#[link(name = "c")]
extern "C" {
pub fn puts(s: *const u8) -> i32;
pub fn fflush(stream: *mut i32) -> i32;
pub fn printf(format: *const i8, ...) -> i32;
pub static stdout: *mut i32;
}
}
mod intrinsics {
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn abort() -> !;
}
#[lang = "panic"]
#[track_caller]
#[no_mangle]
pub fn panic(_msg: &'static str) -> ! {
unsafe {
libc::puts("Panicking\0" as *const str as *const u8);
libc::fflush(libc::stdout);
intrinsics::abort();
}
}
#[lang = "add"]
trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
impl Add for u8 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for i8 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for i32 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for usize {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for isize {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
#[track_caller]
#[lang = "panic_const_add_overflow"]
pub fn panic_const_add_overflow() -> ! {
panic("attempt to add with overflow");
}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
fn inc_ref(num: &mut isize) -> isize {
*num = *num + 5;
@ -139,9 +22,8 @@ fn inc(num: isize) -> isize {
num + 1
}
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
argc = inc(argc);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc);

View file

@ -9,55 +9,38 @@
// Both args: 11
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 {
let string = "Arg: %d\n\0";
let mut closure = || {
unsafe {
libc::printf(string as *const str as *const i8, argc);
}
let mut closure = || unsafe {
libc::printf(string as *const str as *const i8, argc);
};
closure();
let mut closure = || {
unsafe {
libc::printf("Argument: %d\n\0" as *const str as *const i8, argc);
}
let mut closure = || unsafe {
libc::printf("Argument: %d\n\0" as *const str as *const i8, argc);
};
closure();
let mut closure = |string| {
unsafe {
libc::printf(string as *const str as *const i8, argc);
}
let mut closure = |string| unsafe {
libc::printf(string as *const str as *const i8, argc);
};
closure("String arg: %d\n\0");
let mut closure = |arg: isize| {
unsafe {
libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg);
}
let mut closure = |arg: isize| unsafe {
libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg);
};
closure(argc + 1);
let mut closure = |string, arg: isize| {
unsafe {
libc::printf(string as *const str as *const i8, arg);
}
let mut closure = |string, arg: isize| unsafe {
libc::printf(string as *const str as *const i8, arg);
};
closure("Both args: %d\n\0", argc + 10);

View file

@ -6,19 +6,12 @@
// 1
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
@ -27,15 +20,14 @@ extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
libc::printf(b"true\n\0" as *const u8 as *const i8);
}
let string =
match argc {
1 => b"1\n\0",
2 => b"2\n\0",
3 => b"3\n\0",
4 => b"4\n\0",
5 => b"5\n\0",
_ => b"_\n\0",
};
let string = match argc {
1 => b"1\n\0",
2 => b"2\n\0",
3 => b"3\n\0",
4 => b"4\n\0",
5 => b"5\n\0",
_ => b"_\n\0",
};
libc::printf(string as *const u8 as *const i8);
}
0

View file

@ -3,37 +3,13 @@
// Run-time:
// status: 0
#![feature(auto_traits, lang_items, no_core)]
#![allow(internal_features)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {

View file

@ -3,44 +3,13 @@
// Run-time:
// status: 2
#![feature(auto_traits, lang_items, no_core, intrinsics)]
#![allow(internal_features)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
mod libc {
#[link(name = "c")]
extern "C" {
pub fn exit(status: i32);
}
}
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {

View file

@ -3,37 +3,13 @@
// Run-time:
// status: 1
#![feature(auto_traits, lang_items, no_core)]
#![allow(internal_features)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {

View file

@ -0,0 +1,28 @@
// Compiler:
//
// Run-time:
// status: 0
#![feature(const_black_box)]
fn main() {
use std::hint::black_box;
macro_rules! check {
($ty:ty, $expr:expr) => {{
const EXPECTED: $ty = $expr;
assert_eq!($expr, EXPECTED);
}};
}
check!(i32, (black_box(0.0f32) as i32));
check!(u64, (black_box(f32::NAN) as u64));
check!(u128, (black_box(f32::NAN) as u128));
check!(i64, (black_box(f64::NAN) as i64));
check!(u64, (black_box(f64::NAN) as u64));
check!(i16, (black_box(f32::MIN) as i16));
check!(i16, (black_box(f32::MAX) as i16));
}

View file

@ -5,19 +5,12 @@
// stdout: 1
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
use mini_core::*;
fn i16_as_i8(a: i16) -> i8 {
a as i8

View file

@ -3,9 +3,7 @@
// Run-time:
// status: 0
/*
* Code
*/
#![feature(const_black_box)]
fn main() {
use std::hint::black_box;

View file

@ -1,4 +1,3 @@
// Compiler:
//
// Run-time:
@ -7,139 +6,20 @@
// 6
// 11
#![allow(internal_features, unused_attributes)]
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
impl Copy for *mut i32 {}
impl Copy for usize {}
impl Copy for u8 {}
impl Copy for i8 {}
impl Copy for i32 {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
#[lang = "panic_location"]
struct PanicLocation {
file: &'static str,
line: u32,
column: u32,
}
mod libc {
#[link(name = "c")]
extern "C" {
pub fn puts(s: *const u8) -> i32;
pub fn fflush(stream: *mut i32) -> i32;
pub fn printf(format: *const i8, ...) -> i32;
pub static stdout: *mut i32;
}
}
mod intrinsics {
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn abort() -> !;
}
#[lang = "panic"]
#[track_caller]
#[no_mangle]
pub fn panic(_msg: &'static str) -> ! {
unsafe {
libc::puts("Panicking\0" as *const str as *const u8);
libc::fflush(libc::stdout);
intrinsics::abort();
}
}
#[lang = "add"]
trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
impl Add for u8 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for i8 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for i32 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for usize {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for isize {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
#[track_caller]
#[lang = "panic_const_add_overflow"]
pub fn panic_const_add_overflow() -> ! {
panic("attempt to add with overflow");
}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
struct Test {
field: isize,
}
fn test(num: isize) -> Test {
Test {
field: num + 1,
}
Test { field: num + 1 }
}
fn update_num(num: &mut isize) {
@ -147,7 +27,7 @@ fn update_num(num: &mut isize) {
}
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 {
let mut test = test(argc);
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);

View file

@ -5,229 +5,13 @@
// 39
// 10
#![allow(internal_features, unused_attributes)]
#![feature(auto_traits, lang_items, no_core, intrinsics, arbitrary_self_types, rustc_attrs)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
impl Copy for *mut i32 {}
impl Copy for usize {}
impl Copy for u8 {}
impl Copy for i8 {}
impl Copy for i16 {}
impl Copy for i32 {}
#[lang = "deref"]
pub trait Deref {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}
#[lang = "legacy_receiver"]
trait LegacyReceiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
#[lang = "panic_location"]
struct PanicLocation {
file: &'static str,
line: u32,
column: u32,
}
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
pub fn puts(s: *const u8) -> i32;
pub fn fflush(stream: *mut i32) -> i32;
pub static stdout: *mut i32;
}
}
mod intrinsics {
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn abort() -> !;
}
#[lang = "panic"]
#[track_caller]
#[no_mangle]
pub fn panic(_msg: &'static str) -> ! {
unsafe {
libc::puts("Panicking\0" as *const str as *const u8);
libc::fflush(libc::stdout);
intrinsics::abort();
}
}
#[lang = "add"]
trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
impl Add for u8 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for i8 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for i32 {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for usize {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
impl Add for isize {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self + rhs
}
}
#[lang = "sub"]
pub trait Sub<RHS = Self> {
type Output;
fn sub(self, rhs: RHS) -> Self::Output;
}
impl Sub for usize {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self - rhs
}
}
impl Sub for isize {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self - rhs
}
}
impl Sub for u8 {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self - rhs
}
}
impl Sub for i8 {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self - rhs
}
}
impl Sub for i16 {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self - rhs
}
}
#[lang = "mul"]
pub trait Mul<RHS = Self> {
type Output;
#[must_use]
fn mul(self, rhs: RHS) -> Self::Output;
}
impl Mul for u8 {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self * rhs
}
}
impl Mul for usize {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self * rhs
}
}
impl Mul for isize {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self * rhs
}
}
#[track_caller]
#[lang = "panic_const_add_overflow"]
pub fn panic_const_add_overflow() -> ! {
panic("attempt to add with overflow");
}
#[track_caller]
#[lang = "panic_const_sub_overflow"]
pub fn panic_const_sub_overflow() -> ! {
panic("attempt to subtract with overflow");
}
#[track_caller]
#[lang = "panic_const_mul_overflow"]
pub fn panic_const_mul_overflow() -> ! {
panic("attempt to multiply with overflow");
}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {

View file

@ -2,35 +2,32 @@
//
// Run-time:
// status: 0
// stdout: 1
// stdout: 10
// 10
// 42
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
use mini_core::*;
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
static mut ONE: usize = 1;
fn make_array() -> [u8; 3] {
[42, 10, 5]
fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) {
(
a as u8, a as u16, a as u32, a as usize, a as i8, a as i16, a as i32, a as isize, b as u8,
b as u32,
)
}
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42);
unsafe {
let ptr = ONE as *mut usize;
let value = ptr as usize;
libc::printf(b"%ld\n\0" as *const u8 as *const i8, value);
libc::printf(b"%d\n\0" as *const u8 as *const i8, c);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, d);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, j);
}
0
}

View file

@ -6,54 +6,19 @@
// 10
// 42
<<<<<<< HEAD
#![feature(auto_traits, lang_items, no_core, intrinsics)]
#![allow(internal_features)]
=======
#![feature(no_core)]
>>>>>>> db1a31c243a649e1fe20f5466ba181da5be35c14
#![no_std]
#![no_core]
#![no_main]
#[lang = "copy"]
pub unsafe trait Copy {}
impl Copy for bool {}
impl Copy for u8 {}
impl Copy for u16 {}
impl Copy for u32 {}
impl Copy for u64 {}
impl Copy for usize {}
impl Copy for i8 {}
impl Copy for i16 {}
impl Copy for i32 {}
impl Copy for isize {}
impl Copy for f32 {}
impl Copy for char {}
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "legacy_receiver"]
trait LegacyReceiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) {
(

View file

@ -5,26 +5,17 @@
// stdout: 5
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
extern crate mini_core;
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
use mini_core::*;
static mut TWO: usize = 2;
fn index_slice(s: &[u32]) -> u32 {
unsafe {
s[TWO]
}
unsafe { s[TWO] }
}
#[no_mangle]

View file

@ -9,70 +9,13 @@
// 12
// 1
#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)]
#![allow(internal_features)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "destruct"]
pub trait Destruct {}
#[lang = "drop"]
pub trait Drop {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
impl<T: ?Sized> Copy for *mut T {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
mod intrinsics {
use super::Sized;
#[rustc_nounwind]
#[rustc_intrinsic]
pub fn abort() -> !;
}
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
#[lang = "structural_peq"]
pub trait StructuralPartialEq {}
#[lang = "drop_in_place"]
#[allow(unconditional_recursion)]
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
// Code here does not matter - this is replaced by the
// real drop glue by the compiler.
drop_in_place(to_drop);
}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
struct Test {
field: isize,
@ -84,20 +27,14 @@ struct WithRef {
static mut CONSTANT: isize = 10;
static mut TEST: Test = Test {
field: 12,
};
static mut TEST: Test = Test { field: 12 };
static mut TEST2: Test = Test {
field: 14,
};
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 } };
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 {
unsafe {
libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT);
libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field);

View file

@ -5,44 +5,13 @@
// stdout: 1
// 2
#![feature(auto_traits, lang_items, no_core, intrinsics)]
#![allow(internal_features)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
struct Test {
field: isize,

View file

@ -4,44 +4,13 @@
// status: 0
// stdout: 3
#![feature(auto_traits, lang_items, no_core, intrinsics)]
#![allow(internal_features)]
#![feature(no_core)]
#![no_std]
#![no_core]
#![no_main]
/*
* Core
*/
// Because we don't have core yet.
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
trait Copy {
}
impl Copy for isize {}
#[lang = "receiver"]
trait Receiver {
}
#[lang = "freeze"]
pub(crate) unsafe auto trait Freeze {}
mod libc {
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const i8, ...) -> i32;
}
}
/*
* Code
*/
extern crate mini_core;
use mini_core::*;
#[no_mangle]
extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {