-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Fix some unsoundness with PassMode::Cast ABI #122619
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
4498cd6
extend extern tests to include FiveU16s
erikdesjardins 41c6fa8
sparc64: fix crash in ABI code for { f64, f32 } struct
erikdesjardins 74ef47e
make CastTarget::size and CastTarget::llvm_type consistent, remove
erikdesjardins 8841315
make PassMode::Cast consistently copy between Rust/ABI representation
erikdesjardins 8d5fd94
add tests for PassMode::Cast fixes
erikdesjardins 6577aef
Revert "sparc64: fix crash in ABI code for { f64, f32 } struct"
erikdesjardins dec81ac
disable crashing test on sparc
erikdesjardins File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
add tests for PassMode::Cast fixes
Tests added in cast-target-abi.rs, covering the single element, array, and prefix cases in `CastTarget::llvm_type`, and the Rust-is-larger/smaller cases in the Rust<->ABI copying code. ffi-out-of-bounds-loads.rs was overhauled to be runnable on any platform. Its alignment also increases due to the removal of a `min` in the previous commit; this was probably an insufficient workaround for this issue or similar. The higher alignment is fine, since the alloca is actually aligned to 8 bytes, as the test checks now confirm.
- Loading branch information
commit 8d5fd94e6292b298e59a637d84fa16bed30d64d4
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,269 @@ | ||
| // ignore-tidy-linelength | ||
| //@ revisions:aarch64 loongarch64 powerpc64 sparc64 | ||
| //@ compile-flags: -O -C no-prepopulate-passes | ||
|
|
||
| //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu | ||
| //@[aarch64] needs-llvm-components: arm | ||
| //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu | ||
| //@[loongarch64] needs-llvm-components: loongarch | ||
| //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu | ||
| //@[powerpc64] needs-llvm-components: powerpc | ||
| //@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu | ||
| //@[sparc64] needs-llvm-components: sparc | ||
|
|
||
| // Tests that arguments with `PassMode::Cast` are handled correctly. | ||
|
|
||
| #![feature(no_core, lang_items)] | ||
| #![crate_type = "lib"] | ||
| #![no_std] | ||
| #![no_core] | ||
|
|
||
| #[lang="sized"] trait Sized { } | ||
| #[lang="freeze"] trait Freeze { } | ||
| #[lang="copy"] trait Copy { } | ||
|
|
||
| // This struct will be passed as a single `i64` or `i32`. | ||
| // This may be (if `i64)) larger than the Rust layout, which is just `{ i16, i16 }`. | ||
| #[repr(C)] | ||
| pub struct TwoU16s { | ||
| a: u16, | ||
| b: u16, | ||
| } | ||
|
|
||
| // This struct will be passed as `[2 x i64]`. | ||
| // This is larger than the Rust layout. | ||
| #[repr(C)] | ||
| pub struct FiveU16s { | ||
| a: u16, | ||
| b: u16, | ||
| c: u16, | ||
| d: u16, | ||
| e: u16, | ||
| } | ||
|
|
||
| // This struct will be passed as `[2 x double]`. | ||
| // This is the same as the Rust layout. | ||
| #[repr(C)] | ||
| pub struct DoubleDouble { | ||
| f: f64, | ||
| g: f64, | ||
| } | ||
|
|
||
| // On loongarch, this struct will be passed as `{ double, float }`. | ||
| // This is smaller than the Rust layout, which has trailing padding (`{ f64, f32, <f32 padding> }`) | ||
| #[repr(C)] | ||
| pub struct DoubleFloat { | ||
| f: f64, | ||
| g: f32, | ||
| } | ||
|
|
||
| extern "C" { | ||
| fn receives_twou16s(x: TwoU16s); | ||
| fn returns_twou16s() -> TwoU16s; | ||
|
|
||
| fn receives_fiveu16s(x: FiveU16s); | ||
| fn returns_fiveu16s() -> FiveU16s; | ||
|
|
||
| fn receives_doubledouble(x: DoubleDouble); | ||
| fn returns_doubledouble() -> DoubleDouble; | ||
|
|
||
| fn receives_doublefloat(x: DoubleFloat); | ||
| fn returns_doublefloat() -> DoubleFloat; | ||
| } | ||
|
|
||
| // CHECK-LABEL: @call_twou16s | ||
| #[no_mangle] | ||
| pub unsafe fn call_twou16s() { | ||
| // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] | ||
| // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] | ||
| // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i32]], align [[ABI_ALIGN:4]] | ||
| // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] | ||
|
|
||
| // CHECK: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] | ||
|
|
||
| // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 4, i1 false) | ||
| // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // CHECK: call void @receives_twou16s([[ABI_TYPE]] [[ABI_VALUE]]) | ||
| let x = TwoU16s { a: 1, b: 2 }; | ||
| receives_twou16s(x); | ||
| } | ||
|
|
||
| // CHECK-LABEL: @return_twou16s | ||
| #[no_mangle] | ||
| pub unsafe fn return_twou16s() -> TwoU16s { | ||
| // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. | ||
|
|
||
| // powerpc64: [[RETVAL:%.+]] = alloca %TwoU16s, align 2 | ||
| // powerpc64: call void @returns_twou16s(ptr {{.+}} [[RETVAL]]) | ||
|
|
||
|
|
||
| // The other targets copy the cast ABI type to an alloca. | ||
|
|
||
| // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] | ||
| // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] | ||
| // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] | ||
|
|
||
| // aarch64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] | ||
| // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] | ||
| // sparc64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] | ||
|
|
||
| // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() | ||
| // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() | ||
| // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() | ||
|
|
||
| // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
|
|
||
| // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 4, i1 false) | ||
| // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 4, i1 false) | ||
| // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 4, i1 false) | ||
| returns_twou16s() | ||
| } | ||
|
|
||
| // CHECK-LABEL: @call_fiveu16s | ||
| #[no_mangle] | ||
| pub unsafe fn call_fiveu16s() { | ||
| // CHECK: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] | ||
|
|
||
| // CHECK: [[RUST_ALLOCA:%.+]] = alloca %FiveU16s, align 2 | ||
|
|
||
| // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 10, i1 false) | ||
| // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // CHECK: call void @receives_fiveu16s([[ABI_TYPE]] [[ABI_VALUE]]) | ||
| let x = FiveU16s { a: 1, b: 2, c: 3, d: 4, e: 5 }; | ||
| receives_fiveu16s(x); | ||
| } | ||
|
|
||
| // CHECK-LABEL: @return_fiveu16s | ||
| // CHECK-SAME: (ptr {{.+}} sret([10 x i8]) align [[RUST_ALIGN:2]] dereferenceable(10) [[RET_PTR:%.+]]) | ||
| #[no_mangle] | ||
| pub unsafe fn return_fiveu16s() -> FiveU16s { | ||
| // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. | ||
|
|
||
| // powerpc64: call void @returns_fiveu16s(ptr {{.+}} [[RET_PTR]]) | ||
|
|
||
|
|
||
| // The other targets copy the cast ABI type to the sret pointer. | ||
|
|
||
| // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] | ||
| // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] | ||
| // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] | ||
|
|
||
| // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() | ||
| // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() | ||
| // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() | ||
|
|
||
| // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
|
|
||
| // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RET_PTR]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 10, i1 false) | ||
| // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RET_PTR]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 10, i1 false) | ||
| // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RET_PTR]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 10, i1 false) | ||
| returns_fiveu16s() | ||
| } | ||
|
|
||
| // CHECK-LABEL: @call_doubledouble | ||
| #[no_mangle] | ||
| pub unsafe fn call_doubledouble() { | ||
| // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x double\]]], align [[ABI_ALIGN:8]] | ||
| // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] | ||
| // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] | ||
| // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] | ||
|
|
||
| // CHECK: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] | ||
|
|
||
| // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) | ||
| // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // CHECK: call void @receives_doubledouble([[ABI_TYPE]] [[ABI_VALUE]]) | ||
| let x = DoubleDouble { f: 1., g: 2. }; | ||
| receives_doubledouble(x); | ||
| } | ||
|
|
||
| // CHECK-LABEL: @return_doubledouble | ||
| #[no_mangle] | ||
| pub unsafe fn return_doubledouble() -> DoubleDouble { | ||
| // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. | ||
|
|
||
| // powerpc64: [[RETVAL:%.+]] = alloca %DoubleDouble, align 8 | ||
| // powerpc64: call void @returns_doubledouble(ptr {{.+}} [[RETVAL]]) | ||
|
|
||
|
|
||
| // The other targets copy the cast ABI type to an alloca. | ||
|
|
||
| // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x double\]]], align [[ABI_ALIGN:8]] | ||
| // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] | ||
| // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] | ||
|
|
||
| // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] | ||
| // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] | ||
| // sparc64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] | ||
|
|
||
| // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() | ||
| // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() | ||
| // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() | ||
|
|
||
| // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
|
|
||
| // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) | ||
| // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) | ||
| // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) | ||
| returns_doubledouble() | ||
| } | ||
|
|
||
| // CHECK-LABEL: @call_doublefloat | ||
| #[no_mangle] | ||
| pub unsafe fn call_doublefloat() { | ||
| // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] | ||
| // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]] | ||
| // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] | ||
| // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float, i32, i64 }]], align [[ABI_ALIGN:8]] | ||
|
|
||
| // CHECK: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] | ||
|
|
||
| // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) | ||
| // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 12, i1 false) | ||
| // powerpc64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) | ||
| // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) | ||
|
|
||
| // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // CHECK: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]]) | ||
| let x = DoubleFloat { f: 1., g: 2. }; | ||
| receives_doublefloat(x); | ||
| } | ||
|
|
||
| // CHECK-LABEL: @return_doublefloat | ||
| #[no_mangle] | ||
| pub unsafe fn return_doublefloat() -> DoubleFloat { | ||
| // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. | ||
|
|
||
| // powerpc64: [[RETVAL:%.+]] = alloca %DoubleFloat, align 8 | ||
| // powerpc64: call void @returns_doublefloat(ptr {{.+}} [[RETVAL]]) | ||
|
|
||
|
|
||
| // The other targets copy the cast ABI type to an alloca. | ||
|
|
||
| // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] | ||
| // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]] | ||
| // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float, i32, i64 }]], align [[ABI_ALIGN:8]] | ||
|
|
||
| // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] | ||
| // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] | ||
| // sparc64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] | ||
|
|
||
| // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat() | ||
| // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat() | ||
| // sparc64: [[ABI_VALUE:%.+]] = call inreg [[ABI_TYPE]] @returns_doublefloat() | ||
|
|
||
| // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
| // sparc64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] | ||
|
|
||
| // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) | ||
| // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 12, i1 false) | ||
| // sparc64: call void @llvm.memcpy.{{.+}}(ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], i64 16, i1 false) | ||
| returns_doublefloat() | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ double, float, i32, i64 }is almost certainly the wrong type.But, if you try to use
struct DoubleFloaton sparc64 on stable, it crashes (https://godbolt.org/z/bKn6d5jeM), so this isn't a regression.So, I don't think this needs to be fixed as part of this PR. Opened #122620 to track this issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upon reflection, I think this would be a regression. It's better to ICE than to generate incorrect code.
Pushed some commits to remove the ICE fix and instead cfg out this test on sparc.