-
Notifications
You must be signed in to change notification settings - Fork 13.4k
__int128 stack calling conventions are incorrect on x86-64 #41784
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
Comments
Do we also put half in a register and half in memory if we've already used 5 GPRs before we get to the i128? |
These bugs are related: |
This patch might work. I based this of some similar code in AArch64
|
I was wondering why Clang's ABI handling doesn't end up passing this explicitly on the stack, and it seems like this is the reason: llvm-project/clang/lib/CodeGen/Targets/X86.cpp Lines 2155 to 2171 in 91af0d0
As the comment indicates the assumption is, indeed, optimistic... |
Candidate patch: https://reviews.llvm.org/D158169 |
The x86_64 SysV ABI specifies that __int128 is passed either in two registers (if available) or in a 16 byte aligned stack slot. GCC implements this behavior. However, if only one free register is available, LLVM will instead pass one half of the i128 in a register, and the other on the stack. Make sure that either both are passed in registers or both on the stack. Fixes llvm#41784. The patch is basically what craig.topper proposed to do there. Differential Revision: https://reviews.llvm.org/D158169
The x86_64 SysV ABI specifies that __int128 is passed either in two registers (if available) or in a 16 byte aligned stack slot. GCC implements this behavior. However, if only one free register is available, LLVM will instead pass one half of the i128 in a register, and the other on the stack. Make sure that either both are passed in registers or both on the stack. Fixes llvm#41784. The patch is basically what craig.topper proposed to do there. Differential Revision: https://reviews.llvm.org/D158169
The x86_64 SysV ABI specifies that __int128 is passed either in two registers (if available) or in a 16 byte aligned stack slot. GCC implements this behavior. However, if only one free register is available, LLVM will instead pass one half of the i128 in a register, and the other on the stack. Make sure that either both are passed in registers or both on the stack. Fixes llvm#41784. The patch is basically what craig.topper proposed to do there. Differential Revision: https://reviews.llvm.org/D158169
The x86_64 SysV ABI specifies that __int128 is passed either in two registers (if available) or in a 16 byte aligned stack slot. GCC implements this behavior. However, if only one free register is available, LLVM will instead pass one half of the i128 in a register, and the other on the stack. Make sure that either both are passed in registers or both on the stack. Fixes llvm#41784. The patch is basically what craig.topper proposed to do there. Differential Revision: https://reviews.llvm.org/D158169
The x86_64 SysV ABI specifies that __int128 is passed either in two registers (if available) or in a 16 byte aligned stack slot. GCC implements this behavior. However, if only one free register is available, LLVM will instead pass one half of the i128 in a register, and the other on the stack. Make sure that either both are passed in registers or both on the stack. Fixes llvm#41784. The patch is basically what craig.topper proposed to do there. Differential Revision: https://reviews.llvm.org/D158169
The x86_64 SysV ABI specifies that __int128 is passed either in two registers (if available) or in a 16 byte aligned stack slot. GCC implements this behavior. However, if only one free register is available, LLVM will instead pass one half of the i128 in a register, and the other on the stack. Make sure that either both are passed in registers or both on the stack. Fixes llvm#41784. The patch is basically what craig.topper proposed to do there. Differential Revision: https://reviews.llvm.org/D158169
The x86_64 SysV ABI specifies that __int128 is passed either in two registers (if available) or in a 16 byte aligned stack slot. GCC implements this behavior. However, if only one free register is available, LLVM will instead pass one half of the i128 in a register, and the other on the stack. Make sure that either both are passed in registers or both on the stack. Fixes llvm#41784. The patch is basically what craig.topper proposed to do there. Differential Revision: https://reviews.llvm.org/D158169
The x86_64 SysV ABI specifies that __int128 is passed either in two registers (if available) or in a 16 byte aligned stack slot. GCC implements this behavior. However, if only one free register is available, LLVM will instead pass one half of the i128 in a register, and the other on the stack. Make sure that either both are passed in registers or both on the stack. Fixes llvm#41784. The patch is basically what craig.topper proposed to do there. Differential Revision: https://reviews.llvm.org/D158169 (cherry picked from commit fa1b6e6)
Extended Description
This is a bug report that was posted internally at Google, since the user can't register here on bugs.llvm.org:
Clang violates x86-64 calling convention in the obscure case when __int128 is passed on stack.
Conside the following two functions:
Gcc generates identical code for these because __int128 have to be stored aligned on stack (psABI says:
Arguments of type __int128 offer the same operations as INTEGERs, yet they do not fit into one general purpose register but require two registers.
For classification purposes __int128 is treated as if it were implemented as:
typedef struct {
long low, high;
} __int128;
with the exception that arguments of type __int128 that are stored in memory must be aligned on a 16-byte boundary.
Clang generates different code for these two functions:
https://godbolt.org/z/ZKjb4Z
Note that both GCC and Clang show the alignment of __int128 properly as 16 bytes, but this is only getting ignored when the variable is passed on the stack.
The text was updated successfully, but these errors were encountered: