Skip to content

Commit 50cce89

Browse files
committed
Implement preserve_none for 32-bit x86
1 parent 033df38 commit 50cce89

File tree

10 files changed

+456
-131
lines changed

10 files changed

+456
-131
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6433,13 +6433,15 @@ experimental at this time.
64336433
def PreserveNoneDocs : Documentation {
64346434
let Category = DocCatCallingConvs;
64356435
let Content = [{
6436-
On X86-64 and AArch64 targets, this attribute changes the calling convention of a function.
6436+
On X86, X86-64, and AArch64 targets, this attribute changes the calling convention of a function.
64376437
The ``preserve_none`` calling convention tries to preserve as few general
64386438
registers as possible. So all general registers are caller saved registers. It
64396439
also uses more general registers to pass arguments. This attribute doesn't
64406440
impact floating-point registers. ``preserve_none``'s ABI is still unstable, and
64416441
may be changed in the future.
64426442

6443+
- On X86, only ESP and EBP are preserved by the callee. Registers EDI, ESI, EDX,
6444+
ECX, and EAX now can be used to pass function arguments.
64436445
- On X86-64, only RSP and RBP are preserved by the callee.
64446446
Registers R12, R13, R14, R15, RDI, RSI, RDX, RCX, R8, R9, R11, and RAX now can
64456447
be used to pass function arguments. Floating-point registers (XMMs/YMMs) still

clang/lib/Basic/Targets/X86.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
406406
case CC_X86RegCall:
407407
case CC_C:
408408
case CC_PreserveMost:
409+
case CC_PreserveNone:
409410
case CC_Swift:
410411
case CC_X86Pascal:
411412
case CC_IntelOclBicc:

clang/test/Sema/preserve-none-call-conv.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: %clang_cc1 %s -fsyntax-only -triple x86_64-unknown-unknown -verify
22
// RUN: %clang_cc1 %s -fsyntax-only -triple aarch64-unknown-unknown -verify
3+
// RUN: %clang_cc1 %s -fsyntax-only -triple i686-unknown-unknown -verify
34

45
typedef void typedef_fun_t(int);
56

llvm/docs/LangRef.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ added in the future:
463463
registers to pass arguments. This attribute doesn't impact non-general
464464
purpose registers (e.g. floating point registers, on X86 XMMs/YMMs).
465465
Non-general purpose registers still follow the standard C calling
466-
convention. Currently it is for x86_64 and AArch64 only.
466+
convention. Currently it is for x86, x86_64, and AArch64 only.
467467
"``cxx_fast_tlscc``" - The `CXX_FAST_TLS` calling convention for access functions
468468
Clang generates an access function to access C++-style Thread Local Storage
469469
(TLS). The access function generally has an entry block, an exit block and an

llvm/lib/Target/X86/X86CallingConv.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,12 @@ def CC_X86_64_Preserve_None : CallingConv<[
10511051
CCDelegateTo<CC_X86_64_C>
10521052
]>;
10531053

1054+
def CC_X86_32_Preserve_None : CallingConv<[
1055+
// 32-bit variant of CC_X86_64_Preserve_None, above.
1056+
CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, EAX]>>,
1057+
CCDelegateTo<CC_X86_32_C>
1058+
]>;
1059+
10541060
//===----------------------------------------------------------------------===//
10551061
// X86 Root Argument Calling Conventions
10561062
//===----------------------------------------------------------------------===//
@@ -1072,6 +1078,7 @@ def CC_X86_32 : CallingConv<[
10721078
CCIfCC<"CallingConv::X86_RegCall",
10731079
CCIfSubtarget<"isTargetWin32()", CCIfRegCallv4<CCDelegateTo<CC_X86_32_RegCallv4_Win>>>>,
10741080
CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo<CC_X86_32_RegCall>>,
1081+
CCIfCC<"CallingConv::PreserveNone", CCDelegateTo<CC_X86_32_Preserve_None>>,
10751082

10761083
// Otherwise, drop to normal X86-32 CC
10771084
CCDelegateTo<CC_X86_32_C>
@@ -1187,6 +1194,7 @@ def CSR_64_AllRegs_AVX512 : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX,
11871194
(sequence "K%u", 0, 7)),
11881195
(sequence "XMM%u", 0, 15))>;
11891196
def CSR_64_NoneRegs : CalleeSavedRegs<(add RBP)>;
1197+
def CSR_32_NoneRegs : CalleeSavedRegs<(add EBP)>;
11901198

11911199
// Standard C + YMM6-15
11921200
def CSR_Win64_Intel_OCL_BI_AVX : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12,

llvm/lib/Target/X86/X86RegisterInfo.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
316316
return CSR_64_RT_AllRegs_AVX_SaveList;
317317
return CSR_64_RT_AllRegs_SaveList;
318318
case CallingConv::PreserveNone:
319-
return CSR_64_NoneRegs_SaveList;
319+
return Is64Bit ? CSR_64_NoneRegs_SaveList : CSR_32_NoneRegs_SaveList;
320320
case CallingConv::CXX_FAST_TLS:
321321
if (Is64Bit)
322322
return MF->getInfo<X86MachineFunctionInfo>()->isSplitCSR() ?
@@ -444,7 +444,7 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
444444
return CSR_64_RT_AllRegs_AVX_RegMask;
445445
return CSR_64_RT_AllRegs_RegMask;
446446
case CallingConv::PreserveNone:
447-
return CSR_64_NoneRegs_RegMask;
447+
return Is64Bit ? CSR_64_NoneRegs_RegMask : CSR_32_NoneRegs_RegMask;
448448
case CallingConv::CXX_FAST_TLS:
449449
if (Is64Bit)
450450
return CSR_64_TLS_Darwin_RegMask;

llvm/test/CodeGen/X86/preserve_none_swift.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: not llc -mtriple=x86_64 %s -o - 2>&1 | FileCheck %s
2+
; RUN: not llc -mtriple=i686 %s -o - 2>&1 | FileCheck %s
23

34
; Swift attributes should not be used with preserve_none.
45

0 commit comments

Comments
 (0)