Merge pull request #255 from rust-lang/sync_from_rust_2023_feb_28_2

Sync from rust 2023 feb 28
This commit is contained in:
antoyo 2023-03-04 20:21:03 -05:00 committed by GitHub
commit 08a6d6e16b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 1124 additions and 869 deletions

View file

@ -108,14 +108,14 @@ jobs:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
- name: Cache rust repository
# We only clone the rust repository for rustc tests
if: ${{ contains(matrix.commands, 'rustc') }}
uses: actions/cache@v3
id: cache-rust-repository
with:
path: rust
key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
#- name: Cache rust repository
## We only clone the rust repository for rustc tests
#if: ${{ contains(matrix.commands, 'rustc') }}
#uses: actions/cache@v3
#id: cache-rust-repository
#with:
#path: rust
#key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
- name: Build
run: |

18
Cargo.lock generated
View file

@ -11,12 +11,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "ar"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -41,7 +35,7 @@ dependencies = [
[[package]]
name = "gccjit"
version = "1.0.0"
source = "git+https://github.com/antoyo/gccjit.rs#1bd270d0d130fe31807cfbe509ca095c082e5848"
source = "git+https://github.com/antoyo/gccjit.rs#eefb8c662d61477f34b7c32d26bcda5f1ef08432"
dependencies = [
"gccjit_sys",
]
@ -49,7 +43,7 @@ dependencies = [
[[package]]
name = "gccjit_sys"
version = "0.0.1"
source = "git+https://github.com/antoyo/gccjit.rs#1bd270d0d130fe31807cfbe509ca095c082e5848"
source = "git+https://github.com/antoyo/gccjit.rs#eefb8c662d61477f34b7c32d26bcda5f1ef08432"
dependencies = [
"libc 0.1.12",
]
@ -212,11 +206,9 @@ dependencies = [
name = "rustc_codegen_gcc"
version = "0.1.0"
dependencies = [
"ar",
"gccjit",
"lang_tester",
"smallvec",
"target-lexicon",
"tempfile",
]
@ -235,12 +227,6 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "target-lexicon"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d"
[[package]]
name = "tempfile"
version = "3.2.0"

View file

@ -28,9 +28,6 @@ gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
#gccjit = { path = "../gccjit.rs" }
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
target-lexicon = "0.10.0"
ar = "0.8.0"
[dev-dependencies]
lang_tester = "0.3.9"

View file

@ -13,17 +13,17 @@
// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values.
#[cfg(all(any(target_arch = "x86",
#[cfg(any(target_arch = "x86",
target_arch = "arm",
target_arch = "mips",
target_arch = "powerpc",
target_arch = "powerpc64")))]
target_arch = "powerpc64"))]
const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86_64",
#[cfg(any(target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "mips64",
target_arch = "s390x",
target_arch = "sparc64")))]
target_arch = "sparc64"))]
const MIN_ALIGN: usize = 16;
pub struct System;

View file

@ -17,6 +17,9 @@ pub trait Sized {}
#[lang = "destruct"]
pub trait Destruct {}
#[lang = "tuple_trait"]
pub trait Tuple {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
@ -396,7 +399,7 @@ pub struct PhantomData<T: ?Sized>;
#[lang = "fn_once"]
#[rustc_paren_sugar]
pub trait FnOnce<Args> {
pub trait FnOnce<Args: Tuple> {
#[lang = "fn_once_output"]
type Output;
@ -405,7 +408,7 @@ pub trait FnOnce<Args> {
#[lang = "fn_mut"]
#[rustc_paren_sugar]
pub trait FnMut<Args>: FnOnce<Args> {
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
@ -418,8 +421,8 @@ pub fn panic(_msg: &'static str) -> ! {
}
}
#[lang = "panic_no_unwind"]
fn panic_no_unwind() -> ! {
#[lang = "panic_cannot_unwind"]
fn panic_cannot_unwind() -> ! {
unsafe {
libc::puts("Panicking\n\0" as *const str as *const u8);
intrinsics::abort();
@ -531,16 +534,22 @@ pub mod intrinsics {
use crate::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
#[rustc_safe_intrinsic]
pub fn size_of<T>() -> usize;
pub fn size_of_val<T: ?Sized>(val: *const T) -> usize;
#[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
pub fn min_align_of_val<T: ?Sized>(val: *const T) -> usize;
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
pub fn transmute<T, U>(e: T) -> U;
pub fn ctlz_nonzero<T>(x: T) -> T;
#[rustc_safe_intrinsic]
pub fn needs_drop<T: ?Sized>() -> bool;
#[rustc_safe_intrinsic]
pub fn bitreverse<T>(x: T) -> T;
#[rustc_safe_intrinsic]
pub fn bswap<T>(x: T) -> T;
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
pub fn unreachable() -> !;

View file

@ -85,6 +85,7 @@ fn start<T: Termination + 'static>(
main: fn() -> T,
argc: isize,
argv: *const *const u8,
_sigpipe: u8,
) -> isize {
if argc == 3 {
unsafe { puts(*argv); }

View file

@ -1,60 +1,68 @@
src/test/ui/alloc-error/default-alloc-error-hook.rs
src/test/ui/allocator/custom-in-block.rs
src/test/ui/allocator/custom-in-submodule.rs
src/test/ui/allocator/custom.rs
src/test/ui/allocator/hygiene.rs
src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
src/test/ui/allocator/no_std-alloc-error-handler-default.rs
src/test/ui/allocator/xcrate-use.rs
src/test/ui/allocator/xcrate-use2.rs
src/test/ui/asm/may_unwind.rs
src/test/ui/asm/x86_64/multiple-clobber-abi.rs
src/test/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs
src/test/ui/functions-closures/parallel-codegen-closures.rs
src/test/ui/linkage-attr/linkage1.rs
src/test/ui/lto/dylib-works.rs
src/test/ui/numbers-arithmetic/saturating-float-casts.rs
src/test/ui/polymorphization/promoted-function.rs
src/test/ui/process/nofile-limit.rs
src/test/ui/sepcomp/sepcomp-cci.rs
src/test/ui/sepcomp/sepcomp-extern.rs
src/test/ui/sepcomp/sepcomp-fns-backwards.rs
src/test/ui/sepcomp/sepcomp-fns.rs
src/test/ui/sepcomp/sepcomp-statics.rs
src/test/ui/simd/intrinsic/generic-arithmetic-pass.rs
src/test/ui/sse2.rs
src/test/ui/target-feature/missing-plusminus.rs
src/test/ui/asm/x86_64/may_unwind.rs
src/test/ui/backtrace.rs
src/test/ui/catch-unwind-bang.rs
src/test/ui/cfg/cfg-panic-abort.rs
src/test/ui/drop/dynamic-drop-async.rs
src/test/ui/drop/repeat-drop.rs
src/test/ui/fmt/format-args-capture.rs
src/test/ui/generator/panic-drops-resume.rs
src/test/ui/generator/panic-drops.rs
src/test/ui/generator/panic-safe.rs
src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
src/test/ui/iterators/iter-sum-overflow-debug.rs
src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
src/test/ui/mir/mir_calls_to_shims.rs
src/test/ui/mir/mir_drop_order.rs
src/test/ui/mir/mir_let_chains_drop_order.rs
src/test/ui/oom_unwind.rs
src/test/ui/panic-runtime/abort-link-to-unwinding-crates.rs
src/test/ui/panic-runtime/abort.rs
src/test/ui/panic-runtime/link-to-abort.rs
src/test/ui/unwind-no-uwtable.rs
src/test/ui/issues/issue-14875.rs
src/test/ui/issues/issue-29948.rs
src/test/ui/issues/issue-40883.rs
src/test/ui/issues/issue-43853.rs
src/test/ui/issues/issue-47364.rs
src/test/ui/simd/issue-17170.rs
src/test/ui/simd/issue-39720.rs
src/test/ui/simd/issue-89193.rs
src/test/ui/statics/issue-91050-1.rs
src/test/ui/statics/issue-91050-2.rs
src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
src/test/ui/rfcs/rfc1857-drop-order.rs
tests/ui/allocator/custom-in-block.rs
tests/ui/allocator/custom-in-submodule.rs
tests/ui/allocator/custom.rs
tests/ui/allocator/hygiene.rs
tests/ui/allocator/no_std-alloc-error-handler-custom.rs
tests/ui/allocator/no_std-alloc-error-handler-default.rs
tests/ui/allocator/xcrate-use.rs
tests/ui/allocator/xcrate-use2.rs
tests/ui/asm/may_unwind.rs
tests/ui/asm/x86_64/multiple-clobber-abi.rs
tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs
tests/ui/functions-closures/parallel-codegen-closures.rs
tests/ui/linkage-attr/linkage1.rs
tests/ui/lto/dylib-works.rs
tests/ui/numbers-arithmetic/saturating-float-casts.rs
tests/ui/polymorphization/promoted-function.rs
tests/ui/process/nofile-limit.rs
tests/ui/sepcomp/sepcomp-cci.rs
tests/ui/sepcomp/sepcomp-extern.rs
tests/ui/sepcomp/sepcomp-fns-backwards.rs
tests/ui/sepcomp/sepcomp-fns.rs
tests/ui/sepcomp/sepcomp-statics.rs
tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
tests/ui/sse2.rs
tests/ui/target-feature/missing-plusminus.rs
tests/ui/asm/x86_64/may_unwind.rs
tests/ui/backtrace.rs
tests/ui/catch-unwind-bang.rs
tests/ui/cfg/cfg-panic-abort.rs
tests/ui/drop/dynamic-drop-async.rs
tests/ui/drop/repeat-drop.rs
tests/ui/fmt/format-args-capture.rs
tests/ui/generator/panic-drops-resume.rs
tests/ui/generator/panic-drops.rs
tests/ui/intrinsics/panic-uninitialized-zeroed.rs
tests/ui/iterators/iter-sum-overflow-debug.rs
tests/ui/iterators/iter-sum-overflow-overflow-checks.rs
tests/ui/mir/mir_calls_to_shims.rs
tests/ui/mir/mir_drop_order.rs
tests/ui/mir/mir_let_chains_drop_order.rs
tests/ui/oom_unwind.rs
tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
tests/ui/panic-runtime/abort.rs
tests/ui/panic-runtime/link-to-abort.rs
tests/ui/unwind-no-uwtable.rs
tests/ui/parser/unclosed-delimiter-in-dep.rs
tests/ui/runtime/rt-explody-panic-payloads.rs
tests/ui/simd/intrinsic/ptr-cast.rs
tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
tests/ui/consts/missing_span_in_backtrace.rs
tests/ui/drop/dynamic-drop.rs
tests/ui/dyn-star/box.rs
tests/ui/issues/issue-40883.rs
tests/ui/issues/issue-43853.rs
tests/ui/issues/issue-47364.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
tests/ui/rfc-2091-track-caller/std-panic-locations.rs
tests/ui/rfcs/rfc1857-drop-order.rs
tests/ui/simd/issue-17170.rs
tests/ui/simd/issue-39720.rs
tests/ui/simd/issue-89193.rs
tests/ui/statics/issue-91050-1.rs
tests/ui/statics/issue-91050-2.rs
tests/ui/alloc-error/default-alloc-error-hook.rs
tests/ui/generator/panic-safe.rs
tests/ui/issues/issue-14875.rs
tests/ui/issues/issue-29948.rs
tests/ui/panic-while-printing.rs

View file

@ -1,41 +1,39 @@
src/test/ui/asm/x86_64/issue-96797.rs
src/test/ui/intrinsics/const-eval-select-x86_64.rs
src/test/ui/packed/packed-struct-drop-aligned.rs
src/test/ui/packed/packed-struct-generic-layout.rs
src/test/ui/packed/packed-struct-layout.rs
src/test/ui/packed/packed-struct-optimized-enum.rs
src/test/ui/packed/packed-struct-size.rs
src/test/ui/packed/packed-struct-vec.rs
src/test/ui/packed/packed-tuple-struct-layout.rs
src/test/ui/simd/array-type.rs
src/test/ui/simd/intrinsic/float-minmax-pass.rs
src/test/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs
src/test/ui/simd/intrinsic/generic-as.rs
src/test/ui/simd/intrinsic/generic-cast-pass.rs
src/test/ui/simd/intrinsic/generic-cast-pointer-width.rs
src/test/ui/simd/intrinsic/generic-comparison-pass.rs
src/test/ui/simd/intrinsic/generic-elements-pass.rs
src/test/ui/simd/intrinsic/generic-reduction-pass.rs
src/test/ui/simd/intrinsic/generic-select-pass.rs
src/test/ui/simd/intrinsic/inlining-issue67557-ice.rs
src/test/ui/simd/intrinsic/inlining-issue67557.rs
src/test/ui/simd/monomorphize-shuffle-index.rs
src/test/ui/simd/shuffle.rs
src/test/ui/simd/simd-bitmask.rs
src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
src/test/ui/drop/dynamic-drop.rs
src/test/ui/generator/resume-after-return.rs
src/test/ui/iterators/iter-step-overflow-debug.rs
src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
src/test/ui/panic-while-printing.rs
src/test/ui/privacy/reachable-unnameable-items.rs
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
src/test/ui/async-await/async-fn-size-moved-locals.rs
src/test/ui/async-await/async-fn-size-uninit-locals.rs
src/test/ui/cfg/cfg-panic.rs
src/test/ui/generator/size-moved-locals.rs
src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
src/test/ui/runtime/rt-explody-panic-payloads.rs
src/test/ui/simd/intrinsic/generic-gather-pass.rs
src/test/ui/simd/issue-85915-simd-ptrs.rs
tests/ui/asm/x86_64/issue-96797.rs
tests/ui/intrinsics/const-eval-select-x86_64.rs
tests/ui/packed/packed-struct-drop-aligned.rs
tests/ui/packed/packed-struct-generic-layout.rs
tests/ui/packed/packed-struct-layout.rs
tests/ui/packed/packed-struct-optimized-enum.rs
tests/ui/packed/packed-struct-size.rs
tests/ui/packed/packed-struct-vec.rs
tests/ui/packed/packed-tuple-struct-layout.rs
tests/ui/simd/array-type.rs
tests/ui/simd/intrinsic/float-minmax-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
tests/ui/simd/intrinsic/generic-elements-pass.rs
tests/ui/simd/intrinsic/generic-reduction-pass.rs
tests/ui/simd/intrinsic/generic-select-pass.rs
tests/ui/simd/intrinsic/inlining-issue67557-ice.rs
tests/ui/simd/intrinsic/inlining-issue67557.rs
tests/ui/simd/monomorphize-shuffle-index.rs
tests/ui/simd/shuffle.rs
tests/ui/simd/simd-bitmask.rs
tests/ui/generator/resume-after-return.rs
tests/ui/iterators/iter-step-overflow-debug.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
tests/ui/privacy/reachable-unnameable-items.rs
tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
tests/ui/async-await/async-fn-size-moved-locals.rs
tests/ui/async-await/async-fn-size-uninit-locals.rs
tests/ui/cfg/cfg-panic.rs
tests/ui/generator/size-moved-locals.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
tests/ui/simd/intrinsic/generic-gather-pass.rs
tests/ui/simd/issue-85915-simd-ptrs.rs
tests/ui/issues/issue-68010-large-zst-consts.rs
tests/ui/rust-2018/proc-macro-crate-in-paths.rs

65
locales/en-US.ftl Normal file
View file

@ -0,0 +1,65 @@
codegen_gcc_unwinding_inline_asm =
GCC backend does not support unwinding from inline asm
codegen_gcc_lto_not_supported =
LTO is not supported. You may get a linker error.
codegen_gcc_invalid_monomorphization_basic_integer =
invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
codegen_gcc_invalid_monomorphization_invalid_float_vector =
invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
codegen_gcc_invalid_monomorphization_not_float =
invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
codegen_gcc_invalid_monomorphization_unrecognized =
invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
codegen_gcc_invalid_monomorphization_expected_signed_unsigned =
invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type
codegen_gcc_invalid_monomorphization_unsupported_element =
invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
codegen_gcc_invalid_monomorphization_invalid_bitmask =
invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
codegen_gcc_invalid_monomorphization_simd_shuffle =
invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
codegen_gcc_invalid_monomorphization_expected_simd =
invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
codegen_gcc_invalid_monomorphization_mask_type =
invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
codegen_gcc_invalid_monomorphization_return_length =
invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
codegen_gcc_invalid_monomorphization_return_length_input_type =
invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
codegen_gcc_invalid_monomorphization_return_element =
invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
codegen_gcc_invalid_monomorphization_return_type =
invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
codegen_gcc_invalid_monomorphization_inserted_type =
invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
codegen_gcc_invalid_monomorphization_return_integer_type =
invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
codegen_gcc_invalid_monomorphization_mismatched_lengths =
invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
codegen_gcc_invalid_monomorphization_unsupported_cast =
invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
codegen_gcc_invalid_monomorphization_unsupported_operation =
invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
codegen_gcc_invalid_minimum_alignment =
invalid minimum global alignment: {$err}

View file

@ -18,7 +18,7 @@ new file mode 100644
index 0000000..46fd999
--- /dev/null
+++ b/library/core/tests/Cargo.toml
@@ -0,0 +1,8 @@
@@ -0,0 +1,12 @@
+[package]
+name = "core"
+version = "0.0.0"
@ -27,37 +27,18 @@ index 0000000..46fd999
+[lib]
+name = "coretests"
+path = "lib.rs"
diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs
index a35897e..f0bf645 100644
--- a/library/core/tests/num/flt2dec/mod.rs
+++ b/library/core/tests/num/flt2dec/mod.rs
@@ -13,7 +13,6 @@ mod strategy {
mod dragon;
mod grisu;
}
-mod random;
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
match decode(v).1 {
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 6609bc3..241b497 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -1209,6 +1209,7 @@ fn brute_force_rotate_test_1() {
}
}
+/*
#[test]
#[cfg(not(target_arch = "wasm32"))]
fn sort_unstable() {
@@ -1394,6 +1395,7 @@ fn partition_at_index() {
v.select_nth_unstable(0);
assert!(v == [0xDEADBEEF]);
}
+*/
#[test]
#[should_panic(expected = "index 0 greater than length of slice")]
+
+[dependencies]
+rand = { version = "0.8.5", default-features = false }
+rand_xorshift = { version = "0.3.0", default-features = false }
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 42a26ae..5ac1042 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,3 +1,4 @@
+#![cfg(test)]
#![feature(alloc_layout_extra)]
#![feature(array_chunks)]
#![feature(array_methods)]
--
2.21.0 (Apple Git-122)

View file

@ -1,32 +0,0 @@
From f845df4056f5ba16b9f5bd703460c4ac40ea03b9 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Fri, 26 Aug 2022 20:38:58 -0400
Subject: [PATCH] Edit
---
library/core/tests/lib.rs | 2 --
1 file changed, 2 deletions(-)
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 59510d3..179bf26 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -77,7 +77,6 @@
#![feature(unwrap_infallible)]
#![feature(result_into_ok_or_err)]
#![feature(pointer_byte_offsets)]
-#![feature(portable_simd)]
#![feature(ptr_metadata)]
#![feature(once_cell)]
#![feature(option_result_contains)]
@@ -135,7 +134,6 @@ mod pin;
mod pin_macro;
mod ptr;
mod result;
-mod simd;
mod slice;
mod str;
mod str_lossy;
--
2.26.2.7.g19db9cfb68.dirty

View file

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2022-08-26"
channel = "nightly-2023-03-02"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -11,10 +11,6 @@ use crate::intrinsic::ArgAbiExt;
use crate::type_of::LayoutGccExt;
impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
fn apply_attrs_callsite(&mut self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _callsite: Self::Value) {
// TODO(antoyo)
}
fn get_param(&mut self, index: usize) -> Self::Value {
let func = self.current_func();
let param = func.get_param(index as i32);
@ -107,45 +103,24 @@ pub trait FnAbiGccExt<'gcc, 'tcx> {
impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) {
let mut on_stack_param_indices = FxHashSet::default();
let args_capacity: usize = self.args.iter().map(|arg|
if arg.pad.is_some() {
1
}
else {
0
} +
if let PassMode::Pair(_, _) = arg.mode {
2
} else {
1
}
).sum();
// This capacity calculation is approximate.
let mut argument_tys = Vec::with_capacity(
if let PassMode::Indirect { .. } = self.ret.mode {
1
}
else {
0
} + args_capacity,
self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 }
);
let return_ty =
match self.ret.mode {
PassMode::Ignore => cx.type_void(),
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
PassMode::Cast(cast) => cast.gcc_type(cx),
PassMode::Cast(ref cast, _) => cast.gcc_type(cx),
PassMode::Indirect { .. } => {
argument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
cx.type_void()
}
};
for arg in &self.args {
// add padding
if let Some(ty) = arg.pad {
argument_tys.push(ty.gcc_type(cx));
}
for arg in self.args.iter() {
let arg_ty = match arg.mode {
PassMode::Ignore => continue,
PassMode::Direct(_) => arg.layout.immediate_gcc_type(cx),
@ -157,7 +132,13 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
PassMode::Indirect { extra_attrs: Some(_), .. } => {
unimplemented!();
}
PassMode::Cast(cast) => cast.gcc_type(cx),
PassMode::Cast(ref cast, pad_i32) => {
// add padding
if pad_i32 {
argument_tys.push(Reg::i32().gcc_type(cx));
}
cast.gcc_type(cx)
}
PassMode::Indirect { extra_attrs: None, on_stack: true, .. } => {
on_stack_param_indices.insert(argument_tys.len());
arg.memory_ty(cx)

View file

@ -9,7 +9,7 @@ use rustc_span::symbol::sym;
use crate::GccContext;
pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) {
pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) {
let context = &mods.context;
let usize =
match tcx.sess.target.pointer_width {
@ -99,14 +99,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
}
let kind =
if has_alloc_error_handler {
AllocatorKind::Global
}
else {
AllocatorKind::Default
};
let callee = kind.fn_name(sym::oom);
let callee = alloc_error_handler_kind.fn_name(sym::oom);
let args: Vec<_> = types.iter().enumerate()
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
.collect();

View file

@ -1,42 +1,17 @@
use std::fs::File;
use std::path::{Path, PathBuf};
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use rustc_codegen_ssa::back::archive::{
get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
};
use rustc_session::Session;
use rustc_session::cstore::DllImport;
struct ArchiveConfig<'a> {
sess: &'a Session,
use_native_ar: bool,
use_gnu_style_archive: bool,
}
#[derive(Debug)]
enum ArchiveEntry {
FromArchive {
archive_index: usize,
entry_index: usize,
},
File(PathBuf),
}
pub struct ArArchiveBuilderBuilder;
pub(crate) struct ArArchiveBuilderBuilder;
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
let config = ArchiveConfig {
sess,
use_native_ar: false,
// FIXME test for linux and System V derivatives instead
use_gnu_style_archive: sess.target.options.archive_format == "gnu",
};
Box::new(ArArchiveBuilder {
config,
src_archives: vec![],
entries: vec![],
})
Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols))
}
fn create_dll_import_lib(
@ -45,145 +20,8 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
_lib_name: &str,
_dll_imports: &[DllImport],
_tmpdir: &Path,
_is_direct_dependency: bool,
) -> PathBuf {
unimplemented!();
}
}
pub struct ArArchiveBuilder<'a> {
config: ArchiveConfig<'a>,
src_archives: Vec<(PathBuf, ar::Archive<File>)>,
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
// the end of an archive for linkers to not get confused.
entries: Vec<(String, ArchiveEntry)>,
}
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
fn add_file(&mut self, file: &Path) {
self.entries.push((
file.file_name().unwrap().to_str().unwrap().to_string(),
ArchiveEntry::File(file.to_owned()),
));
}
fn add_archive(
&mut self,
archive_path: &Path,
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> std::io::Result<()> {
let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
let archive_index = self.src_archives.len();
let mut i = 0;
while let Some(entry) = archive.next_entry() {
let entry = entry?;
let file_name = String::from_utf8(entry.header().identifier().to_vec())
.map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
if !skip(&file_name) {
self.entries
.push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
}
i += 1;
}
self.src_archives.push((archive_path.to_owned(), archive));
Ok(())
}
fn build(mut self: Box<Self>, output: &Path) -> bool {
use std::process::Command;
fn add_file_using_ar(archive: &Path, file: &Path) {
Command::new("ar")
.arg("r") // add or replace file
.arg("-c") // silence created file message
.arg(archive)
.arg(&file)
.status()
.unwrap();
}
enum BuilderKind<'a> {
Bsd(ar::Builder<File>),
Gnu(ar::GnuBuilder<File>),
NativeAr(&'a Path),
}
let mut builder = if self.config.use_native_ar {
BuilderKind::NativeAr(output)
} else if self.config.use_gnu_style_archive {
BuilderKind::Gnu(ar::GnuBuilder::new(
File::create(output).unwrap(),
self.entries
.iter()
.map(|(name, _)| name.as_bytes().to_vec())
.collect(),
))
} else {
BuilderKind::Bsd(ar::Builder::new(File::create(output).unwrap()))
};
let any_members = !self.entries.is_empty();
// Add all files
for (entry_name, entry) in self.entries.into_iter() {
match entry {
ArchiveEntry::FromArchive {
archive_index,
entry_index,
} => {
let (ref src_archive_path, ref mut src_archive) =
self.src_archives[archive_index];
let entry = src_archive.jump_to_entry(entry_index).unwrap();
let header = entry.header().clone();
match builder {
BuilderKind::Bsd(ref mut builder) => {
builder.append(&header, entry).unwrap()
}
BuilderKind::Gnu(ref mut builder) => {
builder.append(&header, entry).unwrap()
}
BuilderKind::NativeAr(archive_file) => {
Command::new("ar")
.arg("x")
.arg(src_archive_path)
.arg(&entry_name)
.status()
.unwrap();
add_file_using_ar(archive_file, Path::new(&entry_name));
std::fs::remove_file(entry_name).unwrap();
}
}
}
ArchiveEntry::File(file) =>
match builder {
BuilderKind::Bsd(ref mut builder) => {
builder
.append_file(entry_name.as_bytes(), &mut File::open(file).expect("file for bsd builder"))
.unwrap()
},
BuilderKind::Gnu(ref mut builder) => {
builder
.append_file(entry_name.as_bytes(), &mut File::open(&file).expect(&format!("file {:?} for gnu builder", file)))
.unwrap()
},
BuilderKind::NativeAr(archive_file) => add_file_using_ar(archive_file, &file),
},
}
}
// Finalize archive
std::mem::drop(builder);
// Run ranlib to be able to link the archive
let status =
std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib");
if !status.success() {
self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
}
any_members
unimplemented!("creating dll imports is not yet supported");
}
}

View file

@ -12,6 +12,7 @@ use std::borrow::Cow;
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::errors::UnwindingInlineAsm;
use crate::type_of::LayoutGccExt;
use crate::callee::get_fn;
@ -109,7 +110,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) {
if options.contains(InlineAsmOptions::MAY_UNWIND) {
self.sess()
.struct_span_err(span[0], "GCC backend does not support unwinding from inline asm")
.create_err(UnwindingInlineAsm { span: span[0] })
.emit();
return;
}
@ -500,7 +501,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
if options.contains(InlineAsmOptions::NORETURN) {
let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable");
let builtin_unreachable: RValue<'gcc> = unsafe { std::mem::transmute(builtin_unreachable) };
self.call(self.type_void(), builtin_unreachable, &[], None);
self.call(self.type_void(), None, builtin_unreachable, &[], None);
}
// Write results to outputs.

View file

@ -63,7 +63,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
}
}
pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64) {
pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64) {
let prof_timer = tcx.prof.generic_activity("codegen_module");
let start_time = Instant::now();

View file

@ -15,8 +15,11 @@ use gccjit::{
Type,
UnaryOp,
};
use rustc_apfloat::{ieee, Float, Round, Status};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope};
use rustc_codegen_ssa::common::{
AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{
@ -31,6 +34,7 @@ use rustc_codegen_ssa::traits::{
StaticBuilderMethods,
};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_span::Span;
@ -451,12 +455,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
#[cfg(feature="master")]
fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
fn invoke(&mut self, typ: Type<'gcc>, _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
let try_block = self.current_func().new_block("try");
let current_block = self.block.clone();
self.block = try_block;
let call = self.call(typ, func, args, None); // TODO(antoyo): use funclet here?
let call = self.call(typ, None, func, args, None); // TODO(antoyo): use funclet here?
self.block = current_block;
let return_value = self.current_func()
@ -479,10 +483,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
#[cfg(not(feature="master"))]
fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
let call_site = self.call(typ, func, args, None);
fn invoke(&mut self, typ: Type<'gcc>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
let call_site = self.call(typ, None, func, args, None);
let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
self.llbb().end_with_conditional(None, condition, then, catch);
if let Some(_fn_abi) = fn_abi {
// TODO(bjorn3): Apply function attributes
}
call_site
}
@ -707,11 +714,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
self.current_func().new_local(None, aligned_type, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None)
}
fn dynamic_alloca(&mut self, _ty: Type<'gcc>, _align: Align) -> RValue<'gcc> {
unimplemented!();
}
fn array_alloca(&mut self, _ty: Type<'gcc>, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
unimplemented!();
}
@ -765,7 +768,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
bx.range_metadata(load, vr);
}
}
abi::Pointer if vr.start < vr.end && !vr.contains(0) => {
abi::Pointer(_) if vr.start < vr.end && !vr.contains(0) => {
bx.nonnull_metadata(load);
}
_ => {}
@ -811,11 +814,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
OperandRef { val, layout: place.layout }
}
fn write_operand_repeatedly(mut self, cg_elem: OperandRef<'tcx, RValue<'gcc>>, count: u64, dest: PlaceRef<'tcx, RValue<'gcc>>) -> Self {
fn write_operand_repeatedly(&mut self, cg_elem: OperandRef<'tcx, RValue<'gcc>>, count: u64, dest: PlaceRef<'tcx, RValue<'gcc>>) {
let zero = self.const_usize(0);
let count = self.const_usize(count);
let start = dest.project_index(&mut self, zero).llval;
let end = dest.project_index(&mut self, count).llval;
let start = dest.project_index(self, zero).llval;
let end = dest.project_index(self, count).llval;
let header_bb = self.append_sibling_block("repeat_loop_header");
let body_bb = self.append_sibling_block("repeat_loop_body");
@ -834,14 +837,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
self.switch_to_block(body_bb);
let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
cg_elem.val.store(&mut self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align));
cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align));
let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[self.const_usize(1)]);
self.llbb().add_assignment(None, current, next);
self.br(header_bb);
self.switch_to_block(next_bb);
self
}
fn range_metadata(&mut self, _load: RValue<'gcc>, _range: WrappingRange) {
@ -1106,7 +1108,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
let vector_type = vec.get_type().unqualified().dyncast_vector().expect("Called extract_element on a non-vector type");
let element_type = vector_type.get_element_type();
let vec_num_units = vector_type.get_num_units();
let array_type = self.context.new_array_type(None, element_type, vec_num_units as i32);
let array_type = self.context.new_array_type(None, element_type, vec_num_units as u64);
let array = self.context.new_bitcast(None, vec, array_type).to_rvalue();
self.context.new_array_access(None, array, idx).to_rvalue()
}
@ -1197,7 +1199,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
#[cfg(feature="master")]
fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, pers_fn: RValue<'gcc>) -> RValue<'gcc> {
fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
self.set_personality_fn(pers_fn);
// NOTE: insert the current block in a variable so that a later call to invoke knows to
@ -1208,42 +1210,33 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
let zero = self.cx.context.new_rvalue_zero(self.int_type);
let ptr = self.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
let field1_type = self.u8_type.make_pointer();
let field1 = self.context.new_field(None, field1_type, "landing_pad_field_1");
let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_2");
let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
let value = self.current_func().new_local(None, struct_type.as_type(), "landing_pad");
let ptr = self.cx.context.new_cast(None, ptr, field1_type);
self.block.add_assignment(None, value.access_field(None, field1), ptr);
self.block.add_assignment(None, value.access_field(None, field2), zero); // TODO(antoyo): set the proper value here (the type of exception?).
let value1_type = self.u8_type.make_pointer();
let ptr = self.cx.context.new_cast(None, ptr, value1_type);
let value1 = ptr;
let value2 = zero; // TODO(antoyo): set the proper value here (the type of exception?).
value.to_rvalue()
(value1, value2)
}
#[cfg(not(feature="master"))]
fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
let field1 = self.context.new_field(None, self.u8_type.make_pointer(), "landing_pad_field_1");
let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
self.current_func().new_local(None, struct_type.as_type(), "landing_pad")
.to_rvalue()
fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
let value1 = self.current_func().new_local(None, self.u8_type.make_pointer(), "landing_pad0")
.to_rvalue();
let value2 = self.current_func().new_local(None, self.i32_type, "landing_pad1").to_rvalue();
(value1, value2)
}
#[cfg(feature="master")]
fn resume(&mut self, exn: RValue<'gcc>) {
// TODO(antoyo): check if this is normal that we need to dereference the value.
// NOTE: the type is wrong, so in order to get a pointer for parameter, cast it to a
// pointer of pointer that is later dereferenced.
let exn_type = exn.get_type().make_pointer();
let exn = self.context.new_cast(None, exn, exn_type);
let exn = exn.dereference(None).to_rvalue();
fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
let exn_type = exn0.get_type();
let exn = self.context.new_cast(None, exn0, exn_type);
let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume");
self.llbb().add_eval(None, self.context.new_call(None, unwind_resume, &[exn]));
self.unreachable();
}
#[cfg(not(feature="master"))]
fn resume(&mut self, _exn: RValue<'gcc>) {
fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
self.unreachable();
}
@ -1355,16 +1348,27 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
// TODO(antoyo)
}
fn call(&mut self, _typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], funclet: Option<&Funclet>) -> RValue<'gcc> {
fn call(
&mut self,
_typ: Type<'gcc>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
func: RValue<'gcc>,
args: &[RValue<'gcc>],
funclet: Option<&Funclet>,
) -> RValue<'gcc> {
// FIXME(antoyo): remove when having a proper API.
let gcc_func = unsafe { std::mem::transmute(func) };
if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() {
let call = if self.functions.borrow().values().any(|value| *value == gcc_func) {
self.function_call(func, args, funclet)
}
else {
// If it's a not function that was defined, it's a function pointer.
self.function_ptr_call(func, args, funclet)
};
if let Some(_fn_abi) = fn_abi {
// TODO(bjorn3): Apply function attributes
}
call
}
fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
@ -1403,12 +1407,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
val
}
fn fptoui_sat(&mut self, _val: RValue<'gcc>, _dest_ty: Type<'gcc>) -> Option<RValue<'gcc>> {
None
fn fptoui_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
self.fptoint_sat(false, val, dest_ty)
}
fn fptosi_sat(&mut self, _val: RValue<'gcc>, _dest_ty: Type<'gcc>) -> Option<RValue<'gcc>> {
None
fn fptosi_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
self.fptoint_sat(true, val, dest_ty)
}
fn instrprof_increment(&mut self, _fn_name: RValue<'gcc>, _hash: RValue<'gcc>, _num_counters: RValue<'gcc>, _index: RValue<'gcc>) {
@ -1417,6 +1421,166 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
fn fptoint_sat(&mut self, signed: bool, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
let src_ty = self.cx.val_ty(val);
let (float_ty, int_ty) = if self.cx.type_kind(src_ty) == TypeKind::Vector {
assert_eq!(self.cx.vector_length(src_ty), self.cx.vector_length(dest_ty));
(self.cx.element_type(src_ty), self.cx.element_type(dest_ty))
} else {
(src_ty, dest_ty)
};
// FIXME(jistone): the following was originally the fallback SSA implementation, before LLVM 13
// added native `fptosi.sat` and `fptoui.sat` conversions, but it was used by GCC as well.
// Now that LLVM always relies on its own, the code has been moved to GCC, but the comments are
// still LLVM-specific. This should be updated, and use better GCC specifics if possible.
let int_width = self.cx.int_width(int_ty);
let float_width = self.cx.float_width(float_ty);
// LLVM's fpto[su]i returns undef when the input val is infinite, NaN, or does not fit into the
// destination integer type after rounding towards zero. This `undef` value can cause UB in
// safe code (see issue #10184), so we implement a saturating conversion on top of it:
// Semantically, the mathematical value of the input is rounded towards zero to the next
// mathematical integer, and then the result is clamped into the range of the destination
// integer type. Positive and negative infinity are mapped to the maximum and minimum value of
// the destination integer type. NaN is mapped to 0.
//
// Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to
// a value representable in int_ty.
// They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits.
// Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two.
// int_ty::MIN, however, is either zero or a negative power of two and is thus exactly
// representable. Note that this only works if float_ty's exponent range is sufficiently large.
// f16 or 256 bit integers would break this property. Right now the smallest float type is f32
// with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127.
// On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
// we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
// This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
let int_max = |signed: bool, int_width: u64| -> u128 {
let shift_amount = 128 - int_width;
if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount }
};
let int_min = |signed: bool, int_width: u64| -> i128 {
if signed { i128::MIN >> (128 - int_width) } else { 0 }
};
let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) {
let rounded_min =
ieee::Single::from_i128_r(int_min(signed, int_width), Round::TowardZero);
assert_eq!(rounded_min.status, Status::OK);
let rounded_max =
ieee::Single::from_u128_r(int_max(signed, int_width), Round::TowardZero);
assert!(rounded_max.value.is_finite());
(rounded_min.value.to_bits(), rounded_max.value.to_bits())
};
let compute_clamp_bounds_double = |signed: bool, int_width: u64| -> (u128, u128) {
let rounded_min =
ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero);
assert_eq!(rounded_min.status, Status::OK);
let rounded_max =
ieee::Double::from_u128_r(int_max(signed, int_width), Round::TowardZero);
assert!(rounded_max.value.is_finite());
(rounded_min.value.to_bits(), rounded_max.value.to_bits())
};
// To implement saturation, we perform the following steps:
//
// 1. Cast val to an integer with fpto[su]i. This may result in undef.
// 2. Compare val to f_min and f_max, and use the comparison results to select:
// a) int_ty::MIN if val < f_min or val is NaN
// b) int_ty::MAX if val > f_max
// c) the result of fpto[su]i otherwise
// 3. If val is NaN, return 0.0, otherwise return the result of step 2.
//
// This avoids resulting undef because values in range [f_min, f_max] by definition fit into the
// destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of
// undef does not introduce any non-determinism either.
// More importantly, the above procedure correctly implements saturating conversion.
// Proof (sketch):
// If val is NaN, 0 is returned by definition.
// Otherwise, val is finite or infinite and thus can be compared with f_min and f_max.
// This yields three cases to consider:
// (1) if val in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
// saturating conversion for inputs in that range.
// (2) if val > f_max, then val is larger than int_ty::MAX. This holds even if f_max is rounded
// (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
// than int_ty::MAX. Because val is larger than int_ty::MAX, the return value of int_ty::MAX
// is correct.
// (3) if val < f_min, then val is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
// int_ty::MIN and therefore the return value of int_ty::MIN is correct.
// QED.
let float_bits_to_llval = |bx: &mut Self, bits| {
let bits_llval = match float_width {
32 => bx.cx().const_u32(bits as u32),
64 => bx.cx().const_u64(bits as u64),
n => bug!("unsupported float width {}", n),
};
bx.bitcast(bits_llval, float_ty)
};
let (f_min, f_max) = match float_width {
32 => compute_clamp_bounds_single(signed, int_width),
64 => compute_clamp_bounds_double(signed, int_width),
n => bug!("unsupported float width {}", n),
};
let f_min = float_bits_to_llval(self, f_min);
let f_max = float_bits_to_llval(self, f_max);
let int_max = self.cx.const_uint_big(int_ty, int_max(signed, int_width));
let int_min = self.cx.const_uint_big(int_ty, int_min(signed, int_width) as u128);
let zero = self.cx.const_uint(int_ty, 0);
// If we're working with vectors, constants must be "splatted": the constant is duplicated
// into each lane of the vector. The algorithm stays the same, we are just using the
// same constant across all lanes.
let maybe_splat = |bx: &mut Self, val| {
if bx.cx().type_kind(dest_ty) == TypeKind::Vector {
bx.vector_splat(bx.vector_length(dest_ty), val)
} else {
val
}
};
let f_min = maybe_splat(self, f_min);
let f_max = maybe_splat(self, f_max);
let int_max = maybe_splat(self, int_max);
let int_min = maybe_splat(self, int_min);
let zero = maybe_splat(self, zero);
// Step 1 ...
let fptosui_result = if signed { self.fptosi(val, dest_ty) } else { self.fptoui(val, dest_ty) };
let less_or_nan = self.fcmp(RealPredicate::RealULT, val, f_min);
let greater = self.fcmp(RealPredicate::RealOGT, val, f_max);
// Step 2: We use two comparisons and two selects, with %s1 being the
// result:
// %less_or_nan = fcmp ult %val, %f_min
// %greater = fcmp olt %val, %f_max
// %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
// %s1 = select %greater, int_ty::MAX, %s0
// Note that %less_or_nan uses an *unordered* comparison. This
// comparison is true if the operands are not comparable (i.e., if val is
// NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if
// val is NaN.
//
// Performance note: Unordered comparison can be lowered to a "flipped"
// comparison and a negation, and the negation can be merged into the
// select. Therefore, it not necessarily any more expensive than an
// ordered ("normal") comparison. Whether these optimizations will be
// performed is ultimately up to the backend, but at least x86 does
// perform them.
let s0 = self.select(less_or_nan, int_min, fptosui_result);
let s1 = self.select(greater, int_max, s0);
// Step 3: NaN replacement.
// For unsigned types, the above step already yielded int_ty::MIN == 0 if val is NaN.
// Therefore we only need to execute this step for signed integer types.
if signed {
// LLVM has no isNaN predicate, so we use (val == val) instead
let cmp = self.fcmp(RealPredicate::RealOEQ, val, val);
self.select(cmp, s1, zero)
} else {
s1
}
}
#[cfg(feature="master")]
pub fn shuffle_vector(&mut self, v1: RValue<'gcc>, v2: RValue<'gcc>, mask: RValue<'gcc>) -> RValue<'gcc> {
let struct_type = mask.get_type().is_struct().expect("mask should be of struct type");

View file

@ -1,7 +1,7 @@
#[cfg(feature="master")]
use gccjit::{FnAttribute, Visibility};
use gccjit::{FunctionType, Function};
use rustc_middle::ty::{self, Instance, TypeVisitable};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use crate::attributes;

View file

@ -36,7 +36,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
let context = &cx.context;
let byte_type = context.new_type::<u8>();
let typ = context.new_array_type(None, byte_type, bytes.len() as i32);
let typ = context.new_array_type(None, byte_type, bytes.len() as u64);
let elements: Vec<_> =
bytes.iter()
.map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32))
@ -44,7 +44,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) ->
context.new_array_constructor(None, typ, &elements)
}
pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool {
pub fn type_is_pointer(typ: Type<'_>) -> bool {
typ.get_pointee().is_some()
}
@ -115,8 +115,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
self.const_uint(self.usize_type, i)
}
fn const_u8(&self, _i: u8) -> RValue<'gcc> {
unimplemented!();
fn const_u8(&self, i: u8) -> RValue<'gcc> {
self.const_uint(self.type_u8(), i as u64)
}
fn const_real(&self, typ: Type<'gcc>, val: f64) -> RValue<'gcc> {
@ -158,10 +158,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
None
}
fn zst_to_backend(&self, _ty: Type<'gcc>) -> RValue<'gcc> {
self.const_undef(self.type_ix(0))
}
fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> {
let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
match cv {
@ -225,7 +221,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
let base_addr = self.const_bitcast(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);
if layout.primitive() != Pointer {
if !matches!(layout.primitive(), Pointer(_)) {
self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
}
else {
@ -245,7 +241,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
let value =
if layout.size == Size::ZERO {
let value = self.const_usize(alloc.inner().align.bytes());
self.context.new_cast(None, value, ty)
self.const_bitcast(value, ty)
}
else {
let init = const_alloc_to_gcc(self, alloc);

View file

@ -8,12 +8,12 @@ use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::mir::interpret::{self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
use crate::base;
use crate::context::CodegenCx;
use crate::errors::InvalidMinimumAlignment;
use crate::type_of::LayoutGccExt;
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@ -31,6 +31,21 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
}
fn set_global_alignment<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, gv: LValue<'gcc>, mut align: Align) {
// The target may require greater alignment for globals than the type does.
// Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
// which can force it to be smaller. Rust doesn't support this yet.
if let Some(min) = cx.sess().target.min_global_align {
match Align::from_bits(min) {
Ok(min) => align = align.max(min),
Err(err) => {
cx.sess().emit_err(InvalidMinimumAlignment { err });
}
}
}
gv.set_alignment(align.bytes() as i32);
}
impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
fn static_addr_of(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
// TODO(antoyo): implement a proper rvalue comparison in libgccjit instead of doing the
@ -82,7 +97,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
let gcc_type = self.layout_of(ty).gcc_type(self);
// TODO(antoyo): set alignment.
set_global_alignment(self, global, self.align_of(ty));
let value = self.bitcast_if_needed(value, gcc_type);
global.global_set_initializer_rvalue(value);
@ -127,7 +142,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
//
// We could remove this hack whenever we decide to drop macOS 10.10 support.
if self.tcx.sess.target.options.is_like_osx {
// The `inspect` method is okay here because we checked relocations, and
// The `inspect` method is okay here because we checked for provenance, and
// because we are doing this access to inspect the final interpreter state
// (not as part of the interpreter execution).
//
@ -215,7 +230,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
let sym = self.tcx.symbol_name(instance).name;
let global = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
let global =
if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
let llty = self.layout_of(ty).gcc_type(self);
if let Some(global) = self.get_declared_value(sym) {
if self.val_ty(global) != self.type_ptr_to(llty) {
@ -238,7 +254,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
global
} else {
check_and_apply_linkage(&self, &fn_attrs, ty, sym, self.tcx.def_span(def_id))
check_and_apply_linkage(&self, &fn_attrs, ty, sym)
};
if !def_id.is_local() {
@ -278,17 +294,17 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAllocation<'tcx>) -> RValue<'gcc> {
let alloc = alloc.inner();
let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
let dl = cx.data_layout();
let pointer_size = dl.pointer_size.bytes() as usize;
let mut next_offset = 0;
for &(offset, alloc_id) in alloc.relocations().iter() {
for &(offset, alloc_id) in alloc.provenance().ptrs().iter() {
let offset = offset.bytes();
assert_eq!(offset as usize as u64, offset);
let offset = offset as usize;
if offset > next_offset {
// This `inspect` is okay since we have checked that it is not within a relocation, it
// This `inspect` is okay since we have checked that it is not within a pointer with provenance, it
// is within the bounds of the allocation, and it doesn't affect interpreter execution
// (we inspect the result after interpreter execution). Any undef byte is replaced with
// some arbitrary byte value.
@ -301,24 +317,27 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl
read_target_uint( dl.endian,
// This `inspect` is okay since it is within the bounds of the allocation, it doesn't
// affect interpreter execution (we inspect the result after interpreter execution),
// and we properly interpret the relocation as a relocation pointer offset.
// and we properly interpret the provenance as a relocation pointer offset.
alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
)
.expect("const_alloc_to_llvm: could not read relocation pointer")
as u64;
let address_space = cx.tcx.global_alloc(alloc_id).address_space(cx);
llvals.push(cx.scalar_to_backend(
InterpScalar::from_pointer(
interpret::Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
&cx.tcx,
),
abi::Scalar::Initialized { value: Primitive::Pointer, valid_range: WrappingRange::full(dl.pointer_size) },
cx.type_i8p(),
abi::Scalar::Initialized { value: Primitive::Pointer(address_space), valid_range: WrappingRange::full(dl.pointer_size) },
cx.type_i8p_ext(address_space),
));
next_offset = offset + pointer_size;
}
if alloc.len() >= next_offset {
let range = next_offset..alloc.len();
// This `inspect` is okay since we have check that it is after all relocations, it is
// This `inspect` is okay since we have check that it is after all provenance, it is
// within the bounds of the allocation, and it doesn't affect interpreter execution (we
// inspect the result after interpreter execution). Any undef byte is replaced with some
// arbitrary byte value.
@ -336,27 +355,12 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id
Ok((const_alloc_to_gcc(cx, alloc), alloc))
}
fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> {
fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str) -> LValue<'gcc> {
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
let llty = cx.layout_of(ty).gcc_type(cx);
if let Some(linkage) = attrs.linkage {
// If this is a static with a linkage specified, then we need to handle
// it a little specially. The typesystem prevents things like &T and
// extern "C" fn() from being non-null, so we can't just declare a
// static and call it a day. Some linkages (like weak) will make it such
// that the static actually has a null value.
let llty2 =
if let ty::RawPtr(ref mt) = ty.kind() {
cx.layout_of(mt.ty).gcc_type(cx)
}
else {
cx.sess().span_fatal(
span,
"must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
)
};
let gcc_type = cx.layout_of(ty).gcc_type(cx);
if let Some(linkage) = attrs.import_linkage {
// Declare a symbol `foo` with the desired linkage.
let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage));
let global1 = cx.declare_global_with_linkage(&sym, cx.type_i8(), base::global_linkage_to_gcc(linkage));
// Declare an internal global `extern_with_linkage_foo` which
// is initialized with the address of `foo`. If `foo` is
@ -366,9 +370,10 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&sym);
let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section);
let global2 = cx.define_global(&real_name, gcc_type, is_tls, attrs.link_section);
// TODO(antoyo): set linkage.
global2.global_set_initializer_rvalue(global1.get_address(None));
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
}
@ -382,6 +387,6 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
// don't do this then linker errors can be generated where the linker
// complains that one object files has a thread local version of the
// symbol and another one doesn't.
cx.declare_global(&sym, llty, GlobalKind::Imported, is_tls, attrs.link_section)
cx.declare_global(&sym, gcc_type, GlobalKind::Imported, is_tls, attrs.link_section)
}
}

View file

@ -14,7 +14,7 @@ use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_middle::ty::layout::{FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
use rustc_session::Session;
use rustc_span::Span;
use rustc_span::{Span, source_map::respan};
use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
@ -88,9 +88,9 @@ pub struct CodegenCx<'gcc, 'tcx> {
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
// TODO(antoyo): improve the SSA API to not require those.
// Mapping from function pointer type to indexes of on stack parameters.
/// Mapping from function pointer type to indexes of on stack parameters.
pub on_stack_params: RefCell<FxHashMap<FunctionPtrType<'gcc>, FxHashSet<usize>>>,
// Mapping from function to indexes of on stack parameters.
/// Mapping from function to indexes of on stack parameters.
pub on_stack_function_params: RefCell<FxHashMap<Function<'gcc>, FxHashSet<usize>>>,
/// Cache of emitted const globals (value -> global)
@ -258,8 +258,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(),
"{:?} is not a function", function);
debug_assert!(self.functions.borrow().values().any(|value| *value == function),
"{:?} ({:?}) is not a function", value, value.get_type());
function
}
@ -298,7 +298,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
self.is_native_int_type(typ) || self.is_non_native_int_type(typ) || typ.is_compatible_with(self.bool_type)
}
pub fn sess(&self) -> &Session {
pub fn sess(&self) -> &'tcx Session {
&self.tcx.sess
}
@ -391,7 +391,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
tcx,
ty::ParamEnv::reveal_all(),
def_id,
tcx.intern_substs(&[]),
ty::List::empty(),
)
.unwrap().unwrap();
@ -431,10 +431,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
self.codegen_unit
}
fn used_statics(&self) -> &RefCell<Vec<RValue<'gcc>>> {
unimplemented!();
}
fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) {
// TODO(antoyo)
}
@ -443,13 +439,10 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
// TODO(antoyo)
}
fn create_used_variable(&self) {
unimplemented!();
}
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
if self.get_declared_value("main").is_none() {
Some(self.declare_cfn("main", fn_type))
let entry_name = self.sess().target.entry_name.as_ref();
if self.get_declared_value(entry_name).is_none() {
Some(self.declare_entry_fn(entry_name, fn_type, ()))
}
else {
// If the symbol already exists, it is an error: for example, the user wrote
@ -458,14 +451,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
None
}
}
fn compiler_used_statics(&self) -> &RefCell<Vec<RValue<'gcc>>> {
unimplemented!()
}
fn create_compiler_used_variable(&self) {
unimplemented!()
}
}
impl<'gcc, 'tcx> HasTyCtxt<'tcx> for CodegenCx<'gcc, 'tcx> {
@ -492,7 +477,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
#[inline]
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
if let LayoutError::SizeOverflow(_) = err {
self.sess().span_fatal(span, &err.to_string())
self.sess().emit_fatal(respan(span, err))
} else {
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
}
@ -510,7 +495,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
fn_abi_request: FnAbiRequest<'tcx>,
) -> ! {
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
self.sess().span_fatal(span, &err.to_string())
self.sess().emit_fatal(respan(span, err))
} else {
match fn_abi_request {
FnAbiRequest::OfFnPtr { sig, extra_args } => {

View file

@ -4,8 +4,9 @@ use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods};
use rustc_middle::mir;
use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
use rustc_span::{SourceFile, Span, Symbol};
use rustc_target::abi::Size;
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::Size;
use std::ops::Range;
use crate::builder::Builder;
use crate::context::CodegenCx;
@ -13,7 +14,15 @@ use crate::context::CodegenCx;
impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> {
// FIXME(eddyb) find a common convention for all of the debuginfo-related
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
fn dbg_var_addr(&mut self, _dbg_var: Self::DIVariable, _scope_metadata: Self::DIScope, _variable_alloca: Self::Value, _direct_offset: Size, _indirect_offsets: &[Size]) {
fn dbg_var_addr(
&mut self,
_dbg_var: Self::DIVariable,
_scope_metadata: Self::DIScope,
_variable_alloca: Self::Value,
_direct_offset: Size,
_indirect_offsets: &[Size],
_fragment: Option<Range<Size>>,
) {
unimplemented!();
}
@ -31,16 +40,31 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> {
}
impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn create_vtable_debuginfo(&self, _ty: Ty<'tcx>, _trait_ref: Option<PolyExistentialTraitRef<'tcx>>, _vtable: Self::Value) {
fn create_vtable_debuginfo(
&self,
_ty: Ty<'tcx>,
_trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
_vtable: Self::Value,
) {
// TODO(antoyo)
}
fn create_function_debug_context(&self, _instance: Instance<'tcx>, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: RValue<'gcc>, _mir: &mir::Body<'tcx>) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>> {
fn create_function_debug_context(
&self,
_instance: Instance<'tcx>,
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
_llfn: RValue<'gcc>,
_mir: &mir::Body<'tcx>,
) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>> {
// TODO(antoyo)
None
}
fn extend_scope_to_file(&self, _scope_metadata: Self::DIScope, _file: &SourceFile) -> Self::DIScope {
fn extend_scope_to_file(
&self,
_scope_metadata: Self::DIScope,
_file: &SourceFile,
) -> Self::DIScope {
unimplemented!();
}
@ -48,15 +72,32 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
// TODO(antoyo)
}
fn create_dbg_var(&self, _variable_name: Symbol, _variable_type: Ty<'tcx>, _scope_metadata: Self::DIScope, _variable_kind: VariableKind, _span: Span) -> Self::DIVariable {
fn create_dbg_var(
&self,
_variable_name: Symbol,
_variable_type: Ty<'tcx>,
_scope_metadata: Self::DIScope,
_variable_kind: VariableKind,
_span: Span,
) -> Self::DIVariable {
unimplemented!();
}
fn dbg_scope_fn(&self, _instance: Instance<'tcx>, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _maybe_definition_llfn: Option<RValue<'gcc>>) -> Self::DIScope {
fn dbg_scope_fn(
&self,
_instance: Instance<'tcx>,
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
_maybe_definition_llfn: Option<RValue<'gcc>>,
) -> Self::DIScope {
unimplemented!();
}
fn dbg_loc(&self, _scope: Self::DIScope, _inlined_at: Option<Self::DILocation>, _span: Span) -> Self::DILocation {
fn dbg_loc(
&self,
_scope: Self::DIScope,
_inlined_at: Option<Self::DILocation>,
_span: Span,
) -> Self::DILocation {
unimplemented!();
}
}

View file

@ -63,13 +63,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
global
}
pub fn declare_cfn(&self, name: &str, _fn_type: Type<'gcc>) -> RValue<'gcc> {
pub fn declare_entry_fn(&self, name: &str, _fn_type: Type<'gcc>, callconv: () /*llvm::CCallConv*/) -> RValue<'gcc> {
// TODO(antoyo): use the fn_type parameter.
let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
let return_type = self.type_i32();
let variadic = false;
self.linkage.set(FunctionType::Exported);
let func = declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, &[self.type_i32(), const_string], variadic);
let func = declare_raw_fn(self, name, callconv, return_type, &[self.type_i32(), const_string], variadic);
// NOTE: it is needed to set the current_func here as well, because get_fn() is not called
// for the main function.
*self.current_func.borrow_mut() = Some(func);

229
src/errors.rs Normal file
View file

@ -0,0 +1,229 @@
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_macros::Diagnostic;
use rustc_middle::ty::Ty;
use rustc_span::{Span, Symbol};
use std::borrow::Cow;
struct ExitCode(Option<i32>);
impl IntoDiagnosticArg for ExitCode {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
let ExitCode(exit_code) = self;
match exit_code {
Some(t) => t.into_diagnostic_arg(),
None => DiagnosticArgValue::Str(Cow::Borrowed("<signal>")),
}
}
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")]
pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_invalid_float_vector, code = "E0511")]
pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub elem_ty: &'a str,
pub vec_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_not_float, code = "E0511")]
pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_unrecognized, code = "E0511")]
pub(crate) struct InvalidMonomorphizationUnrecognized {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub elem_ty: Ty<'a>,
pub vec_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_unsupported_element, code = "E0511")]
pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_ty: Ty<'a>,
pub elem_ty: Ty<'a>,
pub ret_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_invalid_bitmask, code = "E0511")]
pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
pub expected_int_bits: u64,
pub expected_bytes: u64,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_simd_shuffle, code = "E0511")]
pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_expected_simd, code = "E0511")]
pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub position: &'a str,
pub found_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_mask_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationMaskType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_return_length, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_len: u64,
pub ret_ty: Ty<'a>,
pub out_len: u64,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_return_length_input_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_len: u64,
pub in_ty: Ty<'a>,
pub ret_ty: Ty<'a>,
pub out_len: u64,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_return_element, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_elem: Ty<'a>,
pub in_ty: Ty<'a>,
pub ret_ty: Ty<'a>,
pub out_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_return_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_elem: Ty<'a>,
pub in_ty: Ty<'a>,
pub ret_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_inserted_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_elem: Ty<'a>,
pub in_ty: Ty<'a>,
pub out_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_return_integer_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ret_ty: Ty<'a>,
pub out_ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_mismatched_lengths, code = "E0511")]
pub(crate) struct InvalidMonomorphizationMismatchedLengths {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub m_len: u64,
pub v_len: u64,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_unsupported_cast, code = "E0511")]
pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_ty: Ty<'a>,
pub in_elem: Ty<'a>,
pub ret_ty: Ty<'a>,
pub out_elem: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_monomorphization_unsupported_operation, code = "E0511")]
pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_ty: Ty<'a>,
pub in_elem: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_lto_not_supported)]
pub(crate) struct LTONotSupported;
#[derive(Diagnostic)]
#[diag(codegen_gcc_unwinding_inline_asm)]
pub(crate) struct UnwindingInlineAsm {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_gcc_invalid_minimum_alignment)]
pub(crate) struct InvalidMinimumAlignment {
pub err: String,
}

View file

@ -407,7 +407,7 @@ pub fn ignore_arg_cast(func_name: &str, index: usize, args_len: usize) -> bool {
#[cfg(not(feature="master"))]
pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> {
match name {
"llvm.x86.xgetbv" => {
"llvm.x86.xgetbv" | "llvm.x86.sse2.pause" => {
let gcc_name = "__builtin_trap";
let func = cx.context.get_builtin_function(gcc_name);
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);

View file

@ -7,7 +7,7 @@ use std::iter;
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::common::{IntPredicate, span_invalid_monomorphization_error};
use rustc_codegen_ssa::common::IntPredicate;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
@ -31,6 +31,7 @@ use crate::abi::FnAbiGccExt;
use crate::builder::Builder;
use crate::common::{SignType, TypeReflection};
use crate::context::CodegenCx;
use crate::errors::InvalidMonomorphizationBasicInteger;
use crate::type_of::LayoutGccExt;
use crate::intrinsic::simd::generic_simd_intrinsic;
@ -110,7 +111,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
_ if simple.is_some() => {
// FIXME(antoyo): remove this cast when the API supports function.
let func = unsafe { std::mem::transmute(simple.expect("simple")) };
self.call(self.type_void(), func, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None)
self.call(self.type_void(), None, func, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None)
},
sym::likely => {
self.expect(args[0].immediate(), true)
@ -141,7 +142,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
sym::volatile_load | sym::unaligned_volatile_load => {
let tp_ty = substs.type_at(0);
let mut ptr = args[0].immediate();
if let PassMode::Cast(ty) = fn_abi.ret.mode {
if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self)));
}
let load = self.volatile_load(ptr.get_type(), ptr);
@ -253,15 +254,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
_ => bug!(),
},
None => {
span_invalid_monomorphization_error(
tcx.sess,
span,
&format!(
"invalid monomorphization of `{}` intrinsic: \
expected basic integer type, found `{}`",
name, ty
),
);
tcx.sess.emit_err(InvalidMonomorphizationBasicInteger { span, name, ty });
return;
}
}
@ -320,6 +313,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
return;
}
sym::ptr_mask => {
let usize_type = self.context.new_type::<usize>();
let void_ptr_type = self.context.new_type::<*const ()>();
let ptr = args[0].immediate();
let mask = args[1].immediate();
let addr = self.bitcast(ptr, usize_type);
let masked = self.and(addr, mask);
self.bitcast(masked, void_ptr_type)
},
_ if name_str.starts_with("simd_") => {
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
Ok(llval) => llval,
@ -331,7 +336,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
};
if !fn_abi.ret.is_ignore() {
if let PassMode::Cast(ty) = fn_abi.ret.mode {
if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
let ptr_llty = self.type_ptr_to(ty.gcc_type(self));
let ptr = self.pointercast(result.llval, ptr_llty);
self.store(llval, ptr, result.align);
@ -347,7 +352,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
fn abort(&mut self) {
let func = self.context.get_builtin_function("abort");
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
self.call(self.type_void(), func, &[], None);
self.call(self.type_void(), None, func, &[], None);
}
fn assume(&mut self, value: Self::Value) {
@ -427,7 +432,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
else if self.is_unsized_indirect() {
bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
}
else if let PassMode::Cast(cast) = self.mode {
else if let PassMode::Cast(ref cast, _) = self.mode {
// FIXME(eddyb): Figure out when the simpler Store is safe, clang
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
let can_store_through_cast_ptr = false;
@ -492,7 +497,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
PassMode::Indirect { extra_attrs: Some(_), .. } => {
OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
},
PassMode::Direct(_) | PassMode::Indirect { extra_attrs: None, .. } | PassMode::Cast(_) => {
PassMode::Direct(_) | PassMode::Indirect { extra_attrs: None, .. } | PassMode::Cast(..) => {
let next_arg = next();
self.store(bx, next_arg, dst);
},
@ -1128,7 +1133,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(bx: &'b mut Builder<'a, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, dest: RValue<'gcc>) {
if bx.sess().panic_strategy() == PanicStrategy::Abort {
bx.call(bx.type_void(), try_func, &[data], None);
bx.call(bx.type_void(), None, try_func, &[data], None);
// Return 0 unconditionally from the intrinsic call;
// we can never unwind.
let ret_align = bx.tcx.data_layout.i32_align.abi;
@ -1197,21 +1202,21 @@ fn codegen_gnu_try<'gcc>(bx: &mut Builder<'_, 'gcc, '_>, try_func: RValue<'gcc>,
let zero = bx.cx.context.new_rvalue_zero(bx.int_type);
let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
bx.call(catch_ty, catch_func, &[data, ptr], None);
bx.call(catch_ty, None, catch_func, &[data, ptr], None);
bx.ret(bx.const_i32(1));
// NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not
// generate a try/catch.
// FIXME(antoyo): add a check in the libgccjit API to prevent this.
bx.switch_to_block(current_block);
bx.invoke(try_func_ty, try_func, &[data], then, catch, None);
bx.invoke(try_func_ty, None, try_func, &[data], then, catch, None);
});
let func = unsafe { std::mem::transmute(func) };
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, func, &[try_func, data, catch_func], None);
let ret = bx.call(llty, None, func, &[try_func, data, catch_func], None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}
@ -1248,8 +1253,8 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut
)));
// `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig(
[try_fn_ty, i8p, catch_fn_ty].iter(),
&tcx.types.i32,
[try_fn_ty, i8p, catch_fn_ty],
tcx.types.i32,
false,
rustc_hir::Unsafety::Unsafe,
Abi::Rust,

View file

@ -1,8 +1,13 @@
#[cfg_attr(not(feature="master"), allow(unused_imports))]
use gccjit::{ToRValue, ComparisonOp, UnaryOp};
#[cfg(feature="master")]
use gccjit::{ComparisonOp, UnaryOp};
use gccjit::ToRValue;
use gccjit::{BinaryOp, RValue, Type};
use rustc_codegen_ssa::base::compare_simd_types;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind, span_invalid_monomorphization_error};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
#[cfg(feature="master")]
use rustc_codegen_ssa::errors::ExpectedPointerMutability;
use rustc_codegen_ssa::errors::InvalidMonomorphization;
use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods};
@ -10,48 +15,60 @@ use rustc_hir as hir;
use rustc_middle::span_bug;
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{self, Ty};
use rustc_span::{Span, Symbol, sym};
use rustc_span::{sym, Span, Symbol};
use rustc_target::abi::Align;
use crate::builder::Builder;
#[cfg(feature="master")]
use crate::context::CodegenCx;
#[cfg(feature="master")]
use crate::errors::{InvalidMonomorphizationExpectedSignedUnsigned, InvalidMonomorphizationInsertedType};
use crate::errors::{
InvalidMonomorphizationExpectedSimd,
InvalidMonomorphizationInvalidBitmask,
InvalidMonomorphizationInvalidFloatVector, InvalidMonomorphizationMaskType,
InvalidMonomorphizationMismatchedLengths, InvalidMonomorphizationNotFloat,
InvalidMonomorphizationReturnElement, InvalidMonomorphizationReturnIntegerType,
InvalidMonomorphizationReturnLength, InvalidMonomorphizationReturnLengthInputType,
InvalidMonomorphizationReturnType, InvalidMonomorphizationSimdShuffle,
InvalidMonomorphizationUnrecognized, InvalidMonomorphizationUnsupportedElement,
InvalidMonomorphizationUnsupportedOperation,
};
pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result<RValue<'gcc>, ()> {
pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
bx: &mut Builder<'a, 'gcc, 'tcx>,
name: Symbol,
callee_ty: Ty<'tcx>,
args: &[OperandRef<'tcx, RValue<'gcc>>],
ret_ty: Ty<'tcx>,
llret_ty: Type<'gcc>,
span: Span,
) -> Result<RValue<'gcc>, ()> {
// macros for error handling:
#[allow(unused_macro_rules)]
macro_rules! emit_error {
($msg: tt) => {
emit_error!($msg, )
};
($msg: tt, $($fmt: tt)*) => {
span_invalid_monomorphization_error(
bx.sess(), span,
&format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
name, $($fmt)*));
}
}
macro_rules! return_error {
($($fmt: tt)*) => {
{
emit_error!($($fmt)*);
return Err(());
}
}
($err:expr) => {{
bx.sess().emit_err($err);
return Err(());
}};
}
macro_rules! require {
($cond: expr, $($fmt: tt)*) => {
($cond:expr, $err:expr) => {
if !$cond {
return_error!($($fmt)*);
return_error!($err);
}
};
}
macro_rules! require_simd {
($ty: expr, $position: expr) => {
require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
require!(
$ty.is_simd(),
InvalidMonomorphizationExpectedSimd {
span,
name,
position: $position,
found_ty: $ty
}
)
};
}
@ -73,7 +90,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
&& len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
&& len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) =>
{
let place = PlaceRef::alloca(bx, args[0].layout);
@ -82,12 +99,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
bx.load(int_ty, ptr, Align::ONE)
}
_ => return_error!(
"invalid bitmask `{}`, expected `u{}` or `[u8; {}]`",
mask_ty,
_ => return_error!(InvalidMonomorphizationInvalidBitmask {
span,
name,
ty: mask_ty,
expected_int_bits,
expected_bytes
),
}),
};
let arg1 = args[1].immediate();
@ -133,18 +151,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!(
in_len == out_len,
"expected return type with length {} (same as input type `{}`), \
found `{}` with length {}",
in_len,
in_ty,
ret_ty,
out_len
InvalidMonomorphizationReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
);
require!(
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
"expected return type with integer elements, found `{}` with non-integer `{}`",
ret_ty,
out_ty
InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty }
);
return Ok(compare_simd_types(
@ -158,65 +176,49 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
}
if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") {
let n: u64 =
if stripped.is_empty() {
// Make sure this is actually an array, since typeck only checks the length-suffixed
// version of this intrinsic.
match args[2].layout.ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| {
span_bug!(span, "could not evaluate shuffle index array length")
})
}
_ => return_error!(
"simd_shuffle index must be an array of `u32`, got `{}`",
args[2].layout.ty
),
let n: u64 = if stripped.is_empty() {
// Make sure this is actually an array, since typeck only checks the length-suffixed
// version of this intrinsic.
match args[2].layout.ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
|| span_bug!(span, "could not evaluate shuffle index array length"),
)
}
_ => return_error!(InvalidMonomorphizationSimdShuffle {
span,
name,
ty: args[2].layout.ty
}),
}
else {
stripped.parse().unwrap_or_else(|_| {
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
})
};
} else {
stripped.parse().unwrap_or_else(|_| {
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
})
};
require_simd!(ret_ty, "return");
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!(
out_len == n,
"expected return type of length {}, found `{}` with length {}",
n,
ret_ty,
out_len
InvalidMonomorphizationReturnLength { span, name, in_len: n, ret_ty, out_len }
);
require!(
in_elem == out_ty,
"expected return element type `{}` (element of input `{}`), \
found `{}` with element type `{}`",
in_elem,
in_ty,
ret_ty,
out_ty
InvalidMonomorphizationReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
);
let vector = args[2].immediate();
return Ok(bx.shuffle_vector(
args[0].immediate(),
args[1].immediate(),
vector,
));
return Ok(bx.shuffle_vector(args[0].immediate(), args[1].immediate(), vector));
}
#[cfg(feature="master")]
#[cfg(feature = "master")]
if name == sym::simd_insert {
require!(
in_elem == arg_tys[2],
"expected inserted type `{}` (element of input `{}`), found `{}`",
in_elem,
in_ty,
arg_tys[2]
InvalidMonomorphizationInsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] }
);
let vector = args[0].immediate();
let index = args[1].immediate();
@ -229,14 +231,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
return Ok(variable.to_rvalue());
}
#[cfg(feature="master")]
#[cfg(feature = "master")]
if name == sym::simd_extract {
require!(
ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`",
in_elem,
in_ty,
ret_ty
InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
);
let vector = args[0].immediate();
return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
@ -249,13 +248,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
require!(
m_len == v_len,
"mismatched lengths: mask length `{}` != other vector length `{}`",
m_len,
v_len
InvalidMonomorphizationMismatchedLengths { span, name, m_len, v_len }
);
match m_elem_ty.kind() {
ty::Int(_) => {}
_ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty),
_ => return_error!(InvalidMonomorphizationMaskType { span, name, ty: m_elem_ty }),
}
return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate()));
}
@ -266,12 +263,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(
in_len == out_len,
"expected return type with length {} (same as input type `{}`), \
found `{}` with length {}",
in_len,
in_ty,
ret_ty,
out_len
InvalidMonomorphizationReturnLengthInputType {
span,
name,
in_len,
in_ty,
ret_ty,
out_len
}
);
// casting cares about nominal type, not just structural type
if in_elem == out_elem {
@ -302,11 +301,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
(Style::Unsupported, Style::Unsupported) => {
require!(
false,
"unsupported cast from `{}` with element `{}` to `{}` with element `{}`",
in_ty,
in_elem,
ret_ty,
out_elem
InvalidMonomorphization::UnsupportedCast {
span,
name,
in_ty,
in_elem,
ret_ty,
out_elem
}
);
},
_ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)),
@ -322,10 +324,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
})*
_ => {},
}
require!(false,
"unsupported operation on `{}` with element `{}`",
in_ty,
in_elem)
return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
})*
}
}
@ -372,7 +371,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
}
ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
&& len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
&& len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) =>
{
// Zero-extend iN to the array length:
@ -385,12 +384,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
return Ok(bx.load(array_ty, ptr, Align::ONE));
}
_ => return_error!(
"cannot return `{}`, expected `u{}` or `[u8; {}]`",
_ => return_error!(InvalidMonomorphization::CannotReturn {
span,
name,
ret_ty,
expected_int_bits,
expected_bytes
),
}),
}
}
@ -403,23 +403,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
span: Span,
args: &[OperandRef<'tcx, RValue<'gcc>>],
) -> Result<RValue<'gcc>, ()> {
macro_rules! emit_error {
($msg: tt, $($fmt: tt)*) => {
span_invalid_monomorphization_error(
bx.sess(), span,
&format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
name, $($fmt)*));
}
}
macro_rules! return_error {
($($fmt: tt)*) => {
{
emit_error!($($fmt)*);
return Err(());
}
}
($err:expr) => {{
bx.sess().emit_err($err);
return Err(());
}};
}
let (elem_ty_str, elem_ty) =
if let ty::Float(f) = in_elem.kind() {
let elem_ty = bx.cx.type_float_from_ty(*f);
@ -427,16 +416,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
32 => ("f", elem_ty),
64 => ("", elem_ty),
_ => {
return_error!(
"unsupported element type `{}` of floating-point vector `{}`",
f.name_str(),
in_ty
);
return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty });
}
}
}
else {
return_error!("`{}` is not a floating-point type", in_ty);
return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty });
};
let vec_ty = bx.cx.type_vector(elem_ty, in_len);
@ -459,7 +444,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
sym::simd_fsqrt => "sqrt",
sym::simd_round => "round",
sym::simd_trunc => "trunc",
_ => return_error!("unrecognized intrinsic `{}`", name),
_ => return_error!(InvalidMonomorphizationUnrecognized { span, name })
};
let builtin_name = format!("{}{}", intr_name, elem_ty_str);
let funcs = bx.cx.functions.borrow();
@ -585,27 +570,32 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
require!(
in_len == out_len,
"expected {} argument with length {} (same as input type `{}`), \
found `{}` with length {}",
"second",
in_len,
in_ty,
arg_tys[1],
out_len
InvalidMonomorphization::SecondArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[1],
out_len
}
);
require!(
in_len == out_len2,
"expected {} argument with length {} (same as input type `{}`), \
found `{}` with length {}",
"third",
in_len,
in_ty,
arg_tys[2],
out_len2
InvalidMonomorphization::ThirdArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[2],
out_len: out_len2
}
);
// The return type must match the first argument type
require!(ret_ty == in_ty, "expected return type `{}`, found `{}`", in_ty, ret_ty);
require!(
ret_ty == in_ty,
InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty }
);
// This counts how many pointers
fn ptr_count(t: Ty<'_>) -> usize {
@ -632,15 +622,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
_ => {
require!(
false,
"expected element type `{}` of second argument `{}` \
to be a pointer to the element type `{}` of the first \
argument `{}`, found `{}` != `*_ {}`",
element_ty1,
arg_tys[1],
InvalidMonomorphization::ExpectedElementType {
span,
name,
expected_element: element_ty1,
second_arg: arg_tys[1],
in_elem,
in_ty,
element_ty1,
in_elem
mutability: ExpectedPointerMutability::Not,
}
);
unreachable!();
}
@ -656,10 +646,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
_ => {
require!(
false,
"expected element type `{}` of third argument `{}` \
to be a signed integer type",
element_ty2,
arg_tys[2]
InvalidMonomorphization::ThirdArgElementType {
span,
name,
expected_element: element_ty2,
third_arg: arg_tys[2]
}
);
}
}
@ -685,23 +677,25 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
require!(
in_len == element_len1,
"expected {} argument with length {} (same as input type `{}`), \
found `{}` with length {}",
"second",
in_len,
in_ty,
arg_tys[1],
element_len1
InvalidMonomorphization::SecondArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[1],
out_len: element_len1
}
);
require!(
in_len == element_len2,
"expected {} argument with length {} (same as input type `{}`), \
found `{}` with length {}",
"third",
in_len,
in_ty,
arg_tys[2],
element_len2
InvalidMonomorphization::ThirdArgumentLength {
span,
name,
in_len,
in_ty,
arg_ty: arg_tys[2],
out_len: element_len2
}
);
// This counts how many pointers
@ -732,15 +726,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
_ => {
require!(
false,
"expected element type `{}` of second argument `{}` \
to be a pointer to the element type `{}` of the first \
argument `{}`, found `{}` != `*mut {}`",
element_ty1,
arg_tys[1],
InvalidMonomorphization::ExpectedElementType {
span,
name,
expected_element: element_ty1,
second_arg: arg_tys[1],
in_elem,
in_ty,
element_ty1,
in_elem
mutability: ExpectedPointerMutability::Mut,
}
);
unreachable!();
}
@ -755,10 +749,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
_ => {
require!(
false,
"expected element type `{}` of third argument `{}` \
be a signed integer type",
element_ty2,
arg_tys[2]
InvalidMonomorphization::ThirdArgElementType {
span,
name,
expected_element: element_ty2,
third_arg: arg_tys[2]
}
);
}
}
@ -813,10 +809,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
})*
_ => {},
}
require!(false,
"unsupported operation on `{}` with element `{}`",
in_ty,
in_elem)
return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
})*
}
}
@ -825,7 +818,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
simd_neg: Int => neg, Float => fneg;
}
#[cfg(feature="master")]
#[cfg(feature = "master")]
if name == sym::simd_saturating_add || name == sym::simd_saturating_sub {
let lhs = args[0].immediate();
let rhs = args[1].immediate();
@ -836,14 +829,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)),
_ => {
return_error!(
"expected element type `{}` of vector type `{}` \
to be a signed or unsigned integer type",
arg_tys[0].simd_size_and_type(bx.tcx()).1,
arg_tys[0]
);
}
};
return_error!(InvalidMonomorphizationExpectedSignedUnsigned {
span,
name,
elem_ty: arg_tys[0].simd_size_and_type(bx.tcx()).1,
vec_ty: arg_tys[0],
});
}
};
let result =
match (signed, is_add) {
@ -924,10 +917,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::$name {
require!(
ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`",
in_elem,
in_ty,
ret_ty
InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
);
return match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {
@ -936,8 +926,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
// if overflow occurs, the result is the
// mathematical result modulo 2^n:
Ok(bx.$op(args[1].immediate(), r))
}
else {
} else {
Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
}
}
@ -946,18 +935,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
// ordered arithmetic reductions take an accumulator
let acc = args[1].immediate();
Ok(bx.$float_reduce(acc, args[0].immediate()))
}
else {
} else {
Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
}
}
_ => return_error!(
"unsupported {} from `{}` with element `{}` to `{}`",
sym::$name,
_ => return_error!(InvalidMonomorphizationUnsupportedElement {
span,
name,
in_ty,
in_elem,
elem_ty: in_elem,
ret_ty
),
}),
};
}
};
@ -998,21 +986,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::$name {
require!(
ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`",
in_elem,
in_ty,
ret_ty
InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
);
return match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())),
ty::Float(_) => Ok(bx.$float_red(args[0].immediate())),
_ => return_error!(
"unsupported {} from `{}` with element `{}` to `{}`",
sym::$name,
in_ty,
in_elem,
ret_ty
),
_ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
};
}
};
@ -1030,22 +1009,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let input = if !$boolean {
require!(
ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`",
in_elem,
in_ty,
ret_ty
InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
);
args[0].immediate()
} else {
match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {}
_ => return_error!(
"unsupported {} from `{}` with element `{}` to `{}`",
sym::$name,
_ => return_error!(InvalidMonomorphizationUnsupportedElement {
span,
name,
in_ty,
in_elem,
elem_ty: in_elem,
ret_ty
),
}),
}
args[0].immediate()
@ -1055,13 +1031,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let r = bx.vector_reduce_op(input, $op);
Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) })
}
_ => return_error!(
"unsupported {} from `{}` with element `{}` to `{}`",
sym::$name,
_ => return_error!(InvalidMonomorphizationUnsupportedElement {
span,
name,
in_ty,
in_elem,
elem_ty: in_elem,
ret_ty
),
}),
};
}
};

View file

@ -18,13 +18,17 @@
#![recursion_limit="256"]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
extern crate rustc_apfloat;
extern crate rustc_ast;
extern crate rustc_attr;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_hir;
extern crate rustc_macros;
extern crate rustc_metadata;
extern crate rustc_middle;
extern crate rustc_session;
@ -51,6 +55,7 @@ mod context;
mod coverageinfo;
mod debuginfo;
mod declare;
mod errors;
mod int;
mod intrinsic;
mod mono_item;
@ -60,6 +65,7 @@ mod type_of;
use std::any::Any;
use std::sync::{Arc, Mutex};
use crate::errors::LTONotSupported;
use gccjit::{Context, OptimizationLevel, CType};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
@ -69,7 +75,8 @@ use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModul
use rustc_codegen_ssa::target_features::supported_target_features;
use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{ErrorGuaranteed, Handler};
use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage};
use rustc_macros::fluent_messages;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
@ -80,6 +87,8 @@ use rustc_span::Symbol;
use rustc_span::fatal_error::FatalError;
use tempfile::TempDir;
fluent_messages! { "../locales/en-US.ftl" }
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
@ -96,9 +105,13 @@ pub struct GccCodegenBackend {
}
impl CodegenBackend for GccCodegenBackend {
fn locale_resource(&self) -> &'static str {
crate::DEFAULT_LOCALE_RESOURCE
}
fn init(&self, sess: &Session) {
if sess.lto() != Lto::No {
sess.warn("LTO is not supported. You may get a linker error.");
sess.emit_warning(LTONotSupported {});
}
let temp_dir = TempDir::new().expect("cannot create temporary directory");
@ -149,15 +162,15 @@ impl CodegenBackend for GccCodegenBackend {
}
impl ExtraBackendMethods for GccCodegenBackend {
fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) -> Self::Module {
fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module {
let mut mods = GccContext {
context: Context::default(),
};
unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, has_alloc_error_handler); }
unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
mods
}
fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
base::compile_codegen_unit(tcx, cgu_name, *self.supports_128bit_integers.lock().expect("lock"))
}
@ -167,15 +180,6 @@ impl ExtraBackendMethods for GccCodegenBackend {
Ok(())
})
}
fn target_cpu<'b>(&self, _sess: &'b Session) -> &'b str {
unimplemented!();
}
fn tune_cpu<'b>(&self, _sess: &'b Session) -> Option<&'b str> {
None
// TODO(antoyo)
}
}
pub struct ModuleBuffer;
@ -205,8 +209,8 @@ unsafe impl Sync for GccContext {}
impl WriteBackendMethods for GccCodegenBackend {
type Module = GccContext;
type TargetMachine = ();
type TargetMachineError = ();
type ModuleBuffer = ModuleBuffer;
type Context = ();
type ThinData = ();
type ThinBuffer = ThinBuffer;
@ -324,10 +328,10 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
false
}
/*
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512gfni,
avx512ifma, avx512pf, avx512vaes, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpclmulqdq,
avx512vpopcntdq, bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, xsave, xsavec, xsaveopt, xsaves
adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512ifma,
avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
*/
//false
})

View file

@ -4,7 +4,7 @@ use rustc_codegen_ssa::traits::PreDefineMethods;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::{self, Instance, TypeVisitable};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
use crate::attributes;

View file

@ -1,5 +1,3 @@
use std::convert::TryInto;
use gccjit::{RValue, Struct, Type};
use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
use rustc_codegen_ssa::common::TypeKind;
@ -201,6 +199,21 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> {
value.get_type()
}
fn type_array(&self, ty: Type<'gcc>, len: u64) -> Type<'gcc> {
// TODO: remove this as well?
/*if let Some(struct_type) = ty.is_struct() {
if struct_type.get_field_count() == 0 {
// NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
// size of usize::MAX in test_binary_search, we workaround this by setting the size to
// zero for ZSTs.
// FIXME(antoyo): fix gccjit API.
len = 0;
}
}*/
self.context.new_array_type(None, ty, len)
}
}
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@ -226,27 +239,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn type_named_struct(&self, name: &str) -> Struct<'gcc> {
self.context.new_opaque_struct_type(None, name)
}
pub fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
if let Some(struct_type) = ty.is_struct() {
if struct_type.get_field_count() == 0 {
// NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
// size of usize::MAX in test_binary_search, we workaround this by setting the size to
// zero for ZSTs.
// FIXME(antoyo): fix gccjit API.
len = 0;
}
}
// NOTE: see note above. Some other test uses usize::MAX.
if len == u64::MAX {
len = 0;
}
let len: i32 = len.try_into().expect("array len");
self.context.new_array_type(None, ty, len)
}
}
pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout<'tcx>) -> (Vec<Type<'gcc>>, bool) {
@ -273,7 +265,7 @@ pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
offset = target_offset + field.size;
prev_effective_align = effective_field_align;
}
if !layout.is_unsized() && field_count > 0 {
if layout.is_sized() && field_count > 0 {
if offset > layout.size {
bug!("layout: {:#?} stride: {:?} offset: {:?}", layout, layout.size, offset);
}
@ -296,4 +288,8 @@ impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
// Unsupported.
self.context.new_rvalue_from_int(self.int_type, 0)
}
fn set_kcfi_type_metadata(&self, _function: RValue<'gcc>, _kcfi_typeid: u32) {
// Unsupported.
}
}

View file

@ -3,10 +3,10 @@ use std::fmt::Write;
use gccjit::{Struct, Type};
use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
use rustc_middle::bug;
use rustc_middle::ty::{self, Ty, TypeVisitable};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_target::abi::{self, Abi, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
use crate::abi::{FnAbiGccExt, GccType};
@ -50,6 +50,12 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
}
impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
pub fn align_of(&self, ty: Ty<'tcx>) -> Align {
self.layout_of(ty).align.abi
}
}
fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout<'tcx>, defer: &mut Option<(Struct<'gcc>, TyAndLayout<'tcx>)>) -> Type<'gcc> {
match layout.abi {
Abi::Scalar(_) => bug!("handled elsewhere"),
@ -253,7 +259,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
Int(i, false) => cx.type_from_unsigned_integer(i),
F32 => cx.type_f32(),
F64 => cx.type_f64(),
Pointer => {
Pointer(address_space) => {
// If we know the alignment, pick something better than i8.
let pointee =
if let Some(pointee) = self.pointee_info_at(cx, offset) {
@ -262,7 +268,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
else {
cx.type_i8()
};
cx.type_ptr_to(pointee)
cx.type_ptr_to_ext(pointee, address_space)
}
}
}

33
test.sh
View file

@ -225,10 +225,13 @@ rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$TARGET_TRIPLE/bin/rustc"
[target.x86_64-unknown-linux-gnu]
llvm-filecheck = "`which FileCheck-10 || which FileCheck-11 || which FileCheck-12 || which FileCheck-13 || which FileCheck-14`"
[llvm]
download-ci-llvm = false
EOF
rustc -V | cut -d' ' -f3 | tr -d '('
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') src/test
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') tests
}
function asm_tests() {
@ -236,7 +239,7 @@ function asm_tests() {
echo "[TEST] rustc test suite"
RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 src/test/assembly/asm --rustc-args "$RUSTC_ARGS"
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/assembly/asm --rustc-args "$RUSTC_ARGS"
}
# FIXME(antoyo): linker gives multiple definitions error on Linux
@ -332,21 +335,21 @@ function test_rustc() {
setup_rustc
for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" src/test/ui); do
for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do
rm $test
done
git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
rm -r src/test/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,*lto*.rs,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true
rm src/test/ui/mir/mir_heavy_promoted.rs # this tests is oom-killed in the CI.
for test in $(rg --files-with-matches "thread|lto" src/test/ui); do
rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,borrowck/,chalkify/bugs/,test*,*lto*.rs,consts/const-float-bits-reject-conv.rs,consts/issue-miri-1910.rs} || true
rm tests/ui/mir/mir_heavy_promoted.rs # this tests is oom-killed in the CI.
for test in $(rg --files-with-matches "thread|lto" tests/ui); do
rm $test
done
git checkout src/test/ui/lto/auxiliary/dylib.rs
git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs
git checkout src/test/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
git checkout tests/ui/lto/auxiliary/dylib.rs
git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs
git checkout tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
RUSTC_ARGS="$TEST_FLAGS -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot"
@ -358,14 +361,14 @@ function test_rustc() {
xargs -a ../failing-ui-tests.txt -d'\n' rm
else
# Removing all tests.
find src/test/ui -type f -name '*.rs' -not -path '*/auxiliary/*' -delete
find tests/ui -type f -name '*.rs' -not -path '*/auxiliary/*' -delete
# Putting back only the failing ones.
xargs -a ../failing-ui-tests.txt -d'\n' git checkout --
fi
if [ $nb_parts -gt 0 ]; then
echo "Splitting ui_test into $nb_parts parts (and running part $current_part)"
find src/test/ui -type f -name '*.rs' -not -path "*/auxiliary/*" > ui_tests
find tests/ui -type f -name '*.rs' -not -path "*/auxiliary/*" > ui_tests
# To ensure it'll be always the same sub files, we sort the content.
sort ui_tests -o ui_tests
count=$((`wc -l < ui_tests` / $nb_parts))
@ -374,13 +377,13 @@ function test_rustc() {
count=$((count + 1))
split -d -l $count -a 1 ui_tests ui_tests.split
# Removing all tests.
find src/test/ui -type f -name '*.rs' -not -path "*/auxiliary/*" -delete
find tests/ui -type f -name '*.rs' -not -path "*/auxiliary/*" -delete
# Putting back only the ones we want to test.
xargs -a "ui_tests.split$current_part" -d'\n' git checkout --
fi
echo "[TEST] rustc test suite"
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 src/test/ui/ --rustc-args "$RUSTC_ARGS"
COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS"
}
function test_failing_rustc() {

View file

@ -33,6 +33,7 @@ mod intrinsics {
use super::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -33,6 +33,7 @@ mod intrinsics {
use super::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -105,6 +105,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -3,11 +3,12 @@
// Run-time:
// status: 0
#![feature(asm_const, asm_sym)]
#![feature(asm_const)]
use std::arch::{asm, global_asm};
global_asm!("
global_asm!(
"
.global add_asm
add_asm:
mov rax, rdi
@ -132,7 +133,9 @@ fn main() {
assert_eq!(x, 43);
// check sym fn
extern "C" fn foo() -> u64 { 42 }
extern "C" fn foo() -> u64 {
42
}
let x: u64;
unsafe {
asm!("call {}", sym foo, lateout("rax") x);

View file

@ -57,6 +57,7 @@ mod libc {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -97,10 +97,14 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}
#[lang = "tuple_trait"]
pub trait Tuple {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
@ -114,7 +118,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
#[lang = "fn_once"]
#[rustc_paren_sugar]
pub trait FnOnce<Args> {
pub trait FnOnce<Args: Tuple> {
#[lang = "fn_once_output"]
type Output;
@ -123,7 +127,7 @@ pub trait FnOnce<Args> {
#[lang = "fn_mut"]
#[rustc_paren_sugar]
pub trait FnMut<Args>: FnOnce<Args> {
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}

View file

@ -108,6 +108,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -102,6 +102,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -3,7 +3,7 @@
// Run-time:
// status: 0
#![feature(bench_black_box, const_black_box)]
#![feature(const_black_box)]
/*
* Code

View file

@ -55,6 +55,7 @@ mod libc {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -59,6 +59,7 @@ mod libc {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -65,6 +65,7 @@ mod libc {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -102,6 +102,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
mod intrinsics {
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -102,6 +102,7 @@ mod intrinsics {
use super::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}

View file

@ -45,6 +45,7 @@ mod intrinsics {
use super::Sized;
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !;
}
}