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:
commit
08a6d6e16b
48 changed files with 1124 additions and 869 deletions
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
|
|
@ -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
18
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() -> !;
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
65
locales/en-US.ftl
Normal 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}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2022-08-26"
|
||||
channel = "nightly-2023-03-02"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
43
src/abi.rs
43
src/abi.rs
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
176
src/archive.rs
176
src/archive.rs
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
258
src/builder.rs
258
src/builder.rs
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 } => {
|
||||
|
|
|
|||
|
|
@ -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!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
229
src/errors.rs
Normal 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,
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
),
|
||||
}),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
42
src/lib.rs
42
src/lib.rs
|
|
@ -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
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
44
src/type_.rs
44
src/type_.rs
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
33
test.sh
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ mod intrinsics {
|
|||
use super::Sized;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ mod intrinsics {
|
|||
use super::Sized;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
|
|||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ mod libc {
|
|||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
|
|||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
|
|||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(bench_black_box, const_black_box)]
|
||||
#![feature(const_black_box)]
|
||||
|
||||
/*
|
||||
* Code
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ mod libc {
|
|||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ mod libc {
|
|||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ mod libc {
|
|||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
|
|||
|
||||
mod intrinsics {
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ mod intrinsics {
|
|||
use super::Sized;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ mod intrinsics {
|
|||
use super::Sized;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[rustc_safe_intrinsic]
|
||||
pub fn abort() -> !;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue