Merge pull request #4281 from rust-lang/rustup-2025-04-20
Automatic Rustup
This commit is contained in:
commit
94a9e4425c
118 changed files with 1586 additions and 1655 deletions
|
|
@ -2959,21 +2959,27 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut err = self.path_does_not_live_long_enough(borrow_span, &format!("`{name}`"));
|
||||
let name = if borrow_span.in_external_macro(self.infcx.tcx.sess.source_map()) {
|
||||
// Don't name local variables in external macros.
|
||||
"value".to_string()
|
||||
} else {
|
||||
format!("`{name}`")
|
||||
};
|
||||
|
||||
let mut err = self.path_does_not_live_long_enough(borrow_span, &name);
|
||||
|
||||
if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) {
|
||||
let region_name = annotation.emit(self, &mut err);
|
||||
|
||||
err.span_label(
|
||||
borrow_span,
|
||||
format!("`{name}` would have to be valid for `{region_name}`..."),
|
||||
format!("{name} would have to be valid for `{region_name}`..."),
|
||||
);
|
||||
|
||||
err.span_label(
|
||||
drop_span,
|
||||
format!(
|
||||
"...but `{}` will be dropped here, when the {} returns",
|
||||
name,
|
||||
"...but {name} will be dropped here, when the {} returns",
|
||||
self.infcx
|
||||
.tcx
|
||||
.opt_item_name(self.mir_def_id().to_def_id())
|
||||
|
|
@ -3011,7 +3017,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
} else {
|
||||
err.span_label(borrow_span, "borrowed value does not live long enough");
|
||||
err.span_label(drop_span, format!("`{name}` dropped here while still borrowed"));
|
||||
err.span_label(drop_span, format!("{name} dropped here while still borrowed"));
|
||||
|
||||
borrow_spans.args_subdiag(&mut err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::Capture {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||
&& let hir::def::Res::Local(hir_id) = p.res
|
||||
&& let hir::Node::Pat(pat) = tcx.hir_node(hir_id)
|
||||
{
|
||||
err.span_label(pat.span, format!("binding `{ident}` declared here"));
|
||||
if !ident.span.in_external_macro(tcx.sess.source_map()) {
|
||||
err.span_label(pat.span, format!("binding `{ident}` declared here"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }}'
|
||||
|
|
|
|||
|
|
@ -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) }}'
|
||||
|
|
|
|||
|
|
@ -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) }}'
|
||||
|
|
|
|||
|
|
@ -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) }}'
|
||||
|
|
|
|||
|
|
@ -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) }}'
|
||||
|
|
|
|||
|
|
@ -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) }}'
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
e607be166673a8de9fc07f6f02c60426e556c5f2
|
||||
0ea98a1365b81f7488073512c850e8ee951a4afd
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
From af0e237f056fa838c77463381a19b0dc993c0a35 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Sun, 1 Sep 2024 11:42:17 -0400
|
||||
Subject: [PATCH] Disable not compiling tests
|
||||
|
||||
---
|
||||
library/core/tests/Cargo.toml | 14 ++++++++++++++
|
||||
library/core/tests/lib.rs | 1 +
|
||||
2 files changed, 15 insertions(+)
|
||||
create mode 100644 library/core/tests/Cargo.toml
|
||||
|
||||
diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml
|
||||
new file mode 100644
|
||||
index 0000000..ca326ac
|
||||
--- /dev/null
|
||||
+++ b/library/core/tests/Cargo.toml
|
||||
@@ -0,0 +1,14 @@
|
||||
+[workspace]
|
||||
+
|
||||
+[package]
|
||||
+name = "coretests"
|
||||
+version = "0.0.0"
|
||||
+edition = "2021"
|
||||
+
|
||||
+[lib]
|
||||
+name = "coretests"
|
||||
+path = "lib.rs"
|
||||
+
|
||||
+[dependencies]
|
||||
+rand = { version = "0.8.5", default-features = false }
|
||||
+rand_xorshift = { version = "0.3.0", default-features = false }
|
||||
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
|
||||
index a4a7946..ecfe43f 100644
|
||||
--- a/library/core/tests/lib.rs
|
||||
+++ b/library/core/tests/lib.rs
|
||||
@@ -1,4 +1,5 @@
|
||||
// tidy-alphabetical-start
|
||||
+#![cfg(test)]
|
||||
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
#![cfg_attr(test, feature(cfg_match))]
|
||||
#![feature(alloc_layout_extra)]
|
||||
--
|
||||
2.47.1
|
||||
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
||||
Date: Fri, 3 Dec 2021 12:16:30 +0100
|
||||
From ec2d0dc77fb484d926b45bb626b0db6a4bb0ab5c Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Thu, 27 Mar 2025 09:20:41 -0400
|
||||
Subject: [PATCH] Disable long running tests
|
||||
|
||||
---
|
||||
library/core/tests/slice.rs | 2 ++
|
||||
library/coretests/tests/slice.rs | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
|
||||
index 8402833..84592e0 100644
|
||||
--- a/library/core/tests/slice.rs
|
||||
+++ b/library/core/tests/slice.rs
|
||||
@@ -2462,6 +2462,7 @@ take_tests! {
|
||||
diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs
|
||||
index d17e681..fba5cd6 100644
|
||||
--- a/library/coretests/tests/slice.rs
|
||||
+++ b/library/coretests/tests/slice.rs
|
||||
@@ -2486,6 +2486,7 @@ split_off_tests! {
|
||||
#[cfg(not(miri))] // unused in Miri
|
||||
const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
|
||||
|
||||
|
|
@ -19,14 +19,14 @@ index 8402833..84592e0 100644
|
|||
// can't be a constant due to const mutability rules
|
||||
#[cfg(not(miri))] // unused in Miri
|
||||
macro_rules! empty_max_mut {
|
||||
@@ -2485,6 +2486,7 @@ take_tests! {
|
||||
(take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
|
||||
(take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
|
||||
@@ -2509,6 +2510,7 @@ split_off_tests! {
|
||||
(split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
|
||||
(split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
|
||||
}
|
||||
+*/
|
||||
|
||||
#[test]
|
||||
fn test_slice_from_ptr_range() {
|
||||
--
|
||||
2.26.2.7.g19db9cfb68
|
||||
2.49.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
From 966beefe08be6045bfcca26079b76a7a80413080 Mon Sep 17 00:00:00 2001
|
||||
From b2911e732d1bf0e28872495c4c47af1dad3c7911 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Thu, 28 Sep 2023 17:37:38 -0400
|
||||
Date: Thu, 27 Mar 2025 14:30:10 -0400
|
||||
Subject: [PATCH] Disable libstd and libtest dylib
|
||||
|
||||
---
|
||||
library/std/Cargo.toml | 2 +-
|
||||
library/test/Cargo.toml | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
library/std/Cargo.toml | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
|
||||
index 5b21355..cb0c49b 100644
|
||||
index 176da60..c183cdb 100644
|
||||
--- a/library/std/Cargo.toml
|
||||
+++ b/library/std/Cargo.toml
|
||||
@@ -9,7 +9,7 @@ description = "The Rust Standard Library"
|
||||
edition = "2021"
|
||||
@@ -10,7 +10,7 @@ edition = "2024"
|
||||
autobenches = false
|
||||
|
||||
[lib]
|
||||
-crate-type = ["dylib", "rlib"]
|
||||
|
|
@ -21,3 +20,6 @@ index 5b21355..cb0c49b 100644
|
|||
|
||||
[dependencies]
|
||||
alloc = { path = "../alloc", public = true }
|
||||
--
|
||||
2.49.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,17 @@
|
|||
From 124a11ce086952a5794d5cfbaa45175809497b81 Mon Sep 17 00:00:00 2001
|
||||
From 1a8f6b8e39f343959d4d2e6b6957a6d780ac3fc0 Mon Sep 17 00:00:00 2001
|
||||
From: None <none@example.com>
|
||||
Date: Sat, 18 Nov 2023 10:50:36 -0500
|
||||
Subject: [PATCH] [core] Disable portable-simd test
|
||||
Date: Thu, 27 Mar 2025 14:32:14 -0400
|
||||
Subject: [PATCH] Disable portable-simd test
|
||||
|
||||
---
|
||||
library/core/tests/lib.rs | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
library/coretests/tests/lib.rs | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
|
||||
index b71786c..cf484d5 100644
|
||||
--- a/library/core/tests/lib.rs
|
||||
+++ b/library/core/tests/lib.rs
|
||||
@@ -87,7 +87,6 @@
|
||||
#![feature(numfmt)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pointer_is_aligned_to)]
|
||||
-#![feature(portable_simd)]
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(slice_from_ptr_range)]
|
||||
#![feature(slice_internals)]
|
||||
@@ -155,7 +154,6 @@ mod pin;
|
||||
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
|
||||
index 79022fe..9223b2f 100644
|
||||
--- a/library/coretests/tests/lib.rs
|
||||
+++ b/library/coretests/tests/lib.rs
|
||||
@@ -165,7 +165,6 @@ mod pin;
|
||||
mod pin_macro;
|
||||
mod ptr;
|
||||
mod result;
|
||||
|
|
@ -27,4 +19,6 @@ index b71786c..cf484d5 100644
|
|||
mod slice;
|
||||
mod str;
|
||||
mod str_lossy;
|
||||
-- 2.45.2
|
||||
--
|
||||
2.49.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-01-12"
|
||||
channel = "nightly-2025-04-17"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ use rustc_middle::ty::Ty;
|
|||
use rustc_middle::ty::layout::LayoutOf;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_session::config;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_target::callconv::Conv;
|
||||
use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
|
||||
|
||||
use crate::builder::Builder;
|
||||
|
|
@ -105,6 +107,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 +231,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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(®_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(®_name) {
|
||||
clobbers.push(reg_name);
|
||||
if is_target_supported && !clobbers.contains(®_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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, ¶ms, 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")]
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
|
||||
let result = if ret_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();
|
||||
|
|
@ -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" };
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() };
|
||||
|
|
|
|||
|
|
@ -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() };
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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"))]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
28
compiler/rustc_codegen_gcc/tests/run/float.rs
Normal file
28
compiler/rustc_codegen_gcc/tests/run/float.rs
Normal 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));
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@
|
|||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
#![feature(const_black_box)]
|
||||
|
||||
fn main() {
|
||||
use std::hint::black_box;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,54 +6,13 @@
|
|||
// 10
|
||||
// 42
|
||||
|
||||
#![feature(auto_traits, lang_items, no_core, intrinsics)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
#![feature(no_core)]
|
||||
#![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) {
|
||||
(
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -818,8 +818,8 @@ fn test_unstable_options_tracking_hash() {
|
|||
tracked!(min_function_alignment, Some(Align::EIGHT));
|
||||
tracked!(mir_emit_retag, true);
|
||||
tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
|
||||
tracked!(mir_keep_place_mention, true);
|
||||
tracked!(mir_opt_level, Some(4));
|
||||
tracked!(mir_preserve_ub, true);
|
||||
tracked!(move_size_limit, Some(4096));
|
||||
tracked!(mutable_noalias, false);
|
||||
tracked!(next_solver, NextSolverConfig { coherence: true, globally: true });
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@ bitflags::bitflags! {
|
|||
const IS_UNSAFE_CELL = 1 << 9;
|
||||
/// Indicates whether the type is `UnsafePinned`.
|
||||
const IS_UNSAFE_PINNED = 1 << 10;
|
||||
/// Indicates whether the type is anonymous.
|
||||
const IS_ANONYMOUS = 1 << 11;
|
||||
}
|
||||
}
|
||||
rustc_data_structures::external_bitflags_debug! { AdtFlags }
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
|
|||
// Since this optimization adds new basic blocks and invalidates others,
|
||||
// clean up the cfg to make it nicer for other passes
|
||||
if should_cleanup {
|
||||
simplify_cfg(body);
|
||||
simplify_cfg(tcx, body);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl<'tcx> crate::MirPass<'tcx> for Inline {
|
|||
let _guard = span.enter();
|
||||
if inline::<NormalInliner<'tcx>>(tcx, body) {
|
||||
debug!("running simplify cfg on {:?}", body.source);
|
||||
simplify_cfg(body);
|
||||
simplify_cfg(tcx, body);
|
||||
deref_finder(tcx, body);
|
||||
}
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ impl<'tcx> crate::MirPass<'tcx> for ForceInline {
|
|||
let _guard = span.enter();
|
||||
if inline::<ForceInliner<'tcx>>(tcx, body) {
|
||||
debug!("running simplify cfg on {:?}", body.source);
|
||||
simplify_cfg(body);
|
||||
simplify_cfg(tcx, body);
|
||||
deref_finder(tcx, body);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,11 +90,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
|
|||
};
|
||||
|
||||
for bb in body.basic_blocks.indices() {
|
||||
let old_len = finder.opportunities.len();
|
||||
// If we have any const-eval errors discard any opportunities found
|
||||
if finder.start_from_switch(bb).is_none() {
|
||||
finder.opportunities.truncate(old_len);
|
||||
}
|
||||
finder.start_from_switch(bb);
|
||||
}
|
||||
|
||||
let opportunities = finder.opportunities;
|
||||
|
|
@ -201,28 +197,26 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
|
||||
/// Recursion entry point to find threading opportunities.
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn start_from_switch(&mut self, bb: BasicBlock) -> Option<()> {
|
||||
fn start_from_switch(&mut self, bb: BasicBlock) {
|
||||
let bbdata = &self.body[bb];
|
||||
if bbdata.is_cleanup || self.loop_headers.contains(bb) {
|
||||
return Some(());
|
||||
return;
|
||||
}
|
||||
let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { return Some(()) };
|
||||
let Some(discr) = discr.place() else { return Some(()) };
|
||||
let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { return };
|
||||
let Some(discr) = discr.place() else { return };
|
||||
debug!(?discr, ?bb);
|
||||
|
||||
let discr_ty = discr.ty(self.body, self.tcx).ty;
|
||||
let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else {
|
||||
return Some(());
|
||||
};
|
||||
let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return };
|
||||
|
||||
let Some(discr) = self.map.find(discr.as_ref()) else { return Some(()) };
|
||||
let Some(discr) = self.map.find(discr.as_ref()) else { return };
|
||||
debug!(?discr);
|
||||
|
||||
let cost = CostChecker::new(self.tcx, self.typing_env, None, self.body);
|
||||
let mut state = State::new_reachable();
|
||||
|
||||
let conds = if let Some((value, then, else_)) = targets.as_static_if() {
|
||||
let value = ScalarInt::try_from_uint(value, discr_layout.size)?;
|
||||
let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return };
|
||||
self.arena.alloc_from_iter([
|
||||
Condition { value, polarity: Polarity::Eq, target: then },
|
||||
Condition { value, polarity: Polarity::Ne, target: else_ },
|
||||
|
|
@ -248,10 +242,10 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
mut state: State<ConditionSet<'a>>,
|
||||
mut cost: CostChecker<'_, 'tcx>,
|
||||
depth: usize,
|
||||
) -> Option<()> {
|
||||
) {
|
||||
// Do not thread through loop headers.
|
||||
if self.loop_headers.contains(bb) {
|
||||
return Some(());
|
||||
return;
|
||||
}
|
||||
|
||||
debug!(cost = ?cost.cost());
|
||||
|
|
@ -259,16 +253,16 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
self.body.basic_blocks[bb].statements.iter().enumerate().rev()
|
||||
{
|
||||
if self.is_empty(&state) {
|
||||
return Some(());
|
||||
return;
|
||||
}
|
||||
|
||||
cost.visit_statement(stmt, Location { block: bb, statement_index });
|
||||
if cost.cost() > MAX_COST {
|
||||
return Some(());
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to turn the `current_condition` on `lhs` into a condition on another place.
|
||||
self.process_statement(bb, stmt, &mut state)?;
|
||||
self.process_statement(bb, stmt, &mut state);
|
||||
|
||||
// When a statement mutates a place, assignments to that place that happen
|
||||
// above the mutation cannot fulfill a condition.
|
||||
|
|
@ -280,7 +274,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
if self.is_empty(&state) || depth >= MAX_BACKTRACK {
|
||||
return Some(());
|
||||
return;
|
||||
}
|
||||
|
||||
let last_non_rec = self.opportunities.len();
|
||||
|
|
@ -293,9 +287,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
match term.kind {
|
||||
TerminatorKind::SwitchInt { ref discr, ref targets } => {
|
||||
self.process_switch_int(discr, targets, bb, &mut state);
|
||||
self.find_opportunity(pred, state, cost, depth + 1)?;
|
||||
self.find_opportunity(pred, state, cost, depth + 1);
|
||||
}
|
||||
_ => self.recurse_through_terminator(pred, || state, &cost, depth)?,
|
||||
_ => self.recurse_through_terminator(pred, || state, &cost, depth),
|
||||
}
|
||||
} else if let &[ref predecessors @ .., last_pred] = &predecessors[..] {
|
||||
for &pred in predecessors {
|
||||
|
|
@ -320,13 +314,12 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
let first = &mut new_tos[0];
|
||||
*first = ThreadingOpportunity { chain: vec![bb], target: first.target };
|
||||
self.opportunities.truncate(last_non_rec + 1);
|
||||
return Some(());
|
||||
return;
|
||||
}
|
||||
|
||||
for op in self.opportunities[last_non_rec..].iter_mut() {
|
||||
op.chain.push(bb);
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// Extract the mutated place from a statement.
|
||||
|
|
@ -440,23 +433,23 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
lhs: PlaceIndex,
|
||||
rhs: &Operand<'tcx>,
|
||||
state: &mut State<ConditionSet<'a>>,
|
||||
) -> Option<()> {
|
||||
) {
|
||||
match rhs {
|
||||
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
|
||||
Operand::Constant(constant) => {
|
||||
let constant = self
|
||||
.ecx
|
||||
.eval_mir_constant(&constant.const_, constant.span, None)
|
||||
.discard_err()?;
|
||||
let Some(constant) =
|
||||
self.ecx.eval_mir_constant(&constant.const_, constant.span, None).discard_err()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
self.process_constant(bb, lhs, constant, state);
|
||||
}
|
||||
// Transfer the conditions on the copied rhs.
|
||||
Operand::Move(rhs) | Operand::Copy(rhs) => {
|
||||
let Some(rhs) = self.map.find(rhs.as_ref()) else { return Some(()) };
|
||||
let Some(rhs) = self.map.find(rhs.as_ref()) else { return };
|
||||
state.insert_place_idx(rhs, lhs, &self.map);
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
|
|
@ -466,18 +459,14 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
lhs_place: &Place<'tcx>,
|
||||
rhs: &Rvalue<'tcx>,
|
||||
state: &mut State<ConditionSet<'a>>,
|
||||
) -> Option<()> {
|
||||
let Some(lhs) = self.map.find(lhs_place.as_ref()) else {
|
||||
return Some(());
|
||||
};
|
||||
) {
|
||||
let Some(lhs) = self.map.find(lhs_place.as_ref()) else { return };
|
||||
match rhs {
|
||||
Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?,
|
||||
Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state),
|
||||
// Transfer the conditions on the copy rhs.
|
||||
Rvalue::CopyForDeref(rhs) => {
|
||||
self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)?
|
||||
}
|
||||
Rvalue::CopyForDeref(rhs) => self.process_operand(bb, lhs, &Operand::Copy(*rhs), state),
|
||||
Rvalue::Discriminant(rhs) => {
|
||||
let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return Some(()) };
|
||||
let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return };
|
||||
state.insert_place_idx(rhs, lhs, &self.map);
|
||||
}
|
||||
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
|
||||
|
|
@ -485,7 +474,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
let agg_ty = lhs_place.ty(self.body, self.tcx).ty;
|
||||
let lhs = match kind {
|
||||
// Do not support unions.
|
||||
AggregateKind::Adt(.., Some(_)) => return Some(()),
|
||||
AggregateKind::Adt(.., Some(_)) => return,
|
||||
AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => {
|
||||
if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant)
|
||||
&& let Some(discr_value) = self
|
||||
|
|
@ -498,23 +487,23 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
if let Some(idx) = self.map.apply(lhs, TrackElem::Variant(*variant_index)) {
|
||||
idx
|
||||
} else {
|
||||
return Some(());
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => lhs,
|
||||
};
|
||||
for (field_index, operand) in operands.iter_enumerated() {
|
||||
if let Some(field) = self.map.apply(lhs, TrackElem::Field(field_index)) {
|
||||
self.process_operand(bb, field, operand, state)?;
|
||||
self.process_operand(bb, field, operand, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Transfer the conditions on the copy rhs, after inverting the value of the condition.
|
||||
Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => {
|
||||
let layout = self.ecx.layout_of(place.ty(self.body, self.tcx).ty).unwrap();
|
||||
let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return Some(()) };
|
||||
let Some(place) = self.map.find(place.as_ref()) else { return Some(()) };
|
||||
let conds = conditions.map(self.arena, |mut cond| {
|
||||
let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return };
|
||||
let Some(place) = self.map.find(place.as_ref()) else { return };
|
||||
let Some(conds) = conditions.map(self.arena, |mut cond| {
|
||||
cond.value = self
|
||||
.ecx
|
||||
.unary_op(UnOp::Not, &ImmTy::from_scalar_int(cond.value, layout))
|
||||
|
|
@ -522,7 +511,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
.to_scalar_int()
|
||||
.discard_err()?;
|
||||
Some(cond)
|
||||
})?;
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
state.insert_value_idx(place, conds, &self.map);
|
||||
}
|
||||
// We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`.
|
||||
|
|
@ -532,34 +523,38 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value))
|
||||
| box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)),
|
||||
) => {
|
||||
let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return Some(()) };
|
||||
let Some(place) = self.map.find(place.as_ref()) else { return Some(()) };
|
||||
let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return };
|
||||
let Some(place) = self.map.find(place.as_ref()) else { return };
|
||||
let equals = match op {
|
||||
BinOp::Eq => ScalarInt::TRUE,
|
||||
BinOp::Ne => ScalarInt::FALSE,
|
||||
_ => return Some(()),
|
||||
_ => return,
|
||||
};
|
||||
if value.const_.ty().is_floating_point() {
|
||||
// Floating point equality does not follow bit-patterns.
|
||||
// -0.0 and NaN both have special rules for equality,
|
||||
// and therefore we cannot use integer comparisons for them.
|
||||
// Avoid handling them, though this could be extended in the future.
|
||||
return Some(());
|
||||
return;
|
||||
}
|
||||
let value = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)?;
|
||||
let conds = conditions.map(self.arena, |c| {
|
||||
let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(conds) = conditions.map(self.arena, |c| {
|
||||
Some(Condition {
|
||||
value,
|
||||
polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne },
|
||||
..c
|
||||
})
|
||||
})?;
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
state.insert_value_idx(place, conds, &self.map);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
|
|
@ -568,7 +563,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
bb: BasicBlock,
|
||||
stmt: &Statement<'tcx>,
|
||||
state: &mut State<ConditionSet<'a>>,
|
||||
) -> Option<()> {
|
||||
) {
|
||||
let register_opportunity = |c: Condition| {
|
||||
debug!(?bb, ?c.target, "register");
|
||||
self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target })
|
||||
|
|
@ -581,32 +576,30 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
// If we expect `discriminant(place) ?= A`,
|
||||
// we have an opportunity if `variant_index ?= A`.
|
||||
StatementKind::SetDiscriminant { box place, variant_index } => {
|
||||
let Some(discr_target) = self.map.find_discr(place.as_ref()) else {
|
||||
return Some(());
|
||||
};
|
||||
let Some(discr_target) = self.map.find_discr(place.as_ref()) else { return };
|
||||
let enum_ty = place.ty(self.body, self.tcx).ty;
|
||||
// `SetDiscriminant` guarantees that the discriminant is now `variant_index`.
|
||||
// Even if the discriminant write does nothing due to niches, it is UB to set the
|
||||
// discriminant when the data does not encode the desired discriminant.
|
||||
let discr =
|
||||
self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err()?;
|
||||
self.process_immediate(bb, discr_target, discr, state);
|
||||
let Some(discr) =
|
||||
self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
self.process_immediate(bb, discr_target, discr, state)
|
||||
}
|
||||
// If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`.
|
||||
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(
|
||||
Operand::Copy(place) | Operand::Move(place),
|
||||
)) => {
|
||||
let Some(conditions) = state.try_get(place.as_ref(), &self.map) else {
|
||||
return Some(());
|
||||
};
|
||||
conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity);
|
||||
let Some(conditions) = state.try_get(place.as_ref(), &self.map) else { return };
|
||||
conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity)
|
||||
}
|
||||
StatementKind::Assign(box (lhs_place, rhs)) => {
|
||||
self.process_assign(bb, lhs_place, rhs, state)?;
|
||||
self.process_assign(bb, lhs_place, rhs, state)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, state, cost))]
|
||||
|
|
@ -617,7 +610,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
state: impl FnOnce() -> State<ConditionSet<'a>>,
|
||||
cost: &CostChecker<'_, 'tcx>,
|
||||
depth: usize,
|
||||
) -> Option<()> {
|
||||
) {
|
||||
let term = self.body.basic_blocks[bb].terminator();
|
||||
let place_to_flood = match term.kind {
|
||||
// We come from a target, so those are not possible.
|
||||
|
|
@ -632,9 +625,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
| TerminatorKind::FalseUnwind { .. }
|
||||
| TerminatorKind::Yield { .. } => bug!("{term:?} invalid"),
|
||||
// Cannot reason about inline asm.
|
||||
TerminatorKind::InlineAsm { .. } => return Some(()),
|
||||
TerminatorKind::InlineAsm { .. } => return,
|
||||
// `SwitchInt` is handled specially.
|
||||
TerminatorKind::SwitchInt { .. } => return Some(()),
|
||||
TerminatorKind::SwitchInt { .. } => return,
|
||||
// We can recurse, no thing particular to do.
|
||||
TerminatorKind::Goto { .. } => None,
|
||||
// Flood the overwritten place, and progress through.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
|
|||
}
|
||||
|
||||
if should_cleanup {
|
||||
simplify_cfg(body);
|
||||
simplify_cfg(tcx, body);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ pub(super) struct RemovePlaceMention;
|
|||
|
||||
impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention {
|
||||
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
|
||||
!sess.opts.unstable_opts.mir_keep_place_mention
|
||||
!sess.opts.unstable_opts.mir_preserve_ub
|
||||
}
|
||||
|
||||
fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
|
|||
// if we applied optimizations, we potentially have some cfg to cleanup to
|
||||
// make it easier for further passes
|
||||
if should_simplify {
|
||||
simplify_cfg(body);
|
||||
simplify_cfg(tcx, body);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@
|
|||
//! Here the block (`{ return; }`) has the return type `char`, rather than `()`, but the MIR we
|
||||
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the
|
||||
//! return.
|
||||
//!
|
||||
//! **WARNING**: This is one of the few optimizations that runs on built and analysis MIR, and
|
||||
//! so its effects may affect the type-checking, borrow-checking, and other analysis of MIR.
|
||||
//! We must be extremely careful to only apply optimizations that preserve UB and all
|
||||
//! non-determinism, since changes here can affect which programs compile in an insta-stable way.
|
||||
//! The normal logic that a program with UB can be changed to do anything does not apply to
|
||||
//! pre-"runtime" MIR!
|
||||
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
|
||||
|
|
@ -66,8 +73,8 @@ impl SimplifyCfg {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn simplify_cfg(body: &mut Body<'_>) {
|
||||
CfgSimplifier::new(body).simplify();
|
||||
pub(super) fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
CfgSimplifier::new(tcx, body).simplify();
|
||||
remove_dead_blocks(body);
|
||||
|
||||
// FIXME: Should probably be moved into some kind of pass manager
|
||||
|
|
@ -79,9 +86,9 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
|
|||
self.name()
|
||||
}
|
||||
|
||||
fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
|
||||
simplify_cfg(body);
|
||||
simplify_cfg(tcx, body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
|
|
@ -90,12 +97,13 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
|
|||
}
|
||||
|
||||
struct CfgSimplifier<'a, 'tcx> {
|
||||
preserve_switch_reads: bool,
|
||||
basic_blocks: &'a mut IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
|
||||
pred_count: IndexVec<BasicBlock, u32>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
|
||||
fn new(body: &'a mut Body<'tcx>) -> Self {
|
||||
fn new(tcx: TyCtxt<'tcx>, body: &'a mut Body<'tcx>) -> Self {
|
||||
let mut pred_count = IndexVec::from_elem(0u32, &body.basic_blocks);
|
||||
|
||||
// we can't use mir.predecessors() here because that counts
|
||||
|
|
@ -110,9 +118,12 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Preserve `SwitchInt` reads on built and analysis MIR, or if `-Zmir-preserve-ub`.
|
||||
let preserve_switch_reads = matches!(body.phase, MirPhase::Built | MirPhase::Analysis(_))
|
||||
|| tcx.sess.opts.unstable_opts.mir_preserve_ub;
|
||||
let basic_blocks = body.basic_blocks_mut();
|
||||
|
||||
CfgSimplifier { basic_blocks, pred_count }
|
||||
CfgSimplifier { preserve_switch_reads, basic_blocks, pred_count }
|
||||
}
|
||||
|
||||
fn simplify(mut self) {
|
||||
|
|
@ -253,9 +264,15 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
|
|||
|
||||
// turn a branch with all successors identical to a goto
|
||||
fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
|
||||
match terminator.kind {
|
||||
TerminatorKind::SwitchInt { .. } => {}
|
||||
_ => return false,
|
||||
// Removing a `SwitchInt` terminator may remove reads that result in UB,
|
||||
// so we must not apply this optimization before borrowck or when
|
||||
// `-Zmir-preserve-ub` is set.
|
||||
if self.preserve_switch_reads {
|
||||
return false;
|
||||
}
|
||||
|
||||
let TerminatorKind::SwitchInt { .. } = terminator.kind else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let first_succ = {
|
||||
|
|
|
|||
|
|
@ -1884,13 +1884,15 @@ impl<'a> Parser<'a> {
|
|||
let mut expr = self.parse_expr_opt()?;
|
||||
if let Some(expr) = &mut expr {
|
||||
if label.is_some()
|
||||
&& matches!(
|
||||
expr.kind,
|
||||
&& match &expr.kind {
|
||||
ExprKind::While(_, _, None)
|
||||
| ExprKind::ForLoop { label: None, .. }
|
||||
| ExprKind::Loop(_, None, _)
|
||||
| ExprKind::Block(_, None)
|
||||
)
|
||||
| ExprKind::ForLoop { label: None, .. }
|
||||
| ExprKind::Loop(_, None, _) => true,
|
||||
ExprKind::Block(block, None) => {
|
||||
matches!(block.rules, BlockCheckMode::Default)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
{
|
||||
self.psess.buffer_lint(
|
||||
BREAK_WITH_LABEL_AND_LOOP,
|
||||
|
|
|
|||
|
|
@ -2322,12 +2322,12 @@ options! {
|
|||
mir_include_spans: MirIncludeSpans = (MirIncludeSpans::default(), parse_mir_include_spans, [UNTRACKED],
|
||||
"include extra comments in mir pretty printing, like line numbers and statement indices, \
|
||||
details about types, etc. (boolean for all passes, 'nll' to enable in NLL MIR only, default: 'nll')"),
|
||||
mir_keep_place_mention: bool = (false, parse_bool, [TRACKED],
|
||||
"keep place mention MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
|
||||
(default: no)"),
|
||||
#[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
|
||||
mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
|
||||
"MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
|
||||
mir_preserve_ub: bool = (false, parse_bool, [TRACKED],
|
||||
"keep place mention statements and reads in trivial SwitchInt terminators, which are interpreted \
|
||||
e.g., by miri; implies -Zmir-opt-level=0 (default: no)"),
|
||||
mir_strip_debuginfo: MirStripDebugInfo = (MirStripDebugInfo::None, parse_mir_strip_debuginfo, [TRACKED],
|
||||
"Whether to remove some of the MIR debug info from methods. Default: None"),
|
||||
move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
|
||||
|
|
|
|||
|
|
@ -2218,7 +2218,6 @@ symbols! {
|
|||
unsafe_extern_blocks,
|
||||
unsafe_fields,
|
||||
unsafe_no_drop_flag,
|
||||
unsafe_pin_internals,
|
||||
unsafe_pinned,
|
||||
unsafe_unpin,
|
||||
unsize,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@ pub(crate) fn target() -> Target {
|
|||
base.cpu = "pentium4".into();
|
||||
base.max_atomic_width = Some(64);
|
||||
base.supported_sanitizers = SanitizerSet::ADDRESS;
|
||||
// On Windows 7 32-bit, the alignment characteristic of the TLS Directory
|
||||
// don't appear to be respected by the PE Loader, leading to crashes. As
|
||||
// a result, let's disable has_thread_local to make sure TLS goes through
|
||||
// the emulation layer.
|
||||
// See https://github.com/rust-lang/rust/issues/138903
|
||||
base.has_thread_local = false;
|
||||
|
||||
base.add_pre_link_args(
|
||||
LinkerFlavor::Msvc(Lld::No),
|
||||
|
|
|
|||
|
|
@ -1116,7 +1116,7 @@ impl CStr {
|
|||
/// with the corresponding <code>&[str]</code> slice. Otherwise, it will
|
||||
/// replace any invalid UTF-8 sequences with
|
||||
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
|
||||
/// <code>[Cow]::[Owned]\(&[str])</code> with the result.
|
||||
/// <code>[Cow]::[Owned]\([String])</code> with the result.
|
||||
///
|
||||
/// [str]: prim@str "str"
|
||||
/// [Borrowed]: Cow::Borrowed
|
||||
|
|
|
|||
|
|
@ -23,6 +23,39 @@ impl<I> Enumerate<I> {
|
|||
pub(in crate::iter) fn new(iter: I) -> Enumerate<I> {
|
||||
Enumerate { iter, count: 0 }
|
||||
}
|
||||
|
||||
/// Retrieve the current position of the iterator.
|
||||
///
|
||||
/// If the iterator has not advanced, the position returned will be 0.
|
||||
///
|
||||
/// The position may also exceed the bounds of the iterator to allow for calculating
|
||||
/// the displacement of the iterator from following calls to [`Iterator::next`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(next_index)]
|
||||
///
|
||||
/// let arr = ['a', 'b'];
|
||||
///
|
||||
/// let mut iter = arr.iter().enumerate();
|
||||
///
|
||||
/// assert_eq!(iter.next_index(), 0);
|
||||
/// assert_eq!(iter.next(), Some((0, &'a')));
|
||||
///
|
||||
/// assert_eq!(iter.next_index(), 1);
|
||||
/// assert_eq!(iter.next_index(), 1);
|
||||
/// assert_eq!(iter.next(), Some((1, &'b')));
|
||||
///
|
||||
/// assert_eq!(iter.next_index(), 2);
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// assert_eq!(iter.next_index(), 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "next_index", issue = "130711")]
|
||||
pub fn next_index(&self) -> usize {
|
||||
self.count
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
|||
|
|
@ -1092,24 +1092,15 @@ pub use self::unsafe_pinned::UnsafePinned;
|
|||
#[rustc_pub_transparent]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Pin<Ptr> {
|
||||
// FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
|
||||
// - deter downstream users from accessing it (which would be unsound!),
|
||||
// - let the `pin!` macro access it (such a macro requires using struct
|
||||
// literal syntax in order to benefit from lifetime extension).
|
||||
//
|
||||
// However, if the `Deref` impl exposes a field with the same name as this
|
||||
// field, then the two will collide, resulting in a confusing error when the
|
||||
// user attempts to access the field through a `Pin<Ptr>`. Therefore, the
|
||||
// name `__pointer` is designed to be unlikely to collide with any other
|
||||
// field. Long-term, macro hygiene is expected to offer a more robust
|
||||
// alternative, alongside `unsafe` fields.
|
||||
#[unstable(feature = "unsafe_pin_internals", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
pub __pointer: Ptr,
|
||||
/// Only public for bootstrap.
|
||||
#[cfg(bootstrap)]
|
||||
pub pointer: Ptr,
|
||||
#[cfg(not(bootstrap))]
|
||||
pointer: Ptr,
|
||||
}
|
||||
|
||||
// The following implementations aren't derived in order to avoid soundness
|
||||
// issues. `&self.__pointer` should not be accessible to untrusted trait
|
||||
// issues. `&self.pointer` should not be accessible to untrusted trait
|
||||
// implementations.
|
||||
//
|
||||
// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73> for more details.
|
||||
|
|
@ -1223,7 +1214,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
|
|||
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
|
||||
#[stable(feature = "pin_into_inner", since = "1.39.0")]
|
||||
pub const fn into_inner(pin: Pin<Ptr>) -> Ptr {
|
||||
pin.__pointer
|
||||
pin.pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1360,7 +1351,7 @@ impl<Ptr: Deref> Pin<Ptr> {
|
|||
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> {
|
||||
Pin { __pointer: pointer }
|
||||
Pin { pointer }
|
||||
}
|
||||
|
||||
/// Gets a shared reference to the pinned value this [`Pin`] points to.
|
||||
|
|
@ -1374,7 +1365,7 @@ impl<Ptr: Deref> Pin<Ptr> {
|
|||
#[inline(always)]
|
||||
pub fn as_ref(&self) -> Pin<&Ptr::Target> {
|
||||
// SAFETY: see documentation on this function
|
||||
unsafe { Pin::new_unchecked(&*self.__pointer) }
|
||||
unsafe { Pin::new_unchecked(&*self.pointer) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1418,7 +1409,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
|
|||
#[inline(always)]
|
||||
pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
|
||||
// SAFETY: see documentation on this function
|
||||
unsafe { Pin::new_unchecked(&mut *self.__pointer) }
|
||||
unsafe { Pin::new_unchecked(&mut *self.pointer) }
|
||||
}
|
||||
|
||||
/// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer.
|
||||
|
|
@ -1485,7 +1476,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
|
|||
where
|
||||
Ptr::Target: Sized,
|
||||
{
|
||||
*(self.__pointer) = value;
|
||||
*(self.pointer) = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1513,7 +1504,7 @@ impl<Ptr: Deref> Pin<Ptr> {
|
|||
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
|
||||
#[stable(feature = "pin_into_inner", since = "1.39.0")]
|
||||
pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr {
|
||||
pin.__pointer
|
||||
pin.pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1539,7 +1530,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
|
|||
U: ?Sized,
|
||||
F: FnOnce(&T) -> &U,
|
||||
{
|
||||
let pointer = &*self.__pointer;
|
||||
let pointer = &*self.pointer;
|
||||
let new_pointer = func(pointer);
|
||||
|
||||
// SAFETY: the safety contract for `new_unchecked` must be
|
||||
|
|
@ -1569,7 +1560,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
|
|||
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
pub const fn get_ref(self) -> &'a T {
|
||||
self.__pointer
|
||||
self.pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1580,7 +1571,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
pub const fn into_ref(self) -> Pin<&'a T> {
|
||||
Pin { __pointer: self.__pointer }
|
||||
Pin { pointer: self.pointer }
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the data inside of this `Pin`.
|
||||
|
|
@ -1600,7 +1591,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||
where
|
||||
T: Unpin,
|
||||
{
|
||||
self.__pointer
|
||||
self.pointer
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the data inside of this `Pin`.
|
||||
|
|
@ -1618,7 +1609,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
#[rustc_const_stable(feature = "const_pin", since = "1.84.0")]
|
||||
pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
|
||||
self.__pointer
|
||||
self.pointer
|
||||
}
|
||||
|
||||
/// Constructs a new pin by mapping the interior value.
|
||||
|
|
@ -1705,21 +1696,21 @@ impl<Ptr: LegacyReceiver> LegacyReceiver for Pin<Ptr> {}
|
|||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<Ptr: fmt::Debug> fmt::Debug for Pin<Ptr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.__pointer, f)
|
||||
fmt::Debug::fmt(&self.pointer, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<Ptr: fmt::Display> fmt::Display for Pin<Ptr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.__pointer, f)
|
||||
fmt::Display::fmt(&self.pointer, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<Ptr: fmt::Pointer> fmt::Pointer for Pin<Ptr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.__pointer, f)
|
||||
fmt::Pointer::fmt(&self.pointer, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1945,80 +1936,22 @@ unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
|
|||
/// constructor.
|
||||
///
|
||||
/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
|
||||
#[cfg(not(bootstrap))]
|
||||
#[stable(feature = "pin_macro", since = "1.68.0")]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
#[allow_internal_unstable(unsafe_pin_internals)]
|
||||
#[rustc_macro_edition_2021]
|
||||
#[allow_internal_unstable(super_let)]
|
||||
pub macro pin($value:expr $(,)?) {
|
||||
// This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's
|
||||
// review such a hypothetical macro (that any user-code could define):
|
||||
//
|
||||
// ```rust
|
||||
// macro_rules! pin {( $value:expr ) => (
|
||||
// match &mut { $value } { at_value => unsafe { // Do not wrap `$value` in an `unsafe` block.
|
||||
// $crate::pin::Pin::<&mut _>::new_unchecked(at_value)
|
||||
// }}
|
||||
// )}
|
||||
// ```
|
||||
//
|
||||
// Safety:
|
||||
// - `type P = &mut _`. There are thus no pathological `Deref{,Mut}` impls
|
||||
// that would break `Pin`'s invariants.
|
||||
// - `{ $value }` is braced, making it a _block expression_, thus **moving**
|
||||
// the given `$value`, and making it _become an **anonymous** temporary_.
|
||||
// By virtue of being anonymous, it can no longer be accessed, thus
|
||||
// preventing any attempts to `mem::replace` it or `mem::forget` it, _etc._
|
||||
//
|
||||
// This gives us a `pin!` definition that is sound, and which works, but only
|
||||
// in certain scenarios:
|
||||
// - If the `pin!(value)` expression is _directly_ fed to a function call:
|
||||
// `let poll = pin!(fut).poll(cx);`
|
||||
// - If the `pin!(value)` expression is part of a scrutinee:
|
||||
// ```rust
|
||||
// match pin!(fut) { pinned_fut => {
|
||||
// pinned_fut.as_mut().poll(...);
|
||||
// pinned_fut.as_mut().poll(...);
|
||||
// }} // <- `fut` is dropped here.
|
||||
// ```
|
||||
// Alas, it doesn't work for the more straight-forward use-case: `let` bindings.
|
||||
// ```rust
|
||||
// let pinned_fut = pin!(fut); // <- temporary value is freed at the end of this statement
|
||||
// pinned_fut.poll(...) // error[E0716]: temporary value dropped while borrowed
|
||||
// // note: consider using a `let` binding to create a longer lived value
|
||||
// ```
|
||||
// - Issues such as this one are the ones motivating https://github.com/rust-lang/rfcs/pull/66
|
||||
//
|
||||
// This makes such a macro incredibly unergonomic in practice, and the reason most macros
|
||||
// out there had to take the path of being a statement/binding macro (_e.g._, `pin!(future);`)
|
||||
// instead of featuring the more intuitive ergonomics of an expression macro.
|
||||
//
|
||||
// Luckily, there is a way to avoid the problem. Indeed, the problem stems from the fact that a
|
||||
// temporary is dropped at the end of its enclosing statement when it is part of the parameters
|
||||
// given to function call, which has precisely been the case with our `Pin::new_unchecked()`!
|
||||
// For instance,
|
||||
// ```rust
|
||||
// let p = Pin::new_unchecked(&mut <temporary>);
|
||||
// ```
|
||||
// becomes:
|
||||
// ```rust
|
||||
// let p = { let mut anon = <temporary>; &mut anon };
|
||||
// ```
|
||||
//
|
||||
// However, when using a literal braced struct to construct the value, references to temporaries
|
||||
// can then be taken. This makes Rust change the lifespan of such temporaries so that they are,
|
||||
// instead, dropped _at the end of the enscoping block_.
|
||||
// For instance,
|
||||
// ```rust
|
||||
// let p = Pin { __pointer: &mut <temporary> };
|
||||
// ```
|
||||
// becomes:
|
||||
// ```rust
|
||||
// let mut anon = <temporary>;
|
||||
// let p = Pin { __pointer: &mut anon };
|
||||
// ```
|
||||
// which is *exactly* what we want.
|
||||
//
|
||||
// See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension
|
||||
// for more info.
|
||||
$crate::pin::Pin::<&mut _> { __pointer: &mut { $value } }
|
||||
{
|
||||
super let mut pinned = $value;
|
||||
// SAFETY: The value is pinned: it is the local above which cannot be named outside this macro.
|
||||
unsafe { $crate::pin::Pin::new_unchecked(&mut pinned) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Only for bootstrap.
|
||||
#[cfg(bootstrap)]
|
||||
#[stable(feature = "pin_macro", since = "1.68.0")]
|
||||
#[rustc_macro_transparency = "semitransparent"]
|
||||
pub macro pin($value:expr $(,)?) {
|
||||
$crate::pin::Pin::<&mut _> { pointer: &mut { $value } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1739,3 +1739,11 @@ impl<T: ?Sized> PartialOrd for *const T {
|
|||
*self >= *other
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "raw_ptr_default", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: ?Sized + Thin> Default for *const T {
|
||||
/// Returns the default value of [`null()`][crate::ptr::null].
|
||||
fn default() -> Self {
|
||||
crate::ptr::null()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2156,3 +2156,11 @@ impl<T: ?Sized> PartialOrd for *mut T {
|
|||
*self >= *other
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "raw_ptr_default", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: ?Sized + Thin> Default for *mut T {
|
||||
/// Returns the default value of [`null_mut()`][crate::ptr::null_mut].
|
||||
fn default() -> Self {
|
||||
crate::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,3 +120,13 @@ fn test_double_ended_enumerate() {
|
|||
assert_eq!(it.next_back(), Some((2, 3)));
|
||||
assert_eq!(it.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_iterator_enumerate_next_index() {
|
||||
let mut it = empty::<i32>().enumerate();
|
||||
assert_eq!(it.next_index(), 0);
|
||||
assert_eq!(it.next_index(), 0);
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next_index(), 0);
|
||||
assert_eq!(it.next_index(), 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
#![feature(maybe_uninit_write_slice)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
#![feature(next_index)]
|
||||
#![feature(numfmt)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pointer_is_aligned_to)]
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ fn rust_2024_expr() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(bootstrap))]
|
||||
fn temp_lifetime() {
|
||||
// Check that temporary lifetimes work as in Rust 2021.
|
||||
// Regression test for https://github.com/rust-lang/rust/issues/138596
|
||||
|
|
|
|||
|
|
@ -1020,3 +1020,20 @@ fn test_ptr_swap_nonoverlapping_is_untyped() {
|
|||
ptr_swap_nonoverlapping_is_untyped_inner();
|
||||
const { ptr_swap_nonoverlapping_is_untyped_inner() };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ptr_default() {
|
||||
#[derive(Default)]
|
||||
struct PtrDefaultTest {
|
||||
ptr: *const u64,
|
||||
}
|
||||
let default = PtrDefaultTest::default();
|
||||
assert!(default.ptr.is_null());
|
||||
|
||||
#[derive(Default)]
|
||||
struct PtrMutDefaultTest {
|
||||
ptr: *mut u64,
|
||||
}
|
||||
let default = PtrMutDefaultTest::default();
|
||||
assert!(default.ptr.is_null());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ use libc::c_char;
|
|||
all(target_os = "linux", not(target_env = "musl")),
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "illumos",
|
||||
))]
|
||||
use libc::dirfd;
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
#[cfg(any(target_os = "fuchsia", target_os = "illumos"))]
|
||||
use libc::fstatat as fstatat64;
|
||||
#[cfg(any(all(target_os = "linux", not(target_env = "musl")), target_os = "hurd"))]
|
||||
use libc::fstatat64;
|
||||
|
|
@ -892,7 +893,8 @@ impl DirEntry {
|
|||
all(target_os = "linux", not(target_env = "musl")),
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd"
|
||||
target_os = "hurd",
|
||||
target_os = "illumos",
|
||||
),
|
||||
not(miri) // no dirfd on Miri
|
||||
))]
|
||||
|
|
@ -922,6 +924,7 @@ impl DirEntry {
|
|||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd",
|
||||
target_os = "illumos",
|
||||
)),
|
||||
miri
|
||||
))]
|
||||
|
|
|
|||
|
|
@ -1194,8 +1194,7 @@ pub fn rustc_cargo(
|
|||
let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
|
||||
cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
|
||||
|
||||
if !builder.config.dry_run() {
|
||||
let llvm_config = builder.llvm_config(builder.config.build).unwrap();
|
||||
if let Some(llvm_config) = builder.llvm_config(builder.config.build) {
|
||||
let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
|
||||
cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -584,6 +584,7 @@ Select which editor you would like to set up [default: None]: ";
|
|||
"51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
|
||||
"d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45",
|
||||
"b5dd299b93dca3ceeb9b335f929293cb3d4bf4977866fbe7ceeac2a8a9f99088",
|
||||
"631c837b0e98ae35fd48b0e5f743b1ca60adadf2d0a2b23566ba25df372cf1a9",
|
||||
],
|
||||
EditorKind::Helix => &[
|
||||
"2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233",
|
||||
|
|
@ -602,10 +603,12 @@ Select which editor you would like to set up [default: None]: ";
|
|||
"4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
|
||||
"c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
|
||||
"e53e9129ca5ee5dcbd6ec8b68c2d87376474eb154992deba3c6d9ab1703e0717",
|
||||
"f954316090936c7e590c253ca9d524008375882fa13c5b41d7e2547a896ff893",
|
||||
],
|
||||
EditorKind::Zed => &[
|
||||
"bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c",
|
||||
"a5380cf5dd9328731aecc5dfb240d16dac46ed272126b9728006151ef42f5909",
|
||||
"2e96bf0d443852b12f016c8fc9840ab3d0a2b4fe0b0fb3a157e8d74d5e7e0e26",
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,9 +69,9 @@
|
|||
</Type>
|
||||
|
||||
<Type Name="core::pin::Pin<*>">
|
||||
<DisplayString>Pin({(void*)__pointer}: {__pointer})</DisplayString>
|
||||
<DisplayString>Pin({(void*)pointer}: {pointer})</DisplayString>
|
||||
<Expand>
|
||||
<ExpandedItem>__pointer</ExpandedItem>
|
||||
<ExpandedItem>pointer</ExpandedItem>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@
|
|||
"check"
|
||||
"--json-output"])
|
||||
:linkedProjects ["Cargo.toml"
|
||||
"src/bootstrap/Cargo.toml"
|
||||
"src/tools/rust-analyzer/Cargo.toml"
|
||||
"compiler/rustc_codegen_cranelift/Cargo.toml"
|
||||
"compiler/rustc_codegen_gcc/Cargo.toml"]
|
||||
"compiler/rustc_codegen_gcc/Cargo.toml"
|
||||
"library/Cargo.toml"
|
||||
"src/bootstrap/Cargo.toml"
|
||||
"src/tools/rust-analyzer/Cargo.toml"]
|
||||
:rustfmt ( :overrideCommand ["build/host/rustfmt/bin/rustfmt"
|
||||
"--edition=2021"])
|
||||
:procMacro ( :server "build/host/stage0/libexec/rust-analyzer-proc-macro-srv"
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
],
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"Cargo.toml",
|
||||
"compiler/rustc_codegen_cranelift/Cargo.toml",
|
||||
"compiler/rustc_codegen_gcc/Cargo.toml",
|
||||
"library/Cargo.toml",
|
||||
"src/bootstrap/Cargo.toml",
|
||||
"src/tools/rust-analyzer/Cargo.toml",
|
||||
"compiler/rustc_codegen_cranelift/Cargo.toml",
|
||||
"compiler/rustc_codegen_gcc/Cargo.toml"
|
||||
"src/tools/rust-analyzer/Cargo.toml"
|
||||
],
|
||||
"rust-analyzer.rustfmt.overrideCommand": [
|
||||
"${workspaceFolder}/build/host/rustfmt/bin/rustfmt",
|
||||
|
|
@ -36,5 +36,10 @@
|
|||
},
|
||||
"rust-analyzer.server.extraEnv": {
|
||||
"RUSTUP_TOOLCHAIN": "nightly"
|
||||
},
|
||||
"files.associations": {
|
||||
"*.fixed": "rust",
|
||||
"*.pp": "rust",
|
||||
"*.mir": "rust"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,15 +21,15 @@
|
|||
},
|
||||
"linkedProjects": [
|
||||
"Cargo.toml",
|
||||
"compiler/rustc_codegen_cranelift/Cargo.toml",
|
||||
"compiler/rustc_codegen_gcc/Cargo.toml",
|
||||
"library/Cargo.toml",
|
||||
"src/bootstrap/Cargo.toml",
|
||||
"src/tools/rust-analyzer/Cargo.toml",
|
||||
"compiler/rustc_codegen_cranelift/Cargo.toml",
|
||||
"compiler/rustc_codegen_gcc/Cargo.toml"
|
||||
"src/tools/rust-analyzer/Cargo.toml"
|
||||
],
|
||||
"procMacro": {
|
||||
"enable": true,
|
||||
"server": "${workspaceFolder}/build/host/stage0/libexec/rust-analyzer-proc-macro-srv"
|
||||
"enable": true,
|
||||
"server": "${workspaceFolder}/build/host/stage0/libexec/rust-analyzer-proc-macro-srv"
|
||||
},
|
||||
"rustc": {
|
||||
"source": "./Cargo.toml"
|
||||
|
|
@ -47,5 +47,8 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"file_types": {
|
||||
"Rust": ["fixed", "pp", "mir"]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2773,10 +2773,35 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||
) -> Vec<Item> {
|
||||
use hir::ItemKind;
|
||||
|
||||
let def_id = item.owner_id.to_def_id();
|
||||
let mut name = if renamed.is_some() { renamed } else { cx.tcx.hir_opt_name(item.hir_id()) };
|
||||
fn get_name(
|
||||
cx: &DocContext<'_>,
|
||||
item: &hir::Item<'_>,
|
||||
renamed: Option<Symbol>,
|
||||
) -> Option<Symbol> {
|
||||
renamed.or_else(|| cx.tcx.hir_opt_name(item.hir_id()))
|
||||
}
|
||||
|
||||
let def_id = item.owner_id.to_def_id();
|
||||
cx.with_param_env(def_id, |cx| {
|
||||
// These kinds of item either don't need a `name` or accept a `None` one so we handle them
|
||||
// before.
|
||||
match item.kind {
|
||||
ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
|
||||
ItemKind::Use(path, kind) => {
|
||||
return clean_use_statement(
|
||||
item,
|
||||
get_name(cx, item, renamed),
|
||||
path,
|
||||
kind,
|
||||
cx,
|
||||
&mut FxHashSet::default(),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut name = get_name(cx, item, renamed).unwrap();
|
||||
|
||||
let kind = match item.kind {
|
||||
ItemKind::Static(_, ty, mutability, body_id) => StaticItem(Static {
|
||||
type_: Box::new(clean_ty(ty, cx)),
|
||||
|
|
@ -2815,7 +2840,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||
item_type: Some(type_),
|
||||
})),
|
||||
item.owner_id.def_id.to_def_id(),
|
||||
name.unwrap(),
|
||||
name,
|
||||
import_id,
|
||||
renamed,
|
||||
));
|
||||
|
|
@ -2838,17 +2863,14 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||
generics: clean_generics(generics, cx),
|
||||
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
|
||||
}),
|
||||
ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
|
||||
ItemKind::Macro(_, macro_def, MacroKind::Bang) => MacroItem(Macro {
|
||||
source: display_macro_source(cx, name.unwrap(), macro_def),
|
||||
source: display_macro_source(cx, name, macro_def),
|
||||
macro_rules: macro_def.macro_rules,
|
||||
}),
|
||||
ItemKind::Macro(_, _, macro_kind) => {
|
||||
clean_proc_macro(item, name.as_mut().unwrap(), macro_kind, cx)
|
||||
}
|
||||
ItemKind::Macro(_, _, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
|
||||
// proc macros can have a name set by attributes
|
||||
ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
|
||||
clean_fn_or_proc_macro(item, sig, generics, body_id, name.as_mut().unwrap(), cx)
|
||||
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
|
||||
}
|
||||
ItemKind::Trait(_, _, _, generics, bounds, item_ids) => {
|
||||
let items = item_ids
|
||||
|
|
@ -2864,10 +2886,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||
}))
|
||||
}
|
||||
ItemKind::ExternCrate(orig_name, _) => {
|
||||
return clean_extern_crate(item, name.unwrap(), orig_name, cx);
|
||||
}
|
||||
ItemKind::Use(path, kind) => {
|
||||
return clean_use_statement(item, name, path, kind, cx, &mut FxHashSet::default());
|
||||
return clean_extern_crate(item, name, orig_name, cx);
|
||||
}
|
||||
_ => span_bug!(item.span, "not yet converted"),
|
||||
};
|
||||
|
|
@ -2876,7 +2895,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||
cx,
|
||||
kind,
|
||||
item.owner_id.def_id.to_def_id(),
|
||||
name.unwrap(),
|
||||
name,
|
||||
import_id,
|
||||
renamed,
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ impl JsonRenderer<'_> {
|
|||
let lo = span.lo(self.sess());
|
||||
Some(Span {
|
||||
filename: local_path,
|
||||
begin: (lo.line, lo.col.to_usize()),
|
||||
end: (hi.line, hi.col.to_usize()),
|
||||
begin: (lo.line, lo.col.to_usize() + 1),
|
||||
end: (hi.line, hi.col.to_usize() + 1),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
|
|||
/// This integer is incremented with every breaking change to the API,
|
||||
/// and is returned along with the JSON blob as [`Crate::format_version`].
|
||||
/// Consuming code should assert that this value matches the format version(s) that it supports.
|
||||
pub const FORMAT_VERSION: u32 = 44;
|
||||
pub const FORMAT_VERSION: u32 = 45;
|
||||
|
||||
/// The root of the emitted JSON blob.
|
||||
///
|
||||
|
|
@ -205,9 +205,9 @@ pub struct Item {
|
|||
pub struct Span {
|
||||
/// The path to the source file for this span relative to the path `rustdoc` was invoked with.
|
||||
pub filename: PathBuf,
|
||||
/// Zero indexed Line and Column of the first character of the `Span`
|
||||
/// One indexed Line and Column of the first character of the `Span`.
|
||||
pub begin: (usize, usize),
|
||||
/// Zero indexed Line and Column of the last character of the `Span`
|
||||
/// One indexed Line and Column of the last character of the `Span`.
|
||||
pub end: (usize, usize),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2ef78586529b5f68cc42bcbe9b10b4afe56a942a
|
||||
90fd16eb5be9255006c95e8af12a0d43854dc1a9
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ pub const MIRI_DEFAULT_ARGS: &[&str] = &[
|
|||
"-Zalways-encode-mir",
|
||||
"-Zextra-const-ub-checks",
|
||||
"-Zmir-emit-retag",
|
||||
"-Zmir-keep-place-mention",
|
||||
"-Zmir-preserve-ub",
|
||||
"-Zmir-opt-level=0",
|
||||
"-Zmir-enable-passes=-CheckAlignment,-CheckNull",
|
||||
// Deduplicating diagnostics means we miss events when tracking what happens during an
|
||||
|
|
|
|||
14
src/tools/miri/tests/fail/read_from_trivial_switch.rs
Normal file
14
src/tools/miri/tests/fail/read_from_trivial_switch.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Ensure that we don't optimize out `SwitchInt` reads even if that terminator
|
||||
// branches to the same basic block on every target, since the operand may have
|
||||
// side-effects that affect analysis of the MIR.
|
||||
//
|
||||
// See <https://github.com/rust-lang/miri/issues/4237>.
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
fn main() {
|
||||
let uninit: MaybeUninit<i32> = MaybeUninit::uninit();
|
||||
let bad_ref: &i32 = unsafe { uninit.assume_init_ref() };
|
||||
let &(0 | _) = bad_ref;
|
||||
//~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
|
||||
}
|
||||
15
src/tools/miri/tests/fail/read_from_trivial_switch.stderr
Normal file
15
src/tools/miri/tests/fail/read_from_trivial_switch.stderr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
|
||||
--> tests/fail/read_from_trivial_switch.rs:LL:CC
|
||||
|
|
||||
LL | let &(0 | _) = bad_ref;
|
||||
| ^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at tests/fail/read_from_trivial_switch.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -1,32 +1,24 @@
|
|||
{
|
||||
description = "rustc dev shell";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils, ... }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
x = import ./x { inherit pkgs; };
|
||||
in
|
||||
{
|
||||
devShells.default = with pkgs; mkShell {
|
||||
name = "rustc-dev-shell";
|
||||
nativeBuildInputs = with pkgs; [
|
||||
binutils cmake ninja pkg-config python3 git curl cacert patchelf nix
|
||||
];
|
||||
buildInputs = with pkgs; [
|
||||
openssl glibc.out glibc.static x
|
||||
];
|
||||
# Avoid creating text files for ICEs.
|
||||
RUSTC_ICE = "0";
|
||||
# Provide `libstdc++.so.6` for the self-contained lld.
|
||||
# Provide `libz.so.1`.
|
||||
LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [stdenv.cc.cc.lib zlib]}";
|
||||
};
|
||||
}
|
||||
);
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
}:
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
forEachSystem = lib.genAttrs lib.systems.flakeExposed;
|
||||
in
|
||||
{
|
||||
devShells = forEachSystem (system: {
|
||||
default = nixpkgs.legacyPackages.${system}.callPackage ./shell.nix { };
|
||||
});
|
||||
|
||||
packages = forEachSystem (system: {
|
||||
default = nixpkgs.legacyPackages.${system}.callPackage ./x { };
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,26 @@
|
|||
{ pkgs ? import <nixpkgs> {} }:
|
||||
let
|
||||
x = import ./x { inherit pkgs; };
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
}:
|
||||
let
|
||||
inherit (pkgs.lib) lists attrsets;
|
||||
|
||||
x = pkgs.callPackage ./x { };
|
||||
inherit (x.passthru) cacert env;
|
||||
in
|
||||
pkgs.mkShell {
|
||||
name = "rustc";
|
||||
nativeBuildInputs = with pkgs; [
|
||||
binutils cmake ninja pkg-config python3 git curl cacert patchelf nix
|
||||
];
|
||||
buildInputs = with pkgs; [
|
||||
openssl glibc.out glibc.static x
|
||||
];
|
||||
# Avoid creating text files for ICEs.
|
||||
RUSTC_ICE = "0";
|
||||
# Provide `libstdc++.so.6` for the self-contained lld.
|
||||
# Provide `libz.so.1`
|
||||
LD_LIBRARY_PATH = "${with pkgs; lib.makeLibraryPath [stdenv.cc.cc.lib zlib]}";
|
||||
name = "rustc-shell";
|
||||
|
||||
inputsFrom = [ x ];
|
||||
packages = [
|
||||
pkgs.git
|
||||
pkgs.nix
|
||||
x
|
||||
# Get the runtime deps of the x wrapper
|
||||
] ++ lists.flatten (attrsets.attrValues env);
|
||||
|
||||
env = {
|
||||
# Avoid creating text files for ICEs.
|
||||
RUSTC_ICE = 0;
|
||||
SSL_CERT_FILE = cacert;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,83 @@
|
|||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
pkgs,
|
||||
lib,
|
||||
stdenv,
|
||||
rustc,
|
||||
python3,
|
||||
makeBinaryWrapper,
|
||||
# Bootstrap
|
||||
curl,
|
||||
pkg-config,
|
||||
libiconv,
|
||||
openssl,
|
||||
patchelf,
|
||||
cacert,
|
||||
zlib,
|
||||
# LLVM Deps
|
||||
ninja,
|
||||
cmake,
|
||||
glibc,
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "x";
|
||||
stdenv.mkDerivation (self: {
|
||||
strictDeps = true;
|
||||
name = "x-none";
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
"unwrapped"
|
||||
];
|
||||
|
||||
src = ./x.rs;
|
||||
dontUnpack = true;
|
||||
|
||||
nativeBuildInputs = with pkgs; [ rustc ];
|
||||
nativeBuildInputs = [
|
||||
rustc
|
||||
makeBinaryWrapper
|
||||
];
|
||||
|
||||
env.PYTHON = python3.interpreter;
|
||||
buildPhase = ''
|
||||
PYTHON=${pkgs.lib.getExe pkgs.python3} rustc -Copt-level=3 --crate-name x $src --out-dir $out/bin
|
||||
rustc -Copt-level=3 --crate-name x $src --out-dir $unwrapped/bin
|
||||
'';
|
||||
|
||||
meta = with pkgs.lib; {
|
||||
installPhase =
|
||||
let
|
||||
inherit (self.passthru) cacert env;
|
||||
in
|
||||
''
|
||||
makeWrapper $unwrapped/bin/x $out/bin/x \
|
||||
--set-default SSL_CERT_FILE ${cacert} \
|
||||
--prefix CPATH ";" "${lib.makeSearchPath "include" env.cpath}" \
|
||||
--prefix PATH : ${lib.makeBinPath env.path} \
|
||||
--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath env.ldLib}
|
||||
'';
|
||||
|
||||
# For accessing them in the devshell
|
||||
passthru = {
|
||||
env = {
|
||||
cpath = [ libiconv ];
|
||||
path = [
|
||||
python3
|
||||
patchelf
|
||||
curl
|
||||
pkg-config
|
||||
cmake
|
||||
ninja
|
||||
stdenv.cc
|
||||
];
|
||||
ldLib = [
|
||||
openssl
|
||||
zlib
|
||||
stdenv.cc.cc.lib
|
||||
];
|
||||
};
|
||||
cacert = "${cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Helper for rust-lang/rust x.py";
|
||||
homepage = "https://github.com/rust-lang/rust/blob/master/src/tools/x";
|
||||
license = licenses.mit;
|
||||
license = lib.licenses.mit;
|
||||
mainProgram = "x";
|
||||
};
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -24,43 +24,47 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
|
|||
|
||||
bb1: {
|
||||
_0 = const 0_u32;
|
||||
goto -> bb10;
|
||||
goto -> bb11;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_2 = discriminant((_1.2: std::option::Option<i32>));
|
||||
switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb1];
|
||||
switchInt(copy (_1.1: bool)) -> [0: bb3, otherwise: bb3];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
switchInt(copy (((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb4, 8: bb4, otherwise: bb1];
|
||||
_2 = discriminant((_1.2: std::option::Option<i32>));
|
||||
switchInt(move _2) -> [0: bb5, 1: bb4, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_5 = Le(const 6_u32, copy (_1.3: u32));
|
||||
switchInt(move _5) -> [0: bb5, otherwise: bb7];
|
||||
switchInt(copy (((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb5, 8: bb5, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_3 = Le(const 13_u32, copy (_1.3: u32));
|
||||
switchInt(move _3) -> [0: bb1, otherwise: bb6];
|
||||
_5 = Le(const 6_u32, copy (_1.3: u32));
|
||||
switchInt(move _5) -> [0: bb6, otherwise: bb8];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_4 = Le(copy (_1.3: u32), const 16_u32);
|
||||
switchInt(move _4) -> [0: bb1, otherwise: bb8];
|
||||
_3 = Le(const 13_u32, copy (_1.3: u32));
|
||||
switchInt(move _3) -> [0: bb1, otherwise: bb7];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
_6 = Le(copy (_1.3: u32), const 9_u32);
|
||||
switchInt(move _6) -> [0: bb5, otherwise: bb8];
|
||||
_4 = Le(copy (_1.3: u32), const 16_u32);
|
||||
switchInt(move _4) -> [0: bb1, otherwise: bb9];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
falseEdge -> [real: bb9, imaginary: bb1];
|
||||
_6 = Le(copy (_1.3: u32), const 9_u32);
|
||||
switchInt(move _6) -> [0: bb6, otherwise: bb9];
|
||||
}
|
||||
|
||||
bb9: {
|
||||
falseEdge -> [real: bb10, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
StorageLive(_7);
|
||||
_7 = copy (_1.0: u32);
|
||||
StorageLive(_8);
|
||||
|
|
@ -74,10 +78,10 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
|
|||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageDead(_7);
|
||||
goto -> bb10;
|
||||
goto -> bb11;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
bb11: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// and don't remove it as a dead store.
|
||||
//
|
||||
//@ test-mir-pass: DeadStoreElimination-initial
|
||||
//@ compile-flags: -Zmir-keep-place-mention
|
||||
//@ compile-flags: -Zmir-preserve-ub
|
||||
|
||||
// EMIT_MIR place_mention.main.DeadStoreElimination-initial.diff
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
- _4 = g() -> [return: bb1, unwind unreachable];
|
||||
+ _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)};
|
||||
+ _3 = &mut _4;
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: copy _3 };
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { pointer: copy _3 };
|
||||
+ StorageDead(_3);
|
||||
+ StorageLive(_5);
|
||||
+ _5 = const false;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
- _4 = g() -> [return: bb1, unwind continue];
|
||||
+ _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)};
|
||||
+ _3 = &mut _4;
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: copy _3 };
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { pointer: copy _3 };
|
||||
+ StorageDead(_3);
|
||||
+ StorageLive(_5);
|
||||
+ _5 = const false;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@
|
|||
- }
|
||||
-
|
||||
- bb2: {
|
||||
+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: copy _5 };
|
||||
+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { pointer: copy _5 };
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
|
|
@ -218,7 +218,7 @@
|
|||
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
|
||||
+ _20 = &mut (*_21);
|
||||
+ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 };
|
||||
+ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
|
||||
+ StorageDead(_20);
|
||||
+ StorageLive(_22);
|
||||
+ StorageLive(_23);
|
||||
|
|
@ -239,7 +239,7 @@
|
|||
+ _48 = &mut (_19.0: &mut std::future::Ready<()>);
|
||||
+ _45 = copy (_19.0: &mut std::future::Ready<()>);
|
||||
+ StorageDead(_48);
|
||||
+ _47 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _45 };
|
||||
+ _47 = Pin::<&mut std::future::Ready<()>> { pointer: copy _45 };
|
||||
+ StorageDead(_47);
|
||||
+ _44 = &mut ((*_45).0: std::option::Option<()>);
|
||||
+ StorageLive(_49);
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@
|
|||
- }
|
||||
-
|
||||
- bb2: {
|
||||
+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: copy _5 };
|
||||
+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { pointer: copy _5 };
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
|
|
@ -235,7 +235,7 @@
|
|||
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
|
||||
+ _20 = &mut (*_21);
|
||||
+ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 };
|
||||
+ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
|
||||
+ StorageDead(_20);
|
||||
+ StorageLive(_22);
|
||||
+ StorageLive(_23);
|
||||
|
|
@ -256,7 +256,7 @@
|
|||
+ _50 = &mut (_19.0: &mut std::future::Ready<()>);
|
||||
+ _47 = copy (_19.0: &mut std::future::Ready<()>);
|
||||
+ StorageDead(_50);
|
||||
+ _49 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _47 };
|
||||
+ _49 = Pin::<&mut std::future::Ready<()>> { pointer: copy _47 };
|
||||
+ StorageDead(_49);
|
||||
+ _46 = &mut ((*_47).0: std::option::Option<()>);
|
||||
+ StorageLive(_51);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ fn single_switchint() -> () {
|
|||
}
|
||||
|
||||
bb1: {
|
||||
switchInt(copy (_2.0: i32)) -> [3: bb8, 4: bb8, otherwise: bb7];
|
||||
switchInt(copy (_2.0: i32)) -> [3: bb9, 4: bb9, otherwise: bb8];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
|
@ -22,7 +22,7 @@ fn single_switchint() -> () {
|
|||
}
|
||||
|
||||
bb3: {
|
||||
falseEdge -> [real: bb12, imaginary: bb4];
|
||||
falseEdge -> [real: bb14, imaginary: bb4];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
|
|
@ -30,43 +30,51 @@ fn single_switchint() -> () {
|
|||
}
|
||||
|
||||
bb5: {
|
||||
falseEdge -> [real: bb11, imaginary: bb6];
|
||||
falseEdge -> [real: bb13, imaginary: bb6];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
falseEdge -> [real: bb10, imaginary: bb1];
|
||||
switchInt(copy (_2.1: bool)) -> [0: bb7, otherwise: bb7];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
_1 = const 5_i32;
|
||||
goto -> bb13;
|
||||
falseEdge -> [real: bb12, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb8: {
|
||||
falseEdge -> [real: bb9, imaginary: bb7];
|
||||
_1 = const 5_i32;
|
||||
goto -> bb15;
|
||||
}
|
||||
|
||||
bb9: {
|
||||
_1 = const 4_i32;
|
||||
goto -> bb13;
|
||||
switchInt(copy (_2.1: bool)) -> [0: bb10, otherwise: bb10];
|
||||
}
|
||||
|
||||
bb10: {
|
||||
_1 = const 3_i32;
|
||||
goto -> bb13;
|
||||
falseEdge -> [real: bb11, imaginary: bb8];
|
||||
}
|
||||
|
||||
bb11: {
|
||||
_1 = const 2_i32;
|
||||
goto -> bb13;
|
||||
_1 = const 4_i32;
|
||||
goto -> bb15;
|
||||
}
|
||||
|
||||
bb12: {
|
||||
_1 = const 1_i32;
|
||||
goto -> bb13;
|
||||
_1 = const 3_i32;
|
||||
goto -> bb15;
|
||||
}
|
||||
|
||||
bb13: {
|
||||
_1 = const 2_i32;
|
||||
goto -> bb15;
|
||||
}
|
||||
|
||||
bb14: {
|
||||
_1 = const 1_i32;
|
||||
goto -> bb15;
|
||||
}
|
||||
|
||||
bb15: {
|
||||
StorageDead(_2);
|
||||
StorageDead(_1);
|
||||
_0 = const ();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue