Skip to content

_BitInt implementation does not conform to x86-64 psABI regarding padding bits #62032

Closed
@leni536

Description

@leni536

clang version: 16.0.0
compiler flags: -std=c2x -O2

Observed behavior

Given the following code:

unsigned char f(unsigned _BitInt(4)* ptr) {
    return *ptr;
}

unsigned char g(_BitInt(4)* ptr) {
    unsigned _BitInt(4) uint = *ptr;
    return uint;
}

The generated code for f and g does not mask out "unused" bits from *ptr:

f:                                      # @f
        movzx   eax, byte ptr [rdi]
        ret
g:                                      # @g
        movzx   eax, byte ptr [rdi]
        ret

https://godbolt.org/z/Ev8sbhb84

Expected behavior

The x86-64 psABI specifies that the unused bits within an object of _BitInt(N) type can take unspecified values:

The value of the unused bits beyond the width of the _BitInt(N) value but within the size of the _BitInt(N) are unspecified when stored in memory or register.

https://gitlab.com/x86-psABIs/x86-64-ABI/-/blob/3177443c4f5862d48f371d91ab36209f73cfe69c/x86-64-ABI/low-level-sys-info.tex#L297-299

This means that *ptr in both cases can have the object representation 0b00010000, representing the signed/unsigned _BitInt(N) value 0. But according to the generated code this object representation is passed as-is to the returned unsigned char in both cases, which translates to the return value 16.

As 0b00010000 is a valid object representation for representing the value 0 here, I would expect both functions to return 0 in this case.

In general this requires masking out the unused bits.

Notes

It looks like the current implementation assumes that valid object representations have all zeroes for the unused bits, and other representations are trap representations.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions