Skip to content

riscv64gc-unknown-linux-gnu extern "C" ABI violates repr(transparent) on unions #115481

Closed
@RalfJung

Description

@RalfJung
Member

The types (i32, f32) and MaybeUninit<T> do not have the same ABI, as demonstrated by this testcase:

#![feature(rustc_attrs)]

type T = (i32, f32);

#[rustc_abi(debug)]
extern "C" fn test1(_x: T) {}

#[rustc_abi(debug)]
extern "C" fn test2(_x: std::mem::MaybeUninit<T>) {}

fn main() {}

The first is

                   mode: Cast(
                       CastTarget {
                           prefix: [
                               Some(
                                   Reg {
                                       kind: Integer,
                                       size: Size(4 bytes),
                                   },
                               ),
                               None,
                               None,
                               None,
                               None,
                               None,
                               None,
                               None,
                           ],
                           rest: Uniform {
                               unit: Reg {
                                   kind: Float,
                                   size: Size(4 bytes),
                               },
                               total: Size(4 bytes),
                           },
                           attrs: ArgAttributes {
                               regular: (empty),
                               arg_ext: None,
                               pointee_size: Size(0 bytes),
                               pointee_align: None,
                           },
                       },
                       false,
                   ),

The second is

                   mode: Cast(
                       CastTarget {
                           prefix: [
                               None,
                               None,
                               None,
                               None,
                               None,
                               None,
                               None,
                               None,
                           ],
                           rest: Uniform {
                               unit: Reg {
                                   kind: Integer,
                                   size: Size(8 bytes),
                               },
                               total: Size(8 bytes),
                           },
                           attrs: ArgAttributes {
                               regular: (empty),
                               arg_ext: None,
                               pointee_size: Size(0 bytes),
                               pointee_align: None,
                           },
                       },
                       false,
                   ),

Not sure whom to ping for RISC-V issues.

Activity

added
I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness
O-riscvTarget: RISC-V architecture
A-ABIArea: Concerning the application binary interface (ABI)
on Sep 2, 2023
added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Sep 2, 2023
RalfJung

RalfJung commented on Sep 2, 2023

@RalfJung
MemberAuthor

I think the fix will have to be to treat repr(transparent) unions specially somewhere around here

FieldsShape::Union(_) => {
if !arg_layout.is_zst() {
return Err(CannotUseFpConv);
}
}

RalfJung

RalfJung commented on Sep 3, 2023

@RalfJung
MemberAuthor
msizanoen1

msizanoen1 commented on Sep 3, 2023

@msizanoen1
Contributor

@RalfJung I'm afraid that the semantics of #[repr(transparent)] on unions are not clearly defined enough to figure out exactly how they should be specially treated (which variant should be used? etc.). Can you ping other people who have more knowledge on this? (If repr(transparent) on unions turns out to be incompatible with ABIs that have struct content destructuring semantics that depends on the types of the field in the struct (e.g. the RISC-V C psABI) then we definitely have a bigger problem.)

RalfJung

RalfJung commented on Sep 3, 2023

@RalfJung
MemberAuthor

I have no idea who would know anything about RISC-V calling conventions. 🤷 and no other ABI is failing this test.

Basically, when the ABI description says "unions do X", then this should only apply to repr(C) and repr(Rust) unions. A repr(transparent) union must be treated exactly like its non-ZST field.

added
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Sep 4, 2023

8 remaining items

added 3 commits that reference this issue on Sep 7, 2023

Auto merge of rust-lang#115372 - RalfJung:abi-assert-eq, r=davidtwco

Auto merge of rust-lang#115372 - RalfJung:abi-assert-eq, r=davidtwco

Auto merge of rust-lang#115372 - RalfJung:abi-assert-eq, r=davidtwco

added a commit that references this issue on Sep 19, 2023

Rollup merge of rust-lang#115499 - msizanoen1:riscv-fix-transparent-u…

edd7be5
added a commit that references this issue on Sep 19, 2023
tgross35

tgross35 commented on Sep 19, 2023

@tgross35
Contributor

@RalfJung now that this is fixed, is there a CI test to catch regressions?

RalfJung

RalfJung commented on Sep 19, 2023

@RalfJung
MemberAuthor

There is a test in tests/ui/abi/compatibility.rs but we don't run tests for riscv, since it's a tier 2 target.

RalfJung

RalfJung commented on Sep 19, 2023

@RalfJung
MemberAuthor

Also see #115609 for another ABI issue that affects riscv (and more).

tgross35

tgross35 commented on Sep 19, 2023

@tgross35
Contributor

Are tier 2 tests run once before release or anything like that? It seems like at least a subset of tests (this one) are important enough that we should raise a red flag if we brake them somehow on any targets. But that doesn't fit well into the tiering structure...

RalfJung

RalfJung commented on Sep 20, 2023

@RalfJung
MemberAuthor

I'm not aware of any process like that. Part of the point of being tier 2 is not to burden all contributors with keeping the target working, is it? If we do want to accept that burden, we could consider running something like ./x.py test codegen && ./x.py test ui --test-args abi for tier 2 targets.

But having this discussion in a closed issue makes little sense. Do you want to open a new issue or Zulip thread for discussing tier 2 target test coverage?

RalfJung

RalfJung commented on Sep 21, 2023

@RalfJung
MemberAuthor

Inspired by #116004 I found a way to have a test for this: #116030.

tgross35

tgross35 commented on Sep 21, 2023

@tgross35
Contributor

Awesome! Thanks for the update here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ABIArea: Concerning the application binary interface (ABI)I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-riscvTarget: RISC-V architectureP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @RalfJung@apiraino@tgross35@rustbot@Noratrieb

      Issue actions

        riscv64gc-unknown-linux-gnu `extern "C"` ABI violates repr(transparent) on unions · Issue #115481 · rust-lang/rust