mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Merge commit '59a81c2ca1edc88ad3ac4b27a8e03977ffb8e73a' into subtree-update_cg_gcc_2025_01_12
This commit is contained in:
commit
06f0a9bc78
@ -22,7 +22,6 @@ jobs:
|
||||
- { gcc: "gcc-13.deb" }
|
||||
- { gcc: "gcc-13-without-int128.deb" }
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
# FIXME: re-enable asm tests when GCC can emit in the right syntax.
|
||||
# "--asm-tests",
|
||||
@ -79,6 +78,7 @@ jobs:
|
||||
run: |
|
||||
./y.sh prepare --only-libcore
|
||||
./y.sh build --sysroot
|
||||
./y.sh test --mini-tests
|
||||
cargo test
|
||||
|
||||
- name: Run y.sh cargo build
|
||||
@ -87,7 +87,7 @@ jobs:
|
||||
|
||||
- name: Clean
|
||||
run: |
|
||||
./y.sh clean all
|
||||
./y.sh clean all
|
||||
|
||||
- name: Prepare dependencies
|
||||
run: |
|
||||
@ -95,9 +95,6 @@ jobs:
|
||||
git config --global user.name "User"
|
||||
./y.sh prepare
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./y.sh test --release --clean --build-sysroot ${{ matrix.commands }}
|
||||
|
@ -90,15 +90,12 @@ jobs:
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: ./y.sh prepare
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
# TODO: re-enable those tests for libgccjit 12.
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
id: tests
|
||||
run: |
|
||||
${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log
|
||||
${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log
|
||||
rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Run failing ui pattern tests for ICE
|
||||
@ -106,7 +103,7 @@ jobs:
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
id: ui-tests
|
||||
run: |
|
||||
${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --test-failing-ui-pattern-tests ${{ matrix.libgccjit_version.extra }} | tee output_log_ui
|
||||
${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --test-failing-ui-pattern-tests ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log_ui
|
||||
if grep -q "the compiler unexpectedly panicked" output_log_ui; then
|
||||
echo "Error: 'the compiler unexpectedly panicked' found in output logs. CI Error!!"
|
||||
exit 1
|
||||
|
@ -82,9 +82,6 @@ jobs:
|
||||
#- name: Add more failing tests for GCC 12
|
||||
#run: cat tests/failing-ui-tests12.txt >> tests/failing-ui-tests.txt
|
||||
|
||||
#- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
#run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
|
||||
|
||||
#- name: Run tests
|
||||
#run: |
|
||||
#./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
|
||||
|
@ -23,7 +23,6 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
commands: [
|
||||
"--mini-tests",
|
||||
"--std-tests",
|
||||
# TODO(antoyo): fix those on m68k.
|
||||
#"--test-libcore",
|
||||
@ -93,6 +92,7 @@ jobs:
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh test --mini-tests
|
||||
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test
|
||||
./y.sh clean all
|
||||
|
||||
@ -102,9 +102,6 @@ jobs:
|
||||
git config --global user.name "User"
|
||||
./y.sh prepare --cross
|
||||
|
||||
- name: Add more failing tests because the sysroot is not compiled with LTO
|
||||
run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }}
|
||||
|
@ -13,7 +13,7 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@ -54,6 +54,7 @@ jobs:
|
||||
run: |
|
||||
./y.sh prepare --only-libcore
|
||||
EMBED_LTO_BITCODE=1 ./y.sh build --sysroot --release --release-sysroot
|
||||
./y.sh test --mini-tests
|
||||
cargo test
|
||||
./y.sh clean all
|
||||
|
||||
@ -70,4 +71,9 @@ jobs:
|
||||
run: |
|
||||
# FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
|
||||
echo -n 'lto = "fat"' >> build_system/build_sysroot/Cargo.toml
|
||||
EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }}
|
||||
EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }}
|
||||
|
||||
- name: Run y.sh cargo build
|
||||
run: |
|
||||
EMBED_LTO_BITCODE=1 CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml
|
||||
# TODO: grep the asm output for "call my_func" and fail if it is found.
|
||||
|
@ -73,10 +73,6 @@ jobs:
|
||||
echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV
|
||||
echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV
|
||||
|
||||
- name: Build (part 2)
|
||||
run: |
|
||||
cargo test
|
||||
|
||||
- name: Clean
|
||||
if: ${{ !matrix.cargo_runner }}
|
||||
run: |
|
||||
@ -92,6 +88,7 @@ jobs:
|
||||
if: ${{ !matrix.cargo_runner }}
|
||||
run: |
|
||||
./y.sh test --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore
|
||||
cargo test
|
||||
|
||||
- name: Run stdarch tests
|
||||
if: ${{ !matrix.cargo_runner }}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
@ -11,12 +11,40 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "boml"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "fm"
|
||||
version = "0.2.2"
|
||||
@ -28,18 +56,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "2.2.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bb376e98c82d9284c3a17fc1d6bf9bc921055418950238d7a553c27a7e1f6ab"
|
||||
checksum = "72fd91f4adbf02b53cfc73c97bc33c5f253009043f30c56a5ec08dd5c8094dc8"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "0.3.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93b4b1be553b5df790bf25ca2a1d6add81727dc29f8d5c8742468ed306d621d1"
|
||||
checksum = "0fb7b8f48a75e2cfe78c3d9a980b32771c34ffd12d196021ab3f98c49fbd2f0d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@ -77,9 +105,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
version = "0.2.168"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
@ -97,6 +131,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.8.4"
|
||||
@ -121,6 +161,20 @@ dependencies = [
|
||||
"boml",
|
||||
"gccjit",
|
||||
"lang_tester",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -132,6 +186,19 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.2.0"
|
||||
@ -205,3 +272,76 @@ name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
@ -22,15 +22,16 @@ master = ["gccjit/master"]
|
||||
default = ["master"]
|
||||
|
||||
[dependencies]
|
||||
gccjit = "2.2"
|
||||
gccjit = "2.4"
|
||||
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
|
||||
|
||||
# Local copy.
|
||||
#gccjit = { path = "../gccjit.rs" }
|
||||
|
||||
[dev-dependencies]
|
||||
lang_tester = "0.8.0"
|
||||
boml = "0.3.1"
|
||||
lang_tester = "0.8.0"
|
||||
tempfile = "3.7.1"
|
||||
|
||||
[profile.dev]
|
||||
# By compiling dependencies with optimizations, performing tests gets much faster.
|
||||
|
@ -93,6 +93,7 @@ struct TestArg {
|
||||
sysroot_panic_abort: bool,
|
||||
config_info: ConfigInfo,
|
||||
sysroot_features: Vec<String>,
|
||||
keep_lto_tests: bool,
|
||||
}
|
||||
|
||||
impl TestArg {
|
||||
@ -128,6 +129,9 @@ impl TestArg {
|
||||
"--sysroot-panic-abort" => {
|
||||
test_arg.sysroot_panic_abort = true;
|
||||
}
|
||||
"--keep-lto-tests" => {
|
||||
test_arg.keep_lto_tests = true;
|
||||
}
|
||||
"--sysroot-features" => match args.next() {
|
||||
Some(feature) if !feature.is_empty() => {
|
||||
test_arg.sysroot_features.push(feature);
|
||||
@ -194,7 +198,7 @@ fn build_if_no_backend(env: &Env, args: &TestArg) -> Result<(), String> {
|
||||
}
|
||||
|
||||
fn clean(_env: &Env, args: &TestArg) -> Result<(), String> {
|
||||
let _ = std::fs::remove_dir_all(&args.config_info.cargo_target_dir);
|
||||
let _ = remove_dir_all(&args.config_info.cargo_target_dir);
|
||||
let path = Path::new(&args.config_info.cargo_target_dir).join("gccjit");
|
||||
create_dir(&path)
|
||||
}
|
||||
@ -641,7 +645,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
|
||||
//failing test is fixed upstream.
|
||||
//"https://github.com/marshallpierce/rust-base64", // FIXME: one test is OOM-killed.
|
||||
// TODO: ignore the base64 test that is OOM-killed.
|
||||
"https://github.com/time-rs/time",
|
||||
//"https://github.com/time-rs/time", // FIXME: one test fails (https://github.com/time-rs/time/issues/719).
|
||||
"https://github.com/rust-lang/log",
|
||||
"https://github.com/bitflags/bitflags",
|
||||
//"https://github.com/serde-rs/serde", // FIXME: one test fails.
|
||||
@ -835,8 +839,7 @@ fn valid_ui_error_pattern_test(file: &str) -> bool {
|
||||
.any(|to_ignore| file.ends_with(to_ignore))
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn contains_ui_error_patterns(file_path: &Path) -> Result<bool, String> {
|
||||
fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result<bool, String> {
|
||||
// Tests generating errors.
|
||||
let file = File::open(file_path)
|
||||
.map_err(|error| format!("Failed to read `{}`: {:?}", file_path.display(), error))?;
|
||||
@ -849,22 +852,38 @@ fn contains_ui_error_patterns(file_path: &Path) -> Result<bool, String> {
|
||||
"//@ error-pattern:",
|
||||
"//@ build-fail",
|
||||
"//@ run-fail",
|
||||
"//@ known-bug",
|
||||
"-Cllvm-args",
|
||||
"//~",
|
||||
"thread",
|
||||
]
|
||||
.iter()
|
||||
.any(|check| line.contains(check))
|
||||
.iter()
|
||||
.any(|check| line.contains(check))
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
if !keep_lto_tests
|
||||
&& (line.contains("-Clto")
|
||||
|| line.contains("-C lto")
|
||||
|| line.contains("compile-flags: -Clinker-plugin-lto"))
|
||||
&& !line.contains("-Clto=thin")
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
if line.contains("//[") && line.contains("]~") {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
if file_path.display().to_string().contains("ambiguous-4-extern.rs") {
|
||||
let file_path = file_path.display().to_string();
|
||||
if file_path.contains("ambiguous-4-extern.rs") {
|
||||
eprintln!("nothing found for {file_path:?}");
|
||||
}
|
||||
// The files in this directory contain errors.
|
||||
if file_path.contains("/error-emitter/") {
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
@ -903,7 +922,7 @@ where
|
||||
rust_path.join("tests/ui"),
|
||||
&mut |_dir| Ok(()),
|
||||
&mut |file_path| {
|
||||
if contains_ui_error_patterns(file_path)? {
|
||||
if contains_ui_error_patterns(file_path, args.keep_lto_tests)? {
|
||||
Ok(())
|
||||
} else {
|
||||
remove_file(file_path).map_err(|e| e.to_string())
|
||||
@ -928,7 +947,7 @@ where
|
||||
.iter()
|
||||
.any(|name| *name == dir_name)
|
||||
{
|
||||
std::fs::remove_dir_all(dir).map_err(|error| {
|
||||
remove_dir_all(dir).map_err(|error| {
|
||||
format!("Failed to remove folder `{}`: {:?}", dir.display(), error)
|
||||
})?;
|
||||
}
|
||||
@ -940,27 +959,42 @@ where
|
||||
|
||||
// These two functions are used to remove files that are known to not be working currently
|
||||
// with the GCC backend to reduce noise.
|
||||
fn dir_handling(dir: &Path) -> Result<(), String> {
|
||||
if dir.file_name().map(|name| name == "auxiliary").unwrap_or(true) {
|
||||
return Ok(());
|
||||
}
|
||||
fn dir_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> {
|
||||
move |dir| {
|
||||
if dir.file_name().map(|name| name == "auxiliary").unwrap_or(true) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
walk_dir(dir, &mut dir_handling, &mut file_handling, false)
|
||||
}
|
||||
fn file_handling(file_path: &Path) -> Result<(), String> {
|
||||
if !file_path.extension().map(|extension| extension == "rs").unwrap_or(false) {
|
||||
return Ok(());
|
||||
walk_dir(
|
||||
dir,
|
||||
&mut dir_handling(keep_lto_tests),
|
||||
&mut file_handling(keep_lto_tests),
|
||||
false,
|
||||
)
|
||||
}
|
||||
let path_str = file_path.display().to_string().replace("\\", "/");
|
||||
if valid_ui_error_pattern_test(&path_str) {
|
||||
return Ok(());
|
||||
} else if contains_ui_error_patterns(file_path)? {
|
||||
return remove_file(&file_path);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
walk_dir(rust_path.join("tests/ui"), &mut dir_handling, &mut file_handling, false)?;
|
||||
fn file_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> {
|
||||
move |file_path| {
|
||||
if !file_path.extension().map(|extension| extension == "rs").unwrap_or(false) {
|
||||
return Ok(());
|
||||
}
|
||||
let path_str = file_path.display().to_string().replace("\\", "/");
|
||||
if valid_ui_error_pattern_test(&path_str) {
|
||||
return Ok(());
|
||||
} else if contains_ui_error_patterns(file_path, keep_lto_tests)? {
|
||||
return remove_file(&file_path);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
walk_dir(
|
||||
rust_path.join("tests/ui"),
|
||||
&mut dir_handling(args.keep_lto_tests),
|
||||
&mut file_handling(args.keep_lto_tests),
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
let nb_parts = args.nb_parts.unwrap_or(0);
|
||||
if nb_parts > 0 {
|
||||
@ -1173,7 +1207,7 @@ fn remove_files_callback<'a>(
|
||||
files.split('\n').map(|line| line.trim()).filter(|line| !line.is_empty())
|
||||
{
|
||||
let path = rust_path.join(file);
|
||||
if let Err(e) = std::fs::remove_dir_all(&path) {
|
||||
if let Err(e) = remove_dir_all(&path) {
|
||||
println!("Failed to remove directory `{}`: {}", path.display(), e);
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +170,14 @@ impl Add for usize {
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for isize {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "sub"]
|
||||
pub trait Sub<RHS = Self> {
|
||||
type Output;
|
||||
|
@ -1 +1 @@
|
||||
e744a9459d33864067214741daf5c5bc2a7b88c6
|
||||
45648c2edd4ecd862d9f08196d3d6c6ccba79f07
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 18793c6109890493ceb3ff36549849a36e3d8022 Mon Sep 17 00:00:00 2001
|
||||
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] [core] Disable not compiling tests
|
||||
Subject: [PATCH] Disable not compiling tests
|
||||
|
||||
---
|
||||
library/core/tests/Cargo.toml | 14 ++++++++++++++
|
||||
@ -30,14 +30,15 @@ index 0000000..ca326ac
|
||||
+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 1e336bf..5800ebb 100644
|
||||
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(bootstrap, feature(offset_of_nested))]
|
||||
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
#![cfg_attr(test, feature(cfg_match))]
|
||||
--
|
||||
2.46.0
|
||||
#![feature(alloc_layout_extra)]
|
||||
--
|
||||
2.47.1
|
||||
|
||||
|
@ -27,5 +27,4 @@ index b71786c..cf484d5 100644
|
||||
mod slice;
|
||||
mod str;
|
||||
mod str_lossy;
|
||||
--
|
||||
2.45.2
|
||||
-- 2.45.2
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2024-08-11"
|
||||
channel = "nightly-2025-01-12"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::FnAttribute;
|
||||
use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{FnAttribute, VarAttribute};
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||
alloc_error_handler_name, default_fn_name, global_fn_name,
|
||||
@ -10,6 +10,8 @@ use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::OomStrategy;
|
||||
|
||||
use crate::GccContext;
|
||||
#[cfg(feature = "master")]
|
||||
use crate::base::symbol_visibility_to_gcc;
|
||||
|
||||
pub(crate) unsafe fn codegen(
|
||||
tcx: TyCtxt<'_>,
|
||||
@ -70,12 +72,20 @@ pub(crate) unsafe fn codegen(
|
||||
|
||||
let name = OomStrategy::SYMBOL.to_string();
|
||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||
#[cfg(feature = "master")]
|
||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
tcx.sess.default_visibility(),
|
||||
)));
|
||||
let value = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let value = context.new_rvalue_from_int(i8, value as i32);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string();
|
||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||
#[cfg(feature = "master")]
|
||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
tcx.sess.default_visibility(),
|
||||
)));
|
||||
let value = context.new_rvalue_from_int(i8, 0);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
}
|
||||
@ -105,15 +115,9 @@ fn create_wrapper_function(
|
||||
);
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
match tcx.sess.default_visibility() {
|
||||
rustc_target::spec::SymbolVisibility::Hidden => {
|
||||
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden))
|
||||
}
|
||||
rustc_target::spec::SymbolVisibility::Protected => {
|
||||
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Protected))
|
||||
}
|
||||
rustc_target::spec::SymbolVisibility::Interposable => {}
|
||||
}
|
||||
func.add_attribute(FnAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
tcx.sess.default_visibility(),
|
||||
)));
|
||||
|
||||
if tcx.sess.must_emit_unwind_tables() {
|
||||
// TODO(antoyo): emit unwind tables.
|
||||
|
@ -35,16 +35,13 @@ use rustc_middle::bug;
|
||||
use rustc_middle::dep_graph::WorkProduct;
|
||||
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
|
||||
use rustc_session::config::{CrateType, Lto};
|
||||
use rustc_target::spec::RelocModel;
|
||||
use tempfile::{TempDir, tempdir};
|
||||
|
||||
use crate::back::write::save_temp_bitcode;
|
||||
use crate::errors::{DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib};
|
||||
use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level};
|
||||
|
||||
/// We keep track of the computed LTO cache keys from the previous
|
||||
/// session to determine which CGUs we can reuse.
|
||||
//pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
|
||||
|
||||
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
||||
match crate_type {
|
||||
CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
|
||||
@ -54,7 +51,7 @@ pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
||||
|
||||
struct LtoData {
|
||||
// TODO(antoyo): use symbols_below_threshold.
|
||||
//symbols_below_threshold: Vec<CString>,
|
||||
//symbols_below_threshold: Vec<String>,
|
||||
upstream_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
tmp_path: TempDir,
|
||||
}
|
||||
@ -83,7 +80,7 @@ fn prepare_lto(
|
||||
|
||||
let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
|
||||
if info.level.is_below_threshold(export_threshold) || info.used {
|
||||
Some(CString::new(name.as_str()).unwrap())
|
||||
Some(name.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -91,7 +88,7 @@ fn prepare_lto(
|
||||
let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
|
||||
let mut symbols_below_threshold = {
|
||||
let _timer = cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold");
|
||||
exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<CString>>()
|
||||
exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<String>>()
|
||||
};
|
||||
info!("{} symbols to preserve in this crate", symbols_below_threshold.len());
|
||||
|
||||
@ -159,11 +156,7 @@ fn prepare_lto(
|
||||
}
|
||||
}
|
||||
|
||||
Ok(LtoData {
|
||||
//symbols_below_threshold,
|
||||
upstream_modules,
|
||||
tmp_path,
|
||||
})
|
||||
Ok(LtoData { upstream_modules, tmp_path })
|
||||
}
|
||||
|
||||
fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> {
|
||||
@ -191,7 +184,7 @@ pub(crate) fn run_fat(
|
||||
cached_modules,
|
||||
lto_data.upstream_modules,
|
||||
lto_data.tmp_path,
|
||||
//&symbols_below_threshold,
|
||||
//<o_data.symbols_below_threshold,
|
||||
)
|
||||
}
|
||||
|
||||
@ -202,7 +195,7 @@ fn fat_lto(
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
tmp_path: TempDir,
|
||||
//symbols_below_threshold: &[*const libc::c_char],
|
||||
//symbols_below_threshold: &[String],
|
||||
) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
|
||||
info!("going for a fat lto");
|
||||
@ -327,6 +320,7 @@ fn fat_lto(
|
||||
ptr as *const *const libc::c_char,
|
||||
symbols_below_threshold.len() as libc::size_t,
|
||||
);*/
|
||||
|
||||
save_temp_bitcode(cgcx, &module, "lto.after-restriction");
|
||||
//}
|
||||
}
|
||||
@ -363,8 +357,6 @@ pub(crate) fn run_thin(
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
let lto_data = prepare_lto(cgcx, dcx)?;
|
||||
/*let symbols_below_threshold =
|
||||
symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();*/
|
||||
if cgcx.opts.cg.linker_plugin_lto.enabled() {
|
||||
unreachable!(
|
||||
"We should never reach this case if the LTO step \
|
||||
@ -377,7 +369,8 @@ pub(crate) fn run_thin(
|
||||
modules,
|
||||
lto_data.upstream_modules,
|
||||
lto_data.tmp_path,
|
||||
cached_modules, /*, &symbols_below_threshold*/
|
||||
cached_modules,
|
||||
//<o_data.symbols_below_threshold,
|
||||
)
|
||||
}
|
||||
|
||||
@ -428,7 +421,7 @@ fn thin_lto(
|
||||
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
tmp_path: TempDir,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
//symbols_below_threshold: &[*const libc::c_char],
|
||||
//_symbols_below_threshold: &[String],
|
||||
) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
|
||||
info!("going for that thin, thin LTO");
|
||||
@ -640,7 +633,13 @@ pub unsafe fn optimize_thin_module(
|
||||
}
|
||||
};
|
||||
let module = ModuleCodegen {
|
||||
module_llvm: GccContext { context, should_combine_object_files, temp_dir: None },
|
||||
module_llvm: GccContext {
|
||||
context,
|
||||
should_combine_object_files,
|
||||
// TODO(antoyo): use the correct relocation model here.
|
||||
relocation_model: RelocModel::Pic,
|
||||
temp_dir: None,
|
||||
},
|
||||
name: thin_module.name().to_string(),
|
||||
kind: ModuleKind::Regular,
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::{env, fs};
|
||||
|
||||
use gccjit::OutputKind;
|
||||
use gccjit::{Context, OutputKind};
|
||||
use rustc_codegen_ssa::back::link::ensure_removed;
|
||||
use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
|
||||
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
|
||||
@ -10,6 +10,7 @@ use rustc_session::config::OutputType;
|
||||
use rustc_span::fatal_error::FatalError;
|
||||
use rustc_target::spec::SplitDebuginfo;
|
||||
|
||||
use crate::base::add_pic_option;
|
||||
use crate::errors::CopyBitcode;
|
||||
use crate::{GccCodegenBackend, GccContext};
|
||||
|
||||
@ -31,51 +32,87 @@ pub(crate) unsafe fn codegen(
|
||||
|
||||
// NOTE: Only generate object files with GIMPLE when this environment variable is set for
|
||||
// now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit).
|
||||
// TODO: remove this environment variable.
|
||||
// TODO(antoyo): remove this environment variable.
|
||||
let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1");
|
||||
|
||||
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
|
||||
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
|
||||
|
||||
if config.bitcode_needed() && fat_lto {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name);
|
||||
|
||||
// TODO(antoyo)
|
||||
/*if let Some(bitcode_filename) = bc_out.file_name() {
|
||||
cgcx.prof.artifact_size(
|
||||
"llvm_bitcode",
|
||||
bitcode_filename.to_string_lossy(),
|
||||
data.len() as u64,
|
||||
);
|
||||
}*/
|
||||
|
||||
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||
if config.bitcode_needed() {
|
||||
if fat_lto {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name);
|
||||
context.add_command_line_option("-flto=auto");
|
||||
context.add_command_line_option("-flto-partition=one");
|
||||
// TODO: remove since we don't want fat objects when it is for Bitcode only.
|
||||
context.add_command_line_option("-ffat-lto-objects");
|
||||
context
|
||||
.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
|
||||
}
|
||||
.generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name);
|
||||
|
||||
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name);
|
||||
// TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
|
||||
//embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
// TODO(antoyo)
|
||||
/*if let Some(bitcode_filename) = bc_out.file_name() {
|
||||
cgcx.prof.artifact_size(
|
||||
"llvm_bitcode",
|
||||
bitcode_filename.to_string_lossy(),
|
||||
data.len() as u64,
|
||||
);
|
||||
}*/
|
||||
|
||||
context.add_command_line_option("-flto=auto");
|
||||
context.add_command_line_option("-flto-partition=one");
|
||||
context.add_command_line_option("-ffat-lto-objects");
|
||||
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
|
||||
context
|
||||
.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
|
||||
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"GCC_module_codegen_emit_bitcode",
|
||||
&*module.name,
|
||||
);
|
||||
context.add_command_line_option("-flto=auto");
|
||||
context.add_command_line_option("-flto-partition=one");
|
||||
// TODO(antoyo): remove since we don't want fat objects when it is for Bitcode only.
|
||||
context.add_command_line_option("-ffat-lto-objects");
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
bc_out.to_str().expect("path to str"),
|
||||
);
|
||||
}
|
||||
|
||||
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"GCC_module_codegen_embed_bitcode",
|
||||
&*module.name,
|
||||
);
|
||||
// TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
|
||||
//embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
|
||||
context.add_command_line_option("-flto=auto");
|
||||
context.add_command_line_option("-flto-partition=one");
|
||||
context.add_command_line_option("-ffat-lto-objects");
|
||||
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
bc_out.to_str().expect("path to str"),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"GCC_module_codegen_emit_bitcode",
|
||||
&*module.name,
|
||||
);
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
bc_out.to_str().expect("path to str"),
|
||||
);
|
||||
}
|
||||
|
||||
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
|
||||
// TODO(antoyo): we might want to emit to emit an error here, saying to set the
|
||||
// environment variable EMBED_LTO_BITCODE.
|
||||
let _timer = cgcx.prof.generic_activity_with_arg(
|
||||
"GCC_module_codegen_embed_bitcode",
|
||||
&*module.name,
|
||||
);
|
||||
// TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes?
|
||||
//embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
|
||||
// TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
bc_out.to_str().expect("path to str"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,6 +160,8 @@ pub(crate) unsafe fn codegen(
|
||||
|
||||
// NOTE: without -fuse-linker-plugin, we get the following error:
|
||||
// lto1: internal compiler error: decompressed stream: Destination buffer is too small
|
||||
// TODO(antoyo): since we do not do LTO when the linker is invoked anymore, perhaps
|
||||
// the following flag is not necessary anymore.
|
||||
context.add_driver_option("-fuse-linker-plugin");
|
||||
}
|
||||
|
||||
@ -131,11 +170,43 @@ pub(crate) unsafe fn codegen(
|
||||
// /usr/bin/ld: cannot find -lgcc_s: No such file or directory
|
||||
context.add_driver_option("-nostdlib");
|
||||
|
||||
// NOTE: this doesn't actually generate an executable. With the above flags, it combines the .o files together in another .o.
|
||||
context.compile_to_file(
|
||||
OutputKind::Executable,
|
||||
obj_out.to_str().expect("path to str"),
|
||||
);
|
||||
let path = obj_out.to_str().expect("path to str");
|
||||
|
||||
if fat_lto {
|
||||
let lto_path = format!("{}.lto", path);
|
||||
// FIXME(antoyo): The LTO frontend generates the following warning:
|
||||
// ../build_sysroot/sysroot_src/library/core/src/num/dec2flt/lemire.rs:150:15: warning: type of ‘_ZN4core3num7dec2flt5table17POWER_OF_FIVE_12817ha449a68fb31379e4E’ does not match original declaration [-Wlto-type-mismatch]
|
||||
// 150 | let (lo5, hi5) = POWER_OF_FIVE_128[index];
|
||||
// | ^
|
||||
// lto1: note: ‘_ZN4core3num7dec2flt5table17POWER_OF_FIVE_12817ha449a68fb31379e4E’ was previously declared here
|
||||
//
|
||||
// This option is to mute it to make the UI tests pass with LTO enabled.
|
||||
context.add_driver_option("-Wno-lto-type-mismatch");
|
||||
// NOTE: this doesn't actually generate an executable. With the above
|
||||
// flags, it combines the .o files together in another .o.
|
||||
context.compile_to_file(OutputKind::Executable, <o_path);
|
||||
|
||||
let context = Context::default();
|
||||
if cgcx.target_arch == "x86" || cgcx.target_arch == "x86_64" {
|
||||
// NOTE: it seems we need to use add_driver_option instead of
|
||||
// add_command_line_option here because we use the LTO frontend via gcc.
|
||||
context.add_driver_option("-masm=intel");
|
||||
}
|
||||
|
||||
// NOTE: these two options are needed to invoke LTO to produce an object file.
|
||||
// We need to initiate a second compilation because the arguments "-x lto"
|
||||
// needs to be at the very beginning.
|
||||
context.add_driver_option("-x");
|
||||
context.add_driver_option("lto");
|
||||
add_pic_option(&context, module.module_llvm.relocation_model);
|
||||
context.add_driver_option(lto_path);
|
||||
|
||||
context.compile_to_file(OutputKind::ObjectFile, path);
|
||||
} else {
|
||||
// NOTE: this doesn't actually generate an executable. With the above
|
||||
// flags, it combines the .o files together in another .o.
|
||||
context.compile_to_file(OutputKind::Executable, path);
|
||||
}
|
||||
} else {
|
||||
context.compile_to_file(
|
||||
OutputKind::ObjectFile,
|
||||
|
@ -3,7 +3,7 @@ use std::env;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
use gccjit::{CType, FunctionType, GlobalKind};
|
||||
use gccjit::{CType, Context, FunctionType, GlobalKind};
|
||||
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
|
||||
use rustc_codegen_ssa::mono_item::MonoItemExt;
|
||||
use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
|
||||
@ -15,21 +15,32 @@ use rustc_middle::mir::mono::Visibility;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_target::spec::SymbolVisibility;
|
||||
use rustc_target::spec::{PanicStrategy, RelocModel};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::{GccContext, LockedTargetInfo, SyncContext, gcc_util, new_context};
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
pub fn visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility {
|
||||
match linkage {
|
||||
pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility {
|
||||
match visibility {
|
||||
Visibility::Default => gccjit::Visibility::Default,
|
||||
Visibility::Hidden => gccjit::Visibility::Hidden,
|
||||
Visibility::Protected => gccjit::Visibility::Protected,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
pub fn symbol_visibility_to_gcc(visibility: SymbolVisibility) -> gccjit::Visibility {
|
||||
match visibility {
|
||||
SymbolVisibility::Hidden => gccjit::Visibility::Hidden,
|
||||
SymbolVisibility::Protected => gccjit::Visibility::Protected,
|
||||
SymbolVisibility::Interposable => gccjit::Visibility::Default,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
|
||||
match linkage {
|
||||
Linkage::External => GlobalKind::Imported,
|
||||
@ -140,9 +151,7 @@ pub fn compile_codegen_unit(
|
||||
});
|
||||
}
|
||||
|
||||
if tcx.sess.relocation_model() == rustc_target::spec::RelocModel::Static {
|
||||
context.add_command_line_option("-fno-pie");
|
||||
}
|
||||
add_pic_option(&context, tcx.sess.relocation_model());
|
||||
|
||||
let target_cpu = gcc_util::target_cpu(tcx.sess);
|
||||
if target_cpu != "generic" {
|
||||
@ -199,12 +208,13 @@ pub fn compile_codegen_unit(
|
||||
let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32);
|
||||
let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64);
|
||||
let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128);
|
||||
let u128_type_supported = target_info.supports_target_dependent_type(CType::UInt128t);
|
||||
// TODO: improve this to avoid passing that many arguments.
|
||||
let cx = CodegenCx::new(
|
||||
&context,
|
||||
cgu,
|
||||
tcx,
|
||||
target_info.supports_128bit_int(),
|
||||
u128_type_supported,
|
||||
f16_type_supported,
|
||||
f32_type_supported,
|
||||
f64_type_supported,
|
||||
@ -235,6 +245,7 @@ pub fn compile_codegen_unit(
|
||||
name: cgu_name.to_string(),
|
||||
module_llvm: GccContext {
|
||||
context: Arc::new(SyncContext::new(context)),
|
||||
relocation_model: tcx.sess.relocation_model(),
|
||||
should_combine_object_files: false,
|
||||
temp_dir: None,
|
||||
},
|
||||
@ -244,3 +255,24 @@ pub fn compile_codegen_unit(
|
||||
|
||||
(module, cost)
|
||||
}
|
||||
|
||||
pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) {
|
||||
match relocation_model {
|
||||
rustc_target::spec::RelocModel::Static => {
|
||||
context.add_command_line_option("-fno-pie");
|
||||
context.add_driver_option("-fno-pie");
|
||||
}
|
||||
rustc_target::spec::RelocModel::Pic => {
|
||||
context.add_command_line_option("-fPIC");
|
||||
// NOTE: we use both add_command_line_option and add_driver_option because the usage in
|
||||
// this module (compile_codegen_unit) requires add_command_line_option while the usage
|
||||
// in the back::write module (codegen) requires add_driver_option.
|
||||
context.add_driver_option("-fPIC");
|
||||
}
|
||||
rustc_target::spec::RelocModel::Pie => {
|
||||
context.add_command_line_option("-fPIE");
|
||||
context.add_driver_option("-fPIE");
|
||||
}
|
||||
model => eprintln!("Unsupported relocation model: {:?}", model),
|
||||
}
|
||||
}
|
||||
|
@ -1102,18 +1102,24 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
val: RValue<'gcc>,
|
||||
ptr: RValue<'gcc>,
|
||||
align: Align,
|
||||
_flags: MemFlags,
|
||||
flags: MemFlags,
|
||||
) -> RValue<'gcc> {
|
||||
let ptr = self.check_store(val, ptr);
|
||||
let destination = ptr.dereference(self.location);
|
||||
// NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast
|
||||
// to type so it gets the proper alignment.
|
||||
let destination_type = destination.to_rvalue().get_type().unqualified();
|
||||
let aligned_type = destination_type.get_aligned(align.bytes()).make_pointer();
|
||||
let aligned_destination = self.cx.context.new_bitcast(self.location, ptr, aligned_type);
|
||||
let aligned_destination = aligned_destination.dereference(self.location);
|
||||
self.llbb().add_assignment(self.location, aligned_destination, val);
|
||||
// TODO(antoyo): handle align and flags.
|
||||
let align = if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() };
|
||||
let mut modified_destination_type = destination_type.get_aligned(align);
|
||||
if flags.contains(MemFlags::VOLATILE) {
|
||||
modified_destination_type = modified_destination_type.make_volatile();
|
||||
}
|
||||
|
||||
let modified_ptr =
|
||||
self.cx.context.new_cast(self.location, ptr, modified_destination_type.make_pointer());
|
||||
let modified_destination = modified_ptr.dereference(self.location);
|
||||
self.llbb().add_assignment(self.location, modified_destination, val);
|
||||
// TODO(antoyo): handle `MemFlags::NONTEMPORAL`.
|
||||
// NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here?
|
||||
// When adding support for NONTEMPORAL, make sure to not just emit MOVNT on x86; see the
|
||||
// LLVM backend for details.
|
||||
@ -1236,13 +1242,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
let usize_value = self.cx.const_bitcast(value, self.cx.type_isize());
|
||||
let usize_value = self.cx.context.new_cast(None, value, self.cx.type_isize());
|
||||
self.intcast(usize_value, dest_ty, false)
|
||||
}
|
||||
|
||||
fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
let usize_value = self.intcast(value, self.cx.type_isize(), false);
|
||||
self.cx.const_bitcast(usize_value, dest_ty)
|
||||
self.cx.context.new_cast(None, usize_value, dest_ty)
|
||||
}
|
||||
|
||||
fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
@ -1901,6 +1907,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
v2: RValue<'gcc>,
|
||||
mask: RValue<'gcc>,
|
||||
) -> RValue<'gcc> {
|
||||
// NOTE: if the `mask` is a constant value, the following code will copy it in many places,
|
||||
// which will make GCC create a lot (+4000) local variables in some cases.
|
||||
// So we assign it to an explicit local variable once to avoid this.
|
||||
let func = self.current_func();
|
||||
let mask_var = func.new_local(self.location, mask.get_type(), "mask");
|
||||
let block = self.block;
|
||||
block.add_assignment(self.location, mask_var, mask);
|
||||
let mask = mask_var.to_rvalue();
|
||||
|
||||
// TODO(antoyo): use a recursive unqualified() here.
|
||||
let vector_type = v1.get_type().unqualified().dyncast_vector().expect("vector type");
|
||||
let element_type = vector_type.get_element_type();
|
||||
@ -1917,18 +1932,35 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
self.int_type
|
||||
};
|
||||
|
||||
let vector_type =
|
||||
mask.get_type().dyncast_vector().expect("simd_shuffle mask should be of vector type");
|
||||
let mask_num_units = vector_type.get_num_units();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
self.extract_element(mask, index).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
// NOTE: this condition is needed because we call shuffle_vector in the implementation of
|
||||
// simd_gather.
|
||||
let mut mask_elements = if let Some(vector_type) = mask.get_type().dyncast_vector() {
|
||||
let mask_num_units = vector_type.get_num_units();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
self.extract_element(mask, index).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
mask_elements
|
||||
} else {
|
||||
let struct_type = mask.get_type().is_struct().expect("mask should be of struct type");
|
||||
let mask_num_units = struct_type.get_field_count();
|
||||
let mut mask_elements = vec![];
|
||||
for i in 0..mask_num_units {
|
||||
let field = struct_type.get_field(i as i32);
|
||||
mask_elements.push(self.context.new_cast(
|
||||
self.location,
|
||||
mask.access_field(self.location, field).to_rvalue(),
|
||||
mask_element_type,
|
||||
));
|
||||
}
|
||||
mask_elements
|
||||
};
|
||||
let mask_num_units = mask_elements.len();
|
||||
|
||||
// NOTE: the mask needs to be the same length as the input vectors, so add the missing
|
||||
// elements in the mask if needed.
|
||||
|
@ -72,95 +72,74 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
||||
|
||||
attributes::from_fn_attrs(cx, func, instance);
|
||||
|
||||
let instance_def_id = instance.def_id();
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
let instance_def_id = instance.def_id();
|
||||
|
||||
// TODO(antoyo): set linkage and attributes.
|
||||
// TODO(antoyo): set linkage and attributes.
|
||||
|
||||
// Apply an appropriate linkage/visibility value to our item that we
|
||||
// just declared.
|
||||
//
|
||||
// This is sort of subtle. Inside our codegen unit we started off
|
||||
// compilation by predefining all our own `MonoItem` instances. That
|
||||
// is, everything we're codegenning ourselves is already defined. That
|
||||
// means that anything we're actually codegenning in this codegen unit
|
||||
// will have hit the above branch in `get_declared_value`. As a result,
|
||||
// we're guaranteed here that we're declaring a symbol that won't get
|
||||
// defined, or in other words we're referencing a value from another
|
||||
// codegen unit or even another crate.
|
||||
//
|
||||
// So because this is a foreign value we blanket apply an external
|
||||
// linkage directive because it's coming from a different object file.
|
||||
// The visibility here is where it gets tricky. This symbol could be
|
||||
// referencing some foreign crate or foreign library (an `extern`
|
||||
// block) in which case we want to leave the default visibility. We may
|
||||
// also, though, have multiple codegen units. It could be a
|
||||
// monomorphization, in which case its expected visibility depends on
|
||||
// whether we are sharing generics or not. The important thing here is
|
||||
// that the visibility we apply to the declaration is the same one that
|
||||
// has been applied to the definition (wherever that definition may be).
|
||||
let is_generic = instance.args.non_erasable_generics().next().is_some();
|
||||
// Apply an appropriate linkage/visibility value to our item that we
|
||||
// just declared.
|
||||
//
|
||||
// This is sort of subtle. Inside our codegen unit we started off
|
||||
// compilation by predefining all our own `MonoItem` instances. That
|
||||
// is, everything we're codegenning ourselves is already defined. That
|
||||
// means that anything we're actually codegenning in this codegen unit
|
||||
// will have hit the above branch in `get_declared_value`. As a result,
|
||||
// we're guaranteed here that we're declaring a symbol that won't get
|
||||
// defined, or in other words we're referencing a value from another
|
||||
// codegen unit or even another crate.
|
||||
//
|
||||
// So because this is a foreign value we blanket apply an external
|
||||
// linkage directive because it's coming from a different object file.
|
||||
// The visibility here is where it gets tricky. This symbol could be
|
||||
// referencing some foreign crate or foreign library (an `extern`
|
||||
// block) in which case we want to leave the default visibility. We may
|
||||
// also, though, have multiple codegen units. It could be a
|
||||
// monomorphization, in which case its expected visibility depends on
|
||||
// whether we are sharing generics or not. The important thing here is
|
||||
// that the visibility we apply to the declaration is the same one that
|
||||
// has been applied to the definition (wherever that definition may be).
|
||||
let is_generic = instance.args.non_erasable_generics().next().is_some();
|
||||
|
||||
if is_generic {
|
||||
// This is a monomorphization. Its expected visibility depends
|
||||
// on whether we are in share-generics mode.
|
||||
|
||||
if cx.tcx.sess.opts.share_generics() {
|
||||
// We are in share_generics mode.
|
||||
|
||||
if let Some(instance_def_id) = instance_def_id.as_local() {
|
||||
// This is a definition from the current crate. If the
|
||||
// definition is unreachable for downstream crates or
|
||||
// the current crate does not re-export generics, the
|
||||
// definition of the instance will have been declared
|
||||
// as `hidden`.
|
||||
if cx.tcx.is_unreachable_local_definition(instance_def_id)
|
||||
let is_hidden = if is_generic {
|
||||
// This is a monomorphization of a generic function.
|
||||
if !(cx.tcx.sess.opts.share_generics()
|
||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||
== rustc_attr_parsing::InlineAttr::Never)
|
||||
{
|
||||
// When not sharing generics, all instances are in the same
|
||||
// crate and have hidden visibility.
|
||||
true
|
||||
} else if let Some(instance_def_id) = instance_def_id.as_local() {
|
||||
// This is a monomorphization of a generic function
|
||||
// defined in the current crate. It is hidden if:
|
||||
// - the definition is unreachable for downstream
|
||||
// crates, or
|
||||
// - the current crate does not re-export generics
|
||||
// (because the crate is a C library or executable)
|
||||
cx.tcx.is_unreachable_local_definition(instance_def_id)
|
||||
|| !cx.tcx.local_crate_exports_generics()
|
||||
{
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
} else {
|
||||
// This is a monomorphization of a generic function
|
||||
// defined in an upstream crate.
|
||||
if instance.upstream_monomorphization(tcx).is_some() {
|
||||
// This is instantiated in another crate. It cannot
|
||||
// be `hidden`.
|
||||
} else {
|
||||
// This is a local instantiation of an upstream definition.
|
||||
// If the current crate does not re-export it
|
||||
// (because it is a C library or an executable), it
|
||||
// will have been declared `hidden`.
|
||||
if !cx.tcx.local_crate_exports_generics() {
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
}
|
||||
// defined in an upstream crate. It is hidden if:
|
||||
// - it is instantiated in this crate, and
|
||||
// - the current crate does not re-export generics
|
||||
instance.upstream_monomorphization(tcx).is_none()
|
||||
&& !cx.tcx.local_crate_exports_generics()
|
||||
}
|
||||
} else {
|
||||
// When not sharing generics, all instances are in the same
|
||||
// crate and have hidden visibility
|
||||
#[cfg(feature = "master")]
|
||||
// This is a non-generic function. It is hidden if:
|
||||
// - it is instantiated in the local crate, and
|
||||
// - it is defined an upstream crate (non-local), or
|
||||
// - it is not reachable
|
||||
cx.tcx.is_codegened_item(instance_def_id)
|
||||
&& (!instance_def_id.is_local()
|
||||
|| !cx.tcx.is_reachable_non_generic(instance_def_id))
|
||||
};
|
||||
if is_hidden {
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
} else {
|
||||
// This is a non-generic function
|
||||
if cx.tcx.is_codegened_item(instance_def_id) {
|
||||
// This is a function that is instantiated in the local crate
|
||||
|
||||
if instance_def_id.is_local() {
|
||||
// This is function that is defined in the local crate.
|
||||
// If it is not reachable, it is hidden.
|
||||
if !cx.tcx.is_reachable_non_generic(instance_def_id) {
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
} else {
|
||||
// This is a function from an upstream crate that has
|
||||
// been instantiated here. These are always hidden.
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func
|
||||
|
@ -240,14 +240,14 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
};
|
||||
let ptr_type = base_addr.get_type();
|
||||
let base_addr = self.const_bitcast(base_addr, self.usize_type);
|
||||
let base_addr = self.context.new_cast(None, base_addr, self.usize_type);
|
||||
let offset =
|
||||
self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64);
|
||||
let ptr = self.const_bitcast(base_addr + offset, ptr_type);
|
||||
let ptr = self.context.new_cast(None, base_addr + offset, ptr_type);
|
||||
if !matches!(layout.primitive(), Pointer(_)) {
|
||||
self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
|
||||
} else {
|
||||
self.const_bitcast(ptr, ty)
|
||||
self.context.new_cast(None, ptr, ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
let global = self.declare_global(
|
||||
sym,
|
||||
gcc_type,
|
||||
GlobalKind::Exported,
|
||||
GlobalKind::Imported,
|
||||
is_tls,
|
||||
fn_attrs.link_section,
|
||||
);
|
||||
@ -404,7 +404,6 @@ fn check_and_apply_linkage<'gcc, 'tcx>(
|
||||
// TODO(antoyo): set linkage.
|
||||
let value = cx.const_ptrcast(global1.get_address(None), gcc_type);
|
||||
global2.global_set_initializer_rvalue(value);
|
||||
// TODO(antoyo): use global_set_initializer() when it will work.
|
||||
global2
|
||||
} else {
|
||||
// Generate an external declaration.
|
||||
|
@ -386,6 +386,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
|
||||
type Value = RValue<'gcc>;
|
||||
type Metadata = RValue<'gcc>;
|
||||
// TODO(antoyo): change to Function<'gcc>.
|
||||
type Function = RValue<'gcc>;
|
||||
|
||||
type BasicBlock = Block<'gcc>;
|
||||
|
@ -40,10 +40,6 @@ pub(crate) enum PossibleFeature<'a> {
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_lto_not_supported)]
|
||||
pub(crate) struct LTONotSupported;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_unwinding_inline_asm)]
|
||||
pub(crate) struct UnwindingInlineAsm {
|
||||
|
@ -66,16 +66,14 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
||||
// We do the equivalent above in `target_features_cfg`.
|
||||
// See <https://github.com/rust-lang/rust/issues/134792>.
|
||||
all_rust_features.push((false, feature));
|
||||
} else if !feature.is_empty() {
|
||||
if diagnostics {
|
||||
sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature });
|
||||
}
|
||||
} else if !feature.is_empty() && diagnostics {
|
||||
sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature });
|
||||
}
|
||||
}
|
||||
// Remove features that are meant for rustc, not codegen.
|
||||
all_rust_features.retain(|(_, feature)| {
|
||||
all_rust_features.retain(|&(_, feature)| {
|
||||
// Retain if it is not a rustc feature
|
||||
!RUSTC_SPECIFIC_FEATURES.contains(feature)
|
||||
!RUSTC_SPECIFIC_FEATURES.contains(&feature)
|
||||
});
|
||||
|
||||
// Check feature validity.
|
||||
@ -103,7 +101,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
||||
};
|
||||
sess.dcx().emit_warn(unknown_feature);
|
||||
}
|
||||
Some((_, stability, _)) => {
|
||||
Some(&(_, stability, _)) => {
|
||||
if let Err(reason) = stability.toggle_allowed() {
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature {
|
||||
feature,
|
||||
@ -165,29 +163,25 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
||||
);
|
||||
|
||||
// Translate this into GCC features.
|
||||
let feats = all_rust_features
|
||||
.iter()
|
||||
.filter_map(|&(enable, feature)| {
|
||||
let feats =
|
||||
all_rust_features.iter().flat_map(|&(enable, feature)| {
|
||||
let enable_disable = if enable { '+' } else { '-' };
|
||||
// We run through `to_gcc_features` when
|
||||
// passing requests down to GCC. This means that all in-language
|
||||
// features also work on the command line instead of having two
|
||||
// different names when the GCC name and the Rust name differ.
|
||||
Some(
|
||||
to_gcc_features(sess, feature)
|
||||
.iter()
|
||||
.flat_map(|feat| to_gcc_features(sess, feat).into_iter())
|
||||
.map(|feature| {
|
||||
if enable_disable == '-' {
|
||||
format!("-{}", feature)
|
||||
} else {
|
||||
feature.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
.flatten();
|
||||
to_gcc_features(sess, feature)
|
||||
.iter()
|
||||
.flat_map(|feat| to_gcc_features(sess, feat).into_iter())
|
||||
.map(|feature| {
|
||||
if enable_disable == '-' {
|
||||
format!("-{}", feature)
|
||||
} else {
|
||||
feature.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
features.extend(feats);
|
||||
|
||||
if diagnostics {
|
||||
|
@ -90,7 +90,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if a_type.is_vector() && a_type.is_vector() {
|
||||
} else if a_type.is_vector() && b_type.is_vector() {
|
||||
a >> b
|
||||
} else if a_native && !b_native {
|
||||
self.gcc_lshr(a, self.gcc_int_cast(b, a_type))
|
||||
@ -660,7 +660,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if a_type.is_vector() && a_type.is_vector() {
|
||||
} else if a_type.is_vector() && b_type.is_vector() {
|
||||
a << b
|
||||
} else if a_native && !b_native {
|
||||
self.gcc_shl(a, self.gcc_int_cast(b, a_type))
|
||||
|
@ -421,7 +421,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
|
||||
| "__builtin_ia32_xsaveopt64" => {
|
||||
let new_args = args.to_vec();
|
||||
let thirty_two = builder.context.new_rvalue_from_int(new_args[1].get_type(), 32);
|
||||
let arg2 = new_args[1] << thirty_two | new_args[2];
|
||||
let arg2 = (new_args[1] << thirty_two) | new_args[2];
|
||||
let arg2_type = gcc_func.get_param_type(1);
|
||||
let arg2 = builder.context.new_cast(None, arg2, arg2_type);
|
||||
args = vec![new_args[0], arg2].into();
|
||||
|
@ -13,15 +13,16 @@ use rustc_codegen_ssa::common::IntPredicate;
|
||||
use rustc_codegen_ssa::errors::InvalidMonomorphization;
|
||||
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
||||
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
||||
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_codegen_ssa::traits::MiscCodegenMethods;
|
||||
use rustc_codegen_ssa::traits::{
|
||||
ArgAbiBuilderMethods, BuilderMethods, ConstCodegenMethods, IntrinsicCallBuilderMethods,
|
||||
};
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, MiscCodegenMethods};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_target::abi::HasDataLayout;
|
||||
@ -139,6 +140,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
|
||||
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
sym::fmaf16 => {
|
||||
// TODO(antoyo): use the correct builtin for f16.
|
||||
let func = self.cx.context.get_builtin_function("fmaf");
|
||||
let args: Vec<_> = args
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
self.cx.context.new_cast(self.location, arg.immediate(), self.cx.type_f32())
|
||||
})
|
||||
.collect();
|
||||
let result = self.cx.context.new_call(self.location, func, &args);
|
||||
self.cx.context.new_cast(self.location, result, self.cx.type_f16())
|
||||
}
|
||||
sym::is_val_statically_known => {
|
||||
let a = args[0].immediate();
|
||||
let builtin = self.context.get_builtin_function("__builtin_constant_p");
|
||||
|
@ -379,7 +379,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
// Make sure this is actually a SIMD vector.
|
||||
let idx_ty = args[2].layout.ty;
|
||||
let n: u64 = if idx_ty.is_simd()
|
||||
&& matches!(idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), ty::Uint(ty::UintTy::U32))
|
||||
&& matches!(*idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), ty::Uint(ty::UintTy::U32))
|
||||
{
|
||||
idx_ty.simd_size_and_type(bx.cx.tcx).0
|
||||
} else {
|
||||
@ -829,6 +829,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||
| sym::simd_flog
|
||||
| sym::simd_floor
|
||||
| sym::simd_fma
|
||||
| sym::simd_relaxed_fma
|
||||
| sym::simd_fpow
|
||||
| sym::simd_fpowi
|
||||
| sym::simd_fsin
|
||||
|
@ -27,6 +27,8 @@
|
||||
// Some "regular" crates we want to share with rustc
|
||||
extern crate object;
|
||||
extern crate smallvec;
|
||||
// FIXME(antoyo): clippy bug: remove the #[allow] when it's fixed.
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate tempfile;
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
@ -88,7 +90,6 @@ use std::sync::atomic::Ordering;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use back::lto::{ThinBuffer, ThinData};
|
||||
use errors::LTONotSupported;
|
||||
use gccjit::{CType, Context, OptimizationLevel};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{TargetInfo, Version};
|
||||
@ -109,9 +110,10 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::util::Providers;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{Lto, OptLevel, OutputFilenames};
|
||||
use rustc_session::config::{OptLevel, OutputFilenames};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::fatal_error::FatalError;
|
||||
use rustc_target::spec::RelocModel;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use crate::back::lto::ModuleBuffer;
|
||||
@ -141,11 +143,15 @@ impl TargetInfo {
|
||||
false
|
||||
}
|
||||
|
||||
fn supports_128bit_int(&self) -> bool {
|
||||
self.supports_128bit_integers.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
fn supports_target_dependent_type(&self, _typ: CType) -> bool {
|
||||
fn supports_target_dependent_type(&self, typ: CType) -> bool {
|
||||
match typ {
|
||||
CType::UInt128t | CType::Int128t => {
|
||||
if self.supports_128bit_integers.load(Ordering::SeqCst) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -166,10 +172,6 @@ impl LockedTargetInfo {
|
||||
self.info.lock().expect("lock").cpu_supports(feature)
|
||||
}
|
||||
|
||||
fn supports_128bit_int(&self) -> bool {
|
||||
self.info.lock().expect("lock").supports_128bit_int()
|
||||
}
|
||||
|
||||
fn supports_target_dependent_type(&self, typ: CType) -> bool {
|
||||
self.info.lock().expect("lock").supports_target_dependent_type(typ)
|
||||
}
|
||||
@ -202,10 +204,6 @@ impl CodegenBackend for GccCodegenBackend {
|
||||
#[cfg(feature = "master")]
|
||||
gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
|
||||
|
||||
if sess.lto() == Lto::Thin {
|
||||
sess.dcx().emit_warn(LTONotSupported {});
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "master"))]
|
||||
{
|
||||
let temp_dir = TempDir::new().expect("cannot create temporary directory");
|
||||
@ -297,6 +295,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
|
||||
) -> Self::Module {
|
||||
let mut mods = GccContext {
|
||||
context: Arc::new(SyncContext::new(new_context(tcx))),
|
||||
relocation_model: tcx.sess.relocation_model(),
|
||||
should_combine_object_files: false,
|
||||
temp_dir: None,
|
||||
};
|
||||
@ -328,6 +327,9 @@ impl ExtraBackendMethods for GccCodegenBackend {
|
||||
|
||||
pub struct GccContext {
|
||||
context: Arc<SyncContext>,
|
||||
/// This field is needed in order to be able to set the flag -fPIC when necessary when doing
|
||||
/// LTO.
|
||||
relocation_model: RelocModel,
|
||||
should_combine_object_files: bool,
|
||||
// Temporary directory used by LTO. We keep it here so that it's not removed before linking.
|
||||
temp_dir: Option<TempDir>,
|
||||
@ -492,10 +494,10 @@ fn target_features_cfg(
|
||||
sess.target
|
||||
.rust_target_features()
|
||||
.iter()
|
||||
.filter(|(_, gate, _)| gate.in_cfg())
|
||||
.filter_map(|(feature, gate, _)| {
|
||||
.filter(|&&(_, gate, _)| gate.in_cfg())
|
||||
.filter_map(|&(feature, gate, _)| {
|
||||
if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() {
|
||||
Some(*feature)
|
||||
Some(feature)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
tests/ui/issues/issue-44056.rs
|
||||
tests/ui/lto/fat-lto.rs
|
||||
tests/ui/lto/debuginfo-lto.rs
|
||||
tests/ui/lto/lto-many-codegen-units.rs
|
||||
tests/ui/lto/issue-100772.rs
|
||||
tests/ui/lto/lto-rustc-loads-linker-plugin.rs
|
||||
tests/ui/panic-runtime/lto-unwind.rs
|
||||
tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs
|
||||
tests/ui/sepcomp/sepcomp-lib-lto.rs
|
||||
tests/ui/lto/lto-opt-level-s.rs
|
||||
tests/ui/lto/lto-opt-level-z.rs
|
@ -69,20 +69,22 @@ tests/ui/mir/mir_heavy_promoted.rs
|
||||
tests/ui/consts/const_cmp_type_id.rs
|
||||
tests/ui/consts/issue-73976-monomorphic.rs
|
||||
tests/ui/consts/issue-94675.rs
|
||||
tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs
|
||||
tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs
|
||||
tests/ui/traits/const-traits/const-drop-fail.rs
|
||||
tests/ui/traits/const-traits/const-drop.rs
|
||||
tests/ui/runtime/on-broken-pipe/child-processes.rs
|
||||
tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs
|
||||
tests/ui/sanitizer/cfi-async-closures.rs
|
||||
tests/ui/sanitizer/cfi-closures.rs
|
||||
tests/ui/sanitizer/cfi-complex-receiver.rs
|
||||
tests/ui/sanitizer/cfi-coroutine.rs
|
||||
tests/ui/sanitizer/cfi-drop-in-place.rs
|
||||
tests/ui/sanitizer/cfi-drop-no-principal.rs
|
||||
tests/ui/sanitizer/cfi-fn-ptr.rs
|
||||
tests/ui/sanitizer/cfi-self-ref.rs
|
||||
tests/ui/sanitizer/cfi-supertraits.rs
|
||||
tests/ui/sanitizer/cfi-virtual-auto.rs
|
||||
tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs
|
||||
tests/ui/sanitizer/cfi/async-closures.rs
|
||||
tests/ui/sanitizer/cfi/closures.rs
|
||||
tests/ui/sanitizer/cfi/complex-receiver.rs
|
||||
tests/ui/sanitizer/cfi/coroutine.rs
|
||||
tests/ui/sanitizer/cfi/drop-in-place.rs
|
||||
tests/ui/sanitizer/cfi/drop-no-principal.rs
|
||||
tests/ui/sanitizer/cfi/fn-ptr.rs
|
||||
tests/ui/sanitizer/cfi/self-ref.rs
|
||||
tests/ui/sanitizer/cfi/supertraits.rs
|
||||
tests/ui/sanitizer/cfi/virtual-auto.rs
|
||||
tests/ui/sanitizer/cfi/sized-associated-ty.rs
|
||||
tests/ui/sanitizer/cfi/can-reveal-opaques.rs
|
||||
tests/ui/sanitizer/kcfi-mangling.rs
|
||||
tests/ui/statics/const_generics.rs
|
||||
tests/ui/backtrace/dylib-dep.rs
|
||||
@ -91,6 +93,7 @@ tests/ui/delegation/fn-header.rs
|
||||
tests/ui/consts/zst_no_llvm_alloc.rs
|
||||
tests/ui/consts/const-eval/parse_ints.rs
|
||||
tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
|
||||
tests/ui/simd/intrinsic/generic-as.rs
|
||||
tests/ui/backtrace/backtrace.rs
|
||||
tests/ui/lifetimes/tail-expr-lock-poisoning.rs
|
||||
tests/ui/runtime/rt-explody-panic-payloads.rs
|
||||
@ -118,5 +121,4 @@ 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/sanitizer/cfi-sized-associated-ty.rs
|
||||
tests/ui/sanitizer/cfi-can-reveal-opaques.rs
|
||||
tests/ui/simd/simd-bitmask-notpow2.rs
|
||||
|
@ -11,7 +11,6 @@ tests/ui/simd/array-type.rs
|
||||
tests/ui/simd/intrinsic/float-minmax-pass.rs
|
||||
tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
|
||||
tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs
|
||||
tests/ui/simd/intrinsic/generic-as.rs
|
||||
tests/ui/simd/intrinsic/generic-cast-pass.rs
|
||||
tests/ui/simd/intrinsic/generic-cast-pointer-width.rs
|
||||
tests/ui/simd/intrinsic/generic-comparison-pass.rs
|
||||
|
14
compiler/rustc_codegen_gcc/tests/hello-world/Cargo.lock
Normal file
14
compiler/rustc_codegen_gcc/tests/hello-world/Cargo.lock
Normal file
@ -0,0 +1,14 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "hello_world"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"mylib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mylib"
|
||||
version = "0.1.0"
|
@ -1,4 +1,12 @@
|
||||
[package]
|
||||
name = "hello_world"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
mylib = { path = "mylib" }
|
||||
|
||||
[profile.dev]
|
||||
lto = "thin"
|
||||
|
||||
[profile.release]
|
||||
lto = "fat"
|
||||
|
@ -0,0 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "mylib"
|
||||
version = "0.1.0"
|
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "mylib"
|
||||
version = "0.1.0"
|
||||
authors = ["Antoni Boucher <bouanto@zoho.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
@ -0,0 +1,7 @@
|
||||
pub fn my_func(a: i32, b: i32) -> i32 {
|
||||
let mut res = a;
|
||||
for i in a..b {
|
||||
res += i;
|
||||
}
|
||||
res
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
use mylib::my_func;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
println!("{}", my_func(5, 10));
|
||||
}
|
||||
|
@ -22,14 +22,20 @@ pub fn main_inner(profile: Profile) {
|
||||
let tempdir = TempDir::new().expect("temp dir");
|
||||
let current_dir = current_dir().expect("current dir");
|
||||
let current_dir = current_dir.to_str().expect("current dir").to_string();
|
||||
let toml = Toml::parse(include_str!("../config.toml")).expect("Failed to parse `config.toml`");
|
||||
let gcc_path = if let Ok(gcc_path) = toml.get_string("gcc-path") {
|
||||
PathBuf::from(gcc_path.to_string())
|
||||
} else {
|
||||
// then we try to retrieve it from the `target` folder.
|
||||
let commit = include_str!("../libgccjit.version").trim();
|
||||
Path::new("build/libgccjit").join(commit)
|
||||
};
|
||||
|
||||
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||
|
||||
let gcc_path = std::fs::read_to_string(manifest_dir.join("config.toml"))
|
||||
.ok()
|
||||
.and_then(|v| {
|
||||
let toml = Toml::parse(&v).expect("Failed to parse `config.toml`");
|
||||
toml.get_string("gcc-path").map(PathBuf::from).ok()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
// then we try to retrieve it from the `target` folder.
|
||||
let commit = include_str!("../libgccjit.version").trim();
|
||||
Path::new("build/libgccjit").join(commit)
|
||||
});
|
||||
|
||||
let gcc_path = Path::new(&gcc_path)
|
||||
.canonicalize()
|
||||
@ -83,6 +89,8 @@ pub fn main_inner(profile: Profile) {
|
||||
&format!("{}/build/build_sysroot/sysroot/", current_dir),
|
||||
"-C",
|
||||
"link-arg=-lc",
|
||||
"--extern",
|
||||
"mini_core=target/out/libmini_core.rlib",
|
||||
"-o",
|
||||
exe.to_str().expect("to_str"),
|
||||
path.to_str().expect("to_str"),
|
||||
|
@ -7,38 +7,12 @@
|
||||
// 5
|
||||
// 10
|
||||
|
||||
#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
#![feature(no_core, start)]
|
||||
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
/*
|
||||
* Core
|
||||
*/
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {
|
||||
}
|
||||
|
||||
impl Copy for isize {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for u8 {}
|
||||
impl Copy for i8 {}
|
||||
impl Copy for i16 {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
extern crate mini_core;
|
||||
|
||||
mod libc {
|
||||
#[link(name = "c")]
|
||||
@ -48,182 +22,6 @@ mod libc {
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "index"]
|
||||
pub trait Index<Idx: ?Sized> {
|
||||
type Output: ?Sized;
|
||||
fn index(&self, index: Idx) -> &Self::Output;
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T; 3] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[lang = "panic"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
pub fn panic(_msg: &'static str) -> ! {
|
||||
unsafe {
|
||||
libc::puts("Panicking\0" as *const str as *const u8);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "panic_location"]
|
||||
struct PanicLocation {
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
#[lang = "panic_bounds_check"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
unsafe {
|
||||
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
mod intrinsics {
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub fn abort() -> ! {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
static mut ONE: usize = 1;
|
||||
|
||||
fn make_array() -> [u8; 3] {
|
||||
|
@ -8,200 +8,20 @@
|
||||
// Int argument: 2
|
||||
// Both args: 11
|
||||
|
||||
#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics,
|
||||
unboxed_closures, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
#![feature(no_core, start)]
|
||||
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
/*
|
||||
* Core
|
||||
*/
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {
|
||||
}
|
||||
|
||||
impl Copy for isize {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for u32 {}
|
||||
impl Copy for u8 {}
|
||||
impl Copy for i8 {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
extern crate mini_core;
|
||||
|
||||
mod libc {
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
pub fn puts(s: *const u8) -> i32;
|
||||
pub fn printf(format: *const i8, ...) -> i32;
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "index"]
|
||||
pub trait Index<Idx: ?Sized> {
|
||||
type Output: ?Sized;
|
||||
fn index(&self, index: Idx) -> &Self::Output;
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T; 3] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[lang = "panic_location"]
|
||||
struct PanicLocation {
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
#[lang = "panic_bounds_check"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
unsafe {
|
||||
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
mod intrinsics {
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub fn abort() -> ! {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "tuple_trait"]
|
||||
pub trait Tuple {}
|
||||
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
|
||||
#[lang = "fn_once"]
|
||||
#[rustc_paren_sugar]
|
||||
pub trait FnOnce<Args: Tuple> {
|
||||
#[lang = "fn_once_output"]
|
||||
type Output;
|
||||
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "fn_mut"]
|
||||
#[rustc_paren_sugar]
|
||||
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[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 = "panic"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
pub fn panic(_msg: &'static str) -> ! {
|
||||
unsafe {
|
||||
libc::puts("Panicking\0" as *const str as *const u8);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
#[lang = "panic_const_add_overflow"]
|
||||
pub fn panic_const_add_overflow() -> ! {
|
||||
panic("attempt to add with overflow");
|
||||
}
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
#[start]
|
||||
fn main(mut argc: isize, _argv: *const *const u8) -> isize {
|
||||
let string = "Arg: %d\n\0";
|
||||
|
@ -5,304 +5,20 @@
|
||||
// stdout: true
|
||||
// 1
|
||||
|
||||
#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
#![feature(no_core, start)]
|
||||
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
/*
|
||||
* Core
|
||||
*/
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {
|
||||
}
|
||||
|
||||
impl Copy for isize {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for u64 {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for u32 {}
|
||||
impl Copy for bool {}
|
||||
impl Copy for u16 {}
|
||||
impl Copy for i16 {}
|
||||
impl Copy for char {}
|
||||
impl Copy for i8 {}
|
||||
impl Copy for u8 {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "index"]
|
||||
pub trait Index<Idx: ?Sized> {
|
||||
type Output: ?Sized;
|
||||
fn index(&self, index: Idx) -> &Self::Output;
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T; 3] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[lang = "panic"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
pub fn panic(_msg: &'static str) -> ! {
|
||||
unsafe {
|
||||
libc::puts("Panicking\0" as *const str as *const u8);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "panic_location"]
|
||||
struct PanicLocation {
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
#[lang = "panic_bounds_check"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
unsafe {
|
||||
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
mod intrinsics {
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub fn abort() -> ! {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 = "eq"]
|
||||
pub trait PartialEq<Rhs: ?Sized = Self> {
|
||||
fn eq(&self, other: &Rhs) -> bool;
|
||||
fn ne(&self, other: &Rhs) -> bool;
|
||||
}
|
||||
|
||||
impl PartialEq for u8 {
|
||||
fn eq(&self, other: &u8) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &u8) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for u16 {
|
||||
fn eq(&self, other: &u16) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &u16) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for u32 {
|
||||
fn eq(&self, other: &u32) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &u32) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PartialEq for u64 {
|
||||
fn eq(&self, other: &u64) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &u64) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for usize {
|
||||
fn eq(&self, other: &usize) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &usize) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for i8 {
|
||||
fn eq(&self, other: &i8) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &i8) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for i32 {
|
||||
fn eq(&self, other: &i32) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &i32) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for isize {
|
||||
fn eq(&self, other: &isize) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &isize) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for char {
|
||||
fn eq(&self, other: &char) -> bool {
|
||||
(*self) == (*other)
|
||||
}
|
||||
fn ne(&self, other: &char) -> bool {
|
||||
(*self) != (*other)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
#[start]
|
||||
fn main(argc: isize, _argv: *const *const u8) -> isize {
|
||||
unsafe {
|
||||
|
@ -4,212 +4,20 @@
|
||||
// status: 0
|
||||
// stdout: 1
|
||||
|
||||
#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
#![feature(no_core, start)]
|
||||
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
/*
|
||||
* Core
|
||||
*/
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {
|
||||
}
|
||||
|
||||
impl Copy for isize {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for u8 {}
|
||||
impl Copy for i8 {}
|
||||
impl Copy for i16 {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "index"]
|
||||
pub trait Index<Idx: ?Sized> {
|
||||
type Output: ?Sized;
|
||||
fn index(&self, index: Idx) -> &Self::Output;
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T; 3] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[lang = "panic"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
pub fn panic(_msg: &'static str) -> ! {
|
||||
unsafe {
|
||||
libc::puts("Panicking\0" as *const str as *const u8);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "panic_location"]
|
||||
struct PanicLocation {
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
#[lang = "panic_bounds_check"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
unsafe {
|
||||
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
mod intrinsics {
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub fn abort() -> ! {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
fn i16_as_i8(a: i16) -> i8 {
|
||||
a as i8
|
||||
}
|
||||
|
@ -38,8 +38,8 @@ pub trait Deref {
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
#[lang = "legacy_receiver"]
|
||||
trait LegacyReceiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
|
@ -4,212 +4,20 @@
|
||||
// status: 0
|
||||
// stdout: 1
|
||||
|
||||
#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
#![feature(no_core, start)]
|
||||
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
/*
|
||||
* Core
|
||||
*/
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {
|
||||
}
|
||||
|
||||
impl Copy for isize {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for u8 {}
|
||||
impl Copy for i8 {}
|
||||
impl Copy for i16 {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "index"]
|
||||
pub trait Index<Idx: ?Sized> {
|
||||
type Output: ?Sized;
|
||||
fn index(&self, index: Idx) -> &Self::Output;
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T; 3] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[lang = "panic"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
pub fn panic(_msg: &'static str) -> ! {
|
||||
unsafe {
|
||||
libc::puts("Panicking\0" as *const str as *const u8);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "panic_location"]
|
||||
struct PanicLocation {
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
#[lang = "panic_bounds_check"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
unsafe {
|
||||
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
mod intrinsics {
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub fn abort() -> ! {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
static mut ONE: usize = 1;
|
||||
|
||||
fn make_array() -> [u8; 3] {
|
||||
|
@ -15,18 +15,18 @@
|
||||
#[lang = "copy"]
|
||||
pub unsafe trait Copy {}
|
||||
|
||||
unsafe impl Copy for bool {}
|
||||
unsafe impl Copy for u8 {}
|
||||
unsafe impl Copy for u16 {}
|
||||
unsafe impl Copy for u32 {}
|
||||
unsafe impl Copy for u64 {}
|
||||
unsafe impl Copy for usize {}
|
||||
unsafe impl Copy for i8 {}
|
||||
unsafe impl Copy for i16 {}
|
||||
unsafe impl Copy for i32 {}
|
||||
unsafe impl Copy for isize {}
|
||||
unsafe impl Copy for f32 {}
|
||||
unsafe impl Copy for char {}
|
||||
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")]
|
||||
@ -43,8 +43,8 @@ mod libc {
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
#[lang = "legacy_receiver"]
|
||||
trait LegacyReceiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
|
@ -4,36 +4,12 @@
|
||||
// status: 0
|
||||
// stdout: 5
|
||||
|
||||
#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)]
|
||||
#![allow(internal_features)]
|
||||
#![feature(no_core, start)]
|
||||
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
/*
|
||||
* Core
|
||||
*/
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {
|
||||
}
|
||||
|
||||
impl Copy for isize {}
|
||||
impl Copy for usize {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for u32 {}
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
|
||||
#[lang = "receiver"]
|
||||
trait Receiver {
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
extern crate mini_core;
|
||||
|
||||
mod libc {
|
||||
#[link(name = "c")]
|
||||
@ -42,79 +18,6 @@ mod libc {
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "index"]
|
||||
pub trait Index<Idx: ?Sized> {
|
||||
type Output: ?Sized;
|
||||
fn index(&self, index: Idx) -> &Self::Output;
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T; 3] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for [T] {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {}
|
||||
|
||||
#[lang = "coerce_unsized"]
|
||||
pub trait CoerceUnsized<T> {}
|
||||
|
||||
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
|
||||
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
#[lang = "panic_location"]
|
||||
struct PanicLocation {
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
#[lang = "panic_bounds_check"]
|
||||
#[track_caller]
|
||||
#[no_mangle]
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
unsafe {
|
||||
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
|
||||
intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
mod intrinsics {
|
||||
use super::Sized;
|
||||
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
pub fn abort() -> ! {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Code
|
||||
*/
|
||||
|
||||
static mut TWO: usize = 2;
|
||||
|
||||
fn index_slice(s: &[u32]) -> u32 {
|
||||
|
113
compiler/rustc_codegen_gcc/tests/run/volatile2.rs
Normal file
113
compiler/rustc_codegen_gcc/tests/run/volatile2.rs
Normal file
@ -0,0 +1,113 @@
|
||||
// Compiler:
|
||||
//
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
mod libc {
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
pub fn puts(s: *const u8) -> i32;
|
||||
|
||||
pub fn sigaction(signum: i32, act: *const sigaction, oldact: *mut sigaction) -> i32;
|
||||
pub fn mmap(addr: *mut (), len: usize, prot: i32, flags: i32, fd: i32, offset: i64) -> *mut ();
|
||||
pub fn mprotect(addr: *mut (), len: usize, prot: i32) -> i32;
|
||||
}
|
||||
|
||||
pub const PROT_READ: i32 = 1;
|
||||
pub const PROT_WRITE: i32 = 2;
|
||||
pub const MAP_PRIVATE: i32 = 0x0002;
|
||||
pub const MAP_ANONYMOUS: i32 = 0x0020;
|
||||
pub const MAP_FAILED: *mut u8 = !0 as *mut u8;
|
||||
|
||||
/// glibc sigaction
|
||||
#[repr(C)]
|
||||
pub struct sigaction {
|
||||
pub sa_sigaction: Option<unsafe extern "C" fn(i32, *mut (), *mut ())>,
|
||||
pub sa_mask: [u32; 32],
|
||||
pub sa_flags: i32,
|
||||
pub sa_restorer: Option<unsafe extern "C" fn()>,
|
||||
}
|
||||
|
||||
pub const SA_SIGINFO: i32 = 0x00000004;
|
||||
pub const SIGSEGV: i32 = 11;
|
||||
}
|
||||
|
||||
static mut COUNT: u32 = 0;
|
||||
static mut STORAGE: *mut u8 = core::ptr::null_mut();
|
||||
const PAGE_SIZE: usize = 1 << 15;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
// Register a segfault handler
|
||||
libc::sigaction(
|
||||
libc::SIGSEGV,
|
||||
&libc::sigaction {
|
||||
sa_sigaction: Some(segv_handler),
|
||||
sa_flags: libc::SA_SIGINFO,
|
||||
..core::mem::zeroed()
|
||||
},
|
||||
core::ptr::null_mut(),
|
||||
);
|
||||
|
||||
STORAGE = libc::mmap(
|
||||
core::ptr::null_mut(),
|
||||
PAGE_SIZE * 2,
|
||||
0,
|
||||
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
|
||||
-1,
|
||||
0,
|
||||
).cast();
|
||||
if STORAGE == libc::MAP_FAILED {
|
||||
panic!("error: mmap failed");
|
||||
}
|
||||
|
||||
let p_count = (&mut COUNT) as *mut u32;
|
||||
p_count.write_volatile(0);
|
||||
|
||||
// Trigger segfaults
|
||||
STORAGE.add(0).write_volatile(1);
|
||||
STORAGE.add(PAGE_SIZE).write_volatile(1);
|
||||
STORAGE.add(0).write_volatile(1);
|
||||
STORAGE.add(PAGE_SIZE).write_volatile(1);
|
||||
STORAGE.add(0).write_volatile(1);
|
||||
STORAGE.add(PAGE_SIZE).write_volatile(1);
|
||||
STORAGE.add(0).read_volatile();
|
||||
STORAGE.add(PAGE_SIZE).read_volatile();
|
||||
STORAGE.add(0).read_volatile();
|
||||
STORAGE.add(PAGE_SIZE).read_volatile();
|
||||
STORAGE.add(0).read_volatile();
|
||||
STORAGE.add(PAGE_SIZE).read_volatile();
|
||||
STORAGE.add(0).write_volatile(1);
|
||||
STORAGE.add(PAGE_SIZE).write_volatile(1);
|
||||
|
||||
// The segfault handler should have been called for every `write_volatile` and
|
||||
// `read_volatile` in `STORAGE`. If the compiler ignores volatility, some of these writes
|
||||
// will be combined, causing a different number of segfaults.
|
||||
//
|
||||
// This `p_count` read is done by a volatile read. If the compiler
|
||||
// ignores volatility, the compiler will speculate that `*p_count` is
|
||||
// unchanged and remove this check, failing the test.
|
||||
if p_count.read_volatile() != 14 {
|
||||
panic!("error: segfault count mismatch: {}", p_count.read_volatile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn segv_handler(_: i32, _: *mut (), _: *mut ()) {
|
||||
let p_count = (&mut COUNT) as *mut u32;
|
||||
p_count.write_volatile(p_count.read_volatile() + 1);
|
||||
let count = p_count.read_volatile();
|
||||
|
||||
// Toggle the protected page so that the handler will be called for
|
||||
// each `write_volatile`
|
||||
libc::mprotect(
|
||||
STORAGE.cast(),
|
||||
PAGE_SIZE,
|
||||
if count % 2 == 1 { libc::PROT_READ | libc::PROT_WRITE } else { 0 },
|
||||
);
|
||||
libc::mprotect(
|
||||
STORAGE.add(PAGE_SIZE).cast(),
|
||||
PAGE_SIZE,
|
||||
if count % 2 == 0 { libc::PROT_READ | libc::PROT_WRITE } else { 0 },
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user