Skip to content

Commit c166a43

Browse files
authored
New calling convention preserve_none (#76868)
The new experimental calling convention preserve_none is the opposite side of existing preserve_all. It tries to preserve as few general registers as possible. So all general registers are caller saved registers. It can also uses more general registers to pass arguments. This attribute doesn't impact floating-point registers. Floating-point registers still follow the c calling convention. Currently preserve_none is supported on X86-64 only. It changes the c calling convention in following fields: * RSP and RBP are the only preserved general registers, all other general registers are caller saved registers. * We can use [RDI, RSI, RDX, RCX, R8, R9, R11, R12, R13, R14, R15, RAX] to pass arguments. It can improve the performance of hot tailcall chain, because many callee saved registers' save/restore instructions can be removed if the tail functions are using preserve_none. In my experiment in protocol buffer, the parsing functions are improved by 3% to 10%.
1 parent 7670609 commit c166a43

38 files changed

+635
-3
lines changed

clang/include/clang-c/Index.h

+1
Original file line numberDiff line numberDiff line change
@@ -2986,6 +2986,7 @@ enum CXCallingConv {
29862986
CXCallingConv_SwiftAsync = 17,
29872987
CXCallingConv_AArch64SVEPCS = 18,
29882988
CXCallingConv_M68kRTD = 19,
2989+
CXCallingConv_PreserveNone = 20,
29892990

29902991
CXCallingConv_Invalid = 100,
29912992
CXCallingConv_Unexposed = 200

clang/include/clang/Basic/Attr.td

+6
Original file line numberDiff line numberDiff line change
@@ -2959,6 +2959,12 @@ def M68kRTD: DeclOrTypeAttr {
29592959
let Documentation = [M68kRTDDocs];
29602960
}
29612961

2962+
def PreserveNone : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86> {
2963+
let Spellings = [Clang<"preserve_none">];
2964+
let Subjects = SubjectList<[FunctionLike]>;
2965+
let Documentation = [PreserveNoneDocs];
2966+
}
2967+
29622968
def Target : InheritableAttr {
29632969
let Spellings = [GCC<"target">];
29642970
let Args = [StringArgument<"featuresStr">];

clang/include/clang/Basic/AttrDocs.td

+17
Original file line numberDiff line numberDiff line change
@@ -5506,6 +5506,23 @@ experimental at this time.
55065506
}];
55075507
}
55085508

5509+
def PreserveNoneDocs : Documentation {
5510+
let Category = DocCatCallingConvs;
5511+
let Content = [{
5512+
On X86-64 target, this attribute changes the calling convention of a function.
5513+
The ``preserve_none`` calling convention tries to preserve as few general
5514+
registers as possible. So all general registers are caller saved registers. It
5515+
also uses more general registers to pass arguments. This attribute doesn't
5516+
impact floating-point registers (XMMs/YMMs). Floating-point registers still
5517+
follow the c calling convention.
5518+
5519+
- Only RSP and RBP are preserved by callee.
5520+
5521+
- Register RDI, RSI, RDX, RCX, R8, R9, R11, R12, R13, R14, R15 and RAX now can
5522+
be used to pass function arguments.
5523+
}];
5524+
}
5525+
55095526
def DeprecatedDocs : Documentation {
55105527
let Category = DocCatDecl;
55115528
let Content = [{

clang/include/clang/Basic/Specifiers.h

+1
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ namespace clang {
295295
CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs))
296296
CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel))
297297
CC_M68kRTD, // __attribute__((m68k_rtd))
298+
CC_PreserveNone, // __attribute__((preserve_none))
298299
};
299300

300301
/// Checks whether the given calling convention supports variadic

clang/lib/AST/ItaniumMangle.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -3443,6 +3443,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
34433443
case CC_PreserveMost:
34443444
case CC_PreserveAll:
34453445
case CC_M68kRTD:
3446+
case CC_PreserveNone:
34463447
// FIXME: we should be mangling all of the above.
34473448
return "";
34483449

clang/lib/AST/Type.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -3438,6 +3438,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
34383438
case CC_PreserveMost: return "preserve_most";
34393439
case CC_PreserveAll: return "preserve_all";
34403440
case CC_M68kRTD: return "m68k_rtd";
3441+
case CC_PreserveNone: return "preserve_none";
34413442
}
34423443

34433444
llvm_unreachable("Invalid calling convention.");
@@ -3990,6 +3991,7 @@ bool AttributedType::isCallingConv() const {
39903991
case attr::PreserveMost:
39913992
case attr::PreserveAll:
39923993
case attr::M68kRTD:
3994+
case attr::PreserveNone:
39933995
return true;
39943996
}
39953997
llvm_unreachable("invalid attr kind");

clang/lib/AST/TypePrinter.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info,
10671067
case CC_M68kRTD:
10681068
OS << " __attribute__((m68k_rtd))";
10691069
break;
1070+
case CC_PreserveNone:
1071+
OS << " __attribute__((preserve_none))";
1072+
break;
10701073
}
10711074
}
10721075

@@ -1911,6 +1914,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
19111914
case attr::M68kRTD:
19121915
OS << "m68k_rtd";
19131916
break;
1917+
case attr::PreserveNone:
1918+
OS << "preserve_none";
1919+
break;
19141920
case attr::NoDeref:
19151921
OS << "noderef";
19161922
break;

clang/lib/Basic/Targets/X86.h

+2
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
777777
case CC_Win64:
778778
case CC_PreserveMost:
779779
case CC_PreserveAll:
780+
case CC_PreserveNone:
780781
case CC_X86RegCall:
781782
case CC_OpenCLKernel:
782783
return CCCR_OK;
@@ -854,6 +855,7 @@ class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
854855
case CC_IntelOclBicc:
855856
case CC_PreserveMost:
856857
case CC_PreserveAll:
858+
case CC_PreserveNone:
857859
case CC_X86_64SysV:
858860
case CC_Swift:
859861
case CC_SwiftAsync:

clang/lib/CodeGen/CGCall.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
7373
case CC_Swift: return llvm::CallingConv::Swift;
7474
case CC_SwiftAsync: return llvm::CallingConv::SwiftTail;
7575
case CC_M68kRTD: return llvm::CallingConv::M68k_RTD;
76+
case CC_PreserveNone: return llvm::CallingConv::PreserveNone;
7677
}
7778
}
7879

@@ -256,6 +257,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
256257
if (D->hasAttr<M68kRTDAttr>())
257258
return CC_M68kRTD;
258259

260+
if (D->hasAttr<PreserveNoneAttr>())
261+
return CC_PreserveNone;
262+
259263
return CC_C;
260264
}
261265

clang/lib/CodeGen/CGDebugInfo.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,8 @@ static unsigned getDwarfCC(CallingConv CC) {
14501450
return llvm::dwarf::DW_CC_LLVM_X86RegCall;
14511451
case CC_M68kRTD:
14521452
return llvm::dwarf::DW_CC_LLVM_M68kRTD;
1453+
case CC_PreserveNone:
1454+
return llvm::dwarf::DW_CC_LLVM_PreserveNone;
14531455
}
14541456
return 0;
14551457
}

clang/lib/Sema/SemaDeclAttr.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -5235,6 +5235,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
52355235
case ParsedAttr::AT_M68kRTD:
52365236
D->addAttr(::new (S.Context) M68kRTDAttr(S.Context, AL));
52375237
return;
5238+
case ParsedAttr::AT_PreserveNone:
5239+
D->addAttr(::new (S.Context) PreserveNoneAttr(S.Context, AL));
5240+
return;
52385241
default:
52395242
llvm_unreachable("unexpected attribute kind");
52405243
}
@@ -5441,6 +5444,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
54415444
case ParsedAttr::AT_M68kRTD:
54425445
CC = CC_M68kRTD;
54435446
break;
5447+
case ParsedAttr::AT_PreserveNone:
5448+
CC = CC_PreserveNone;
5449+
break;
54445450
default: llvm_unreachable("unexpected attribute kind");
54455451
}
54465452

@@ -9559,6 +9565,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
95599565
case ParsedAttr::AT_AArch64SVEPcs:
95609566
case ParsedAttr::AT_AMDGPUKernelCall:
95619567
case ParsedAttr::AT_M68kRTD:
9568+
case ParsedAttr::AT_PreserveNone:
95629569
handleCallConvAttr(S, D, AL);
95639570
break;
95649571
case ParsedAttr::AT_Suppress:

clang/lib/Sema/SemaType.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
137137
case ParsedAttr::AT_IntelOclBicc: \
138138
case ParsedAttr::AT_PreserveMost: \
139139
case ParsedAttr::AT_PreserveAll: \
140-
case ParsedAttr::AT_M68kRTD
140+
case ParsedAttr::AT_M68kRTD: \
141+
case ParsedAttr::AT_PreserveNone
141142

142143
// Function type attributes.
143144
#define FUNCTION_TYPE_ATTRS_CASELIST \
@@ -7919,6 +7920,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
79197920
return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
79207921
case ParsedAttr::AT_M68kRTD:
79217922
return createSimpleAttr<M68kRTDAttr>(Ctx, Attr);
7923+
case ParsedAttr::AT_PreserveNone:
7924+
return createSimpleAttr<PreserveNoneAttr>(Ctx, Attr);
79227925
}
79237926
llvm_unreachable("unexpected attribute kind!");
79247927
}

clang/test/CodeGen/debug-info-cc.c

+7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
// CC_SwiftAsync, // __attribute__((swiftasynccall))
2323
// CC_PreserveMost, // __attribute__((preserve_most))
2424
// CC_PreserveAll, // __attribute__((preserve_all))
25+
// CC_PreserveNone, // __attribute__((preserve_none))
2526
// };
2627

2728
#ifdef __x86_64__
@@ -51,6 +52,12 @@ __attribute__((preserve_all)) int add_preserve_all(int a, int b) {
5152
return a+b;
5253
}
5354

55+
// LINUX: !DISubprogram({{.*}}"add_preserve_none", {{.*}}type: ![[FTY:[0-9]+]]
56+
// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_PreserveNone,
57+
__attribute__((preserve_none)) int add_preserve_none(int a, int b) {
58+
return a+b;
59+
}
60+
5461
// LINUX: !DISubprogram({{.*}}"add_swiftcall", {{.*}}type: ![[FTY:[0-9]+]]
5562
// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_Swift,
5663
__attribute__((swiftcall)) int add_swiftcall(int a, int b) {

clang/test/CodeGen/preserve-call-conv.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm < %s | FileCheck %s
1+
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm < %s | FileCheck %s --check-prefixes=CHECK,X86-LINUX
22
// RUN: %clang_cc1 -triple arm64-unknown-unknown -emit-llvm < %s | FileCheck %s
33

44
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -emit-llvm %s -o - | FileCheck %s
@@ -19,3 +19,9 @@ void boo(void) __attribute__((preserve_all)) {
1919
// CHECK-LABEL: define {{(dso_local )?}}preserve_allcc void @boo()
2020
}
2121

22+
// Check that the preserve_none calling convention attribute at the source level
23+
// is lowered to the corresponding calling convention attrribute at the LLVM IR
24+
// level.
25+
void bar(void) __attribute__((preserve_none)) {
26+
// X86-LINUX-LABEL: define {{(dso_local )?}}preserve_nonecc void @bar()
27+
}

clang/test/Misc/pragma-attribute-supported-attributes-list.test

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163
// CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter)
164164
// CHECK-NEXT: PatchableFunctionEntry (SubjectMatchRule_function, SubjectMatchRule_objc_method)
165165
// CHECK-NEXT: Pointer (SubjectMatchRule_record_not_is_union)
166+
// CHECK-NEXT: PreserveNone (SubjectMatchRule_hasType_functionType)
166167
// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record)
167168
// CHECK-NEXT: ReadOnlyPlacement (SubjectMatchRule_record)
168169
// CHECK-NEXT: ReleaseHandle (SubjectMatchRule_variable_is_parameter)

clang/test/Sema/no_callconv.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ void __attribute__((swiftasynccall)) funcKK() {} // expected-error {{'swiftasync
1515
void __attribute__((pascal)) funcG() {} // expected-error {{'pascal' calling convention is not supported for this target}}
1616
void __attribute__((preserve_most)) funcL() {} // expected-error {{'preserve_most' calling convention is not supported for this target}}
1717
void __attribute__((preserve_all)) funcM() {} // expected-error {{'preserve_all' calling convention is not supported for this target}}
18+
void __attribute__((preserve_none)) funcN() {} // expected-error {{'preserve_none' calling convention is not supported for this target}}
1819
void __attribute__((stdcall)) funcD() {} // expected-error {{'stdcall' calling convention is not supported for this target}}
1920
void __attribute__((fastcall)) funcE() {} // expected-error {{'fastcall' calling convention is not supported for this target}}
2021
void __attribute__((thiscall)) funcF() {} // expected-error {{'thiscall' calling convention is not supported for this target}}
@@ -30,6 +31,7 @@ void __attribute__((swiftcall)) funcK() {}
3031
void __attribute__((swiftasynccall)) funcKK() {}
3132
void __attribute__((preserve_most)) funcL() {}
3233
void __attribute__((preserve_all)) funcM() {}
34+
void __attribute__((preserve_none)) funcN() {}
3335

3436
// Same function with different calling conventions. Error with a note pointing to the last decl.
3537
void __attribute__((preserve_all)) funcR(); // expected-note {{previous declaration is here}}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 %s -fsyntax-only -triple x86_64-unknown-unknown -verify
2+
3+
typedef void typedef_fun_t(int);
4+
5+
void __attribute__((preserve_none)) boo(void *ptr) {
6+
}
7+
8+
void __attribute__((preserve_none(1))) boo1(void *ptr) { // expected-error {{'preserve_none' attribute takes no arguments}}
9+
}
10+
11+
void (__attribute__((preserve_none)) *pboo1)(void *) = boo;
12+
13+
void (__attribute__((cdecl)) *pboo2)(void *) = boo; // expected-error {{incompatible function pointer types initializing 'void (*)(void *) __attribute__((cdecl))' with an expression of type 'void (void *) __attribute__((preserve_none))'}}
14+
void (*pboo3)(void *) = boo; // expected-error {{incompatible function pointer types initializing 'void (*)(void *)' with an expression of type 'void (void *) __attribute__((preserve_none))'}}
15+
16+
typedef_fun_t typedef_fun_boo; // expected-note {{previous declaration is here}}
17+
void __attribute__((preserve_none)) typedef_fun_boo(int x) { } // expected-error {{function declared 'preserve_none' here was previously declared without calling convention}}
18+
19+
struct type_test_boo {} __attribute__((preserve_none)); // expected-warning {{'preserve_none' attribute only applies to functions and function pointers}}

clang/tools/libclang/CXType.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
679679
TCALLINGCONV(PreserveMost);
680680
TCALLINGCONV(PreserveAll);
681681
TCALLINGCONV(M68kRTD);
682+
TCALLINGCONV(PreserveNone);
682683
case CC_SpirFunction: return CXCallingConv_Unexposed;
683684
case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed;
684685
case CC_OpenCLKernel: return CXCallingConv_Unexposed;

llvm/docs/LangRef.rst

+7
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,13 @@ added in the future:
421421
This calling convention, like the `PreserveMost` calling convention, will be
422422
used by a future version of the ObjectiveC runtime and should be considered
423423
experimental at this time.
424+
"``preserve_nonecc``" - The `PreserveNone` calling convention
425+
This calling convention doesn't preserve any general registers. So all
426+
general registers are caller saved registers. It also uses all general
427+
registers to pass arguments. This attribute doesn't impact non-general
428+
purpose registers (e.g. floating point registers, on X86 XMMs/YMMs).
429+
Non-general purpose registers still follow the standard c calling
430+
convention. Currently it is for x86_64 only.
424431
"``cxx_fast_tlscc``" - The `CXX_FAST_TLS` calling convention for access functions
425432
Clang generates an access function to access C++-style TLS. The access
426433
function generally has an entry block, an exit block and an initialization

llvm/include/llvm/AsmParser/LLToken.h

+1
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ enum Kind {
160160
kw_swifttailcc,
161161
kw_preserve_mostcc,
162162
kw_preserve_allcc,
163+
kw_preserve_nonecc,
163164
kw_ghccc,
164165
kw_x86_intrcc,
165166
kw_hhvmcc,

llvm/include/llvm/BinaryFormat/Dwarf.def

+1
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,7 @@ HANDLE_DW_CC(0xc9, LLVM_PreserveMost)
10381038
HANDLE_DW_CC(0xca, LLVM_PreserveAll)
10391039
HANDLE_DW_CC(0xcb, LLVM_X86RegCall)
10401040
HANDLE_DW_CC(0xcc, LLVM_M68kRTD)
1041+
HANDLE_DW_CC(0xcd, LLVM_PreserveNone)
10411042
// From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently
10421043
// generated by any toolchain. It is used internally to GDB to indicate OpenCL
10431044
// C functions that have been compiled with the IBM XL C for OpenCL compiler and

llvm/include/llvm/IR/CallingConv.h

+3
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ namespace CallingConv {
8686
/// their stack.
8787
SwiftTail = 20,
8888

89+
/// Used for runtime calls that preserves none general registers.
90+
PreserveNone = 21,
91+
8992
/// This is the start of the target-specific calling conventions, e.g.
9093
/// fastcall and thiscall on X86.
9194
FirstTargetCC = 64,

llvm/lib/AsmParser/LLLexer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ lltok::Kind LLLexer::LexIdentifier() {
617617
KEYWORD(anyregcc);
618618
KEYWORD(preserve_mostcc);
619619
KEYWORD(preserve_allcc);
620+
KEYWORD(preserve_nonecc);
620621
KEYWORD(ghccc);
621622
KEYWORD(x86_intrcc);
622623
KEYWORD(hhvmcc);

llvm/lib/AsmParser/LLParser.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2109,6 +2109,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) {
21092109
/// ::= 'anyregcc'
21102110
/// ::= 'preserve_mostcc'
21112111
/// ::= 'preserve_allcc'
2112+
/// ::= 'preserve_nonecc'
21122113
/// ::= 'ghccc'
21132114
/// ::= 'swiftcc'
21142115
/// ::= 'swifttailcc'
@@ -2169,6 +2170,7 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
21692170
case lltok::kw_anyregcc: CC = CallingConv::AnyReg; break;
21702171
case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break;
21712172
case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break;
2173+
case lltok::kw_preserve_nonecc:CC = CallingConv::PreserveNone; break;
21722174
case lltok::kw_ghccc: CC = CallingConv::GHC; break;
21732175
case lltok::kw_swiftcc: CC = CallingConv::Swift; break;
21742176
case lltok::kw_swifttailcc: CC = CallingConv::SwiftTail; break;

llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,9 @@ void DWARFTypePrinter::appendSubroutineNameAfter(
616616
case CallingConvention::DW_CC_LLVM_PreserveAll:
617617
OS << " __attribute__((preserve_all))";
618618
break;
619+
case CallingConvention::DW_CC_LLVM_PreserveNone:
620+
OS << " __attribute__((preserve_none))";
621+
break;
619622
case CallingConvention::DW_CC_LLVM_X86RegCall:
620623
OS << " __attribute__((regcall))";
621624
break;

llvm/lib/IR/AsmWriter.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
304304
case CallingConv::AnyReg: Out << "anyregcc"; break;
305305
case CallingConv::PreserveMost: Out << "preserve_mostcc"; break;
306306
case CallingConv::PreserveAll: Out << "preserve_allcc"; break;
307+
case CallingConv::PreserveNone: Out << "preserve_nonecc"; break;
307308
case CallingConv::CXX_FAST_TLS: Out << "cxx_fast_tlscc"; break;
308309
case CallingConv::GHC: Out << "ghccc"; break;
309310
case CallingConv::Tail: Out << "tailcc"; break;

llvm/lib/Target/X86/X86CallingConv.td

+19
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,23 @@ def CC_Intel_OCL_BI : CallingConv<[
10561056
CCDelegateTo<CC_X86_32_C>
10571057
]>;
10581058

1059+
def CC_X86_64_Preserve_None : CallingConv<[
1060+
// We don't preserve general registers, so all of them can be used to pass
1061+
// arguments except
1062+
// - RBP frame pointer
1063+
// - R10 'nest' parameter
1064+
// - RBX base pointer
1065+
// - R16 - R31 these are not available everywhere
1066+
CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D,
1067+
R11D, R12D, R13D, R14D, R15D, EAX]>>,
1068+
1069+
CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8, R9,
1070+
R11, R12, R13, R14, R15, RAX]>>,
1071+
1072+
// Otherwise it's the same as the regular C calling convention.
1073+
CCDelegateTo<CC_X86_64_C>
1074+
]>;
1075+
10591076
//===----------------------------------------------------------------------===//
10601077
// X86 Root Argument Calling Conventions
10611078
//===----------------------------------------------------------------------===//
@@ -1095,6 +1112,7 @@ def CC_X86_64 : CallingConv<[
10951112
CCIfCC<"CallingConv::X86_RegCall",
10961113
CCIfSubtarget<"isTargetWin64()", CCDelegateTo<CC_X86_Win64_RegCall>>>,
10971114
CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo<CC_X86_SysV64_RegCall>>,
1115+
CCIfCC<"CallingConv::PreserveNone", CCDelegateTo<CC_X86_64_Preserve_None>>,
10981116
CCIfCC<"CallingConv::X86_INTR", CCCustom<"CC_X86_Intr">>,
10991117

11001118
// Mingw64 and native Win64 use Win64 CC
@@ -1184,6 +1202,7 @@ def CSR_64_AllRegs_AVX512 : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX,
11841202
(sequence "ZMM%u", 0, 31),
11851203
(sequence "K%u", 0, 7)),
11861204
(sequence "XMM%u", 0, 15))>;
1205+
def CSR_64_NoneRegs : CalleeSavedRegs<(add RBP)>;
11871206

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

0 commit comments

Comments
 (0)