Skip to content

Commit bc5ed56

Browse files
authored
Update calling conventions for OCaml (#22)
1 parent 3acad44 commit bc5ed56

File tree

10 files changed

+124
-31
lines changed

10 files changed

+124
-31
lines changed

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ enum Kind {
173173
kw_amdgpu_kernel,
174174
kw_amdgpu_gfx,
175175
kw_tailcc,
176+
kw_oxcaml_fpcc,
177+
kw_oxcaml_nofpcc,
178+
kw_oxcaml_ccc,
179+
kw_oxcaml_c_stackcc,
180+
kw_oxcaml_alloccc,
176181

177182
// Attributes:
178183
kw_attributes,

llvm/include/llvm/IR/CallingConv.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,12 @@ namespace CallingConv {
241241
/// Preserve X2-X15, X19-X29, SP, Z0-Z31, P0-P15.
242242
AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 = 103,
243243

244-
/// Calling convention for OCaml
245-
OCaml = 104,
246-
247-
/// Special case of the C calling convention for calling from OCaml
248-
OCaml_C_Call = 105,
244+
/// Calling conventions used by OxCaml
245+
OxCaml_WithFP = 104, // normal OxCaml functions (with frame pointers)
246+
OxCaml_WithoutFP = 105, // normal OxCaml functions (w/o frame pointers)
247+
OxCaml_C_Call = 106, // [caml_c_call]
248+
OxCaml_C_Call_StackArgs = 107, // [caml_c_call_stack_args_llvm_backend]
249+
OxCaml_Alloc = 108, // [caml_call_gc] and [caml_local_realloc]
249250

250251
/// The highest possible ID. Must be some 2^k - 1.
251252
MaxID = 1023

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,11 @@ lltok::Kind LLLexer::LexIdentifier() {
631631
KEYWORD(amdgpu_kernel);
632632
KEYWORD(amdgpu_gfx);
633633
KEYWORD(tailcc);
634+
KEYWORD(oxcaml_fpcc);
635+
KEYWORD(oxcaml_nofpcc);
636+
KEYWORD(oxcaml_ccc);
637+
KEYWORD(oxcaml_c_stackcc);
638+
KEYWORD(oxcaml_alloccc);
634639

635640
KEYWORD(cc);
636641
KEYWORD(c);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,6 +2019,11 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) {
20192019
/// ::= 'amdgpu_cs'
20202020
/// ::= 'amdgpu_kernel'
20212021
/// ::= 'tailcc'
2022+
/// ::= 'oxcaml_fpcc'
2023+
/// ::= 'oxcaml_nofpcc'
2024+
/// ::= 'oxcaml_ccc'
2025+
/// ::= 'oxcaml_c_stackcc'
2026+
/// ::= 'oxcaml_alloccc'
20222027
/// ::= 'cc' UINT
20232028
///
20242029
bool LLParser::parseOptionalCallingConv(unsigned &CC) {
@@ -2077,6 +2082,11 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
20772082
case lltok::kw_amdgpu_cs: CC = CallingConv::AMDGPU_CS; break;
20782083
case lltok::kw_amdgpu_kernel: CC = CallingConv::AMDGPU_KERNEL; break;
20792084
case lltok::kw_tailcc: CC = CallingConv::Tail; break;
2085+
case lltok::kw_oxcaml_fpcc: CC = CallingConv::OxCaml_WithFP; break;
2086+
case lltok::kw_oxcaml_nofpcc: CC = CallingConv::OxCaml_WithoutFP; break;
2087+
case lltok::kw_oxcaml_ccc: CC = CallingConv::OxCaml_C_Call; break;
2088+
case lltok::kw_oxcaml_c_stackcc:CC = CallingConv::OxCaml_C_Call_StackArgs; break;
2089+
case lltok::kw_oxcaml_alloccc: CC = CallingConv::OxCaml_Alloc; break;
20802090
case lltok::kw_cc: {
20812091
Lex.Lex();
20822092
return parseUInt32(CC);

llvm/lib/IR/AsmWriter.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,15 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
340340
case CallingConv::AMDGPU_CS: Out << "amdgpu_cs"; break;
341341
case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break;
342342
case CallingConv::AMDGPU_Gfx: Out << "amdgpu_gfx"; break;
343-
case CallingConv::OCaml: Out << "ocamlcc"; break;
343+
case CallingConv::OxCaml_WithFP: Out << "oxcaml_fpcc"; break;
344+
case CallingConv::OxCaml_WithoutFP:
345+
Out << "oxcaml_nofpcc";
346+
break;
347+
case CallingConv::OxCaml_C_Call: Out << "oxcaml_ccc"; break;
348+
case CallingConv::OxCaml_C_Call_StackArgs:
349+
Out << "oxcaml_c_stackcc";
350+
break;
351+
case CallingConv::OxCaml_Alloc: Out << "oxcaml_alloccc"; break;
344352
}
345353
}
346354

llvm/lib/IR/Verifier.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3581,10 +3581,11 @@ void Verifier::verifyMustTailCall(CallInst &CI) {
35813581
AttributeList CalleeAttrs = CI.getAttributes();
35823582
if (CI.getCallingConv() == CallingConv::SwiftTail ||
35833583
CI.getCallingConv() == CallingConv::Tail ||
3584-
CI.getCallingConv() == CallingConv::OCaml) {
3584+
CI.getCallingConv() == CallingConv::OxCaml_WithFP ||
3585+
CI.getCallingConv() == CallingConv::OxCaml_WithoutFP) {
35853586
StringRef CCName =
35863587
CI.getCallingConv() == CallingConv::Tail ? "tailcc" :
3587-
CI.getCallingConv() == CallingConv::SwiftTail ? "swifttailcc" : "ocamlcc";
3588+
CI.getCallingConv() == CallingConv::SwiftTail ? "swifttailcc" : "oxcamlcc";
35883589

35893590
// - Only sret, byval, swiftself, and swiftasync ABI-impacting attributes
35903591
// are allowed in swifttailcc call

llvm/lib/Target/X86/X86CallingConv.td

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -440,12 +440,12 @@ def RetCC_X86_64_HHVM: CallingConv<[
440440
RAX, R10, R11, R13, R14, R15]>>
441441
]>;
442442

443-
def RetCC_X86_64_OCaml : CallingConv<[
443+
def RetCC_X86_64_OxCaml : CallingConv<[
444444
// Promote all types to i64
445445
CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
446446

447447
// Runtime registers (R14, R15) are threaded through function calls
448-
// See the argument calling conventions for OCaml for more details
448+
// See the argument calling conventions for OxCaml for more details
449449
CCIfType<[i64], CCAssignToReg<[R14, R15, RAX, RBX, RDI, RSI, RDX, RCX, R8, R9, R12, R13]>>,
450450

451451
CCIfType<[f32, f64], CCAssignToReg<[
@@ -454,7 +454,13 @@ def RetCC_X86_64_OCaml : CallingConv<[
454454
]>>
455455
]>;
456456

457-
def RetCC_X86_64_OCaml_C_Call : CallingConv<[
457+
def RetCC_X86_64_OxCaml_C_Call : CallingConv<[
458+
CCIfType<[i64], CCAssignToReg<[R14, R15]>>,
459+
460+
CCDelegateTo<RetCC_X86_64_C>
461+
]>;
462+
463+
def RetCC_X86_64_OxCaml_C_Call_StackArgs : CallingConv<[
458464
CCIfType<[i64], CCAssignToReg<[R14, R15]>>,
459465

460466
CCDelegateTo<RetCC_X86_64_C>
@@ -513,9 +519,15 @@ def RetCC_X86_64 : CallingConv<[
513519
// Mingw64 and native Win64 use Win64 CC
514520
CCIfSubtarget<"isTargetWin64()", CCDelegateTo<RetCC_X86_Win64_C>>,
515521

516-
// Handle OCaml calls
517-
CCIfCC<"CallingConv::OCaml", CCDelegateTo<RetCC_X86_64_OCaml>>,
518-
CCIfCC<"CallingConv::OCaml_C_Call", CCDelegateTo<RetCC_X86_64_OCaml_C_Call>>,
522+
// OxCaml CCs
523+
CCIfCC<"CallingConv::OxCaml_WithFP", CCDelegateTo<RetCC_X86_64_OxCaml>>,
524+
CCIfCC<"CallingConv::OxCaml_WithoutFP", CCDelegateTo<RetCC_X86_64_OxCaml>>,
525+
CCIfCC<"CallingConv::OxCaml_C_Call", CCDelegateTo<RetCC_X86_64_OxCaml_C_Call>>,
526+
CCIfCC<"CallingConv::OxCaml_C_Call_StackArgs",
527+
CCDelegateTo<RetCC_X86_64_OxCaml_C_Call_StackArgs>>,
528+
529+
// See arg CC for OxCaml_Alloc for why we use OxCaml here.
530+
CCIfCC<"CallingConv::OxCaml_Alloc", CCDelegateTo<RetCC_X86_64_OxCaml>>,
519531

520532
// Otherwise, drop to normal X86-64 CC
521533
CCDelegateTo<RetCC_X86_64_C>
@@ -723,7 +735,7 @@ def CC_X86_Win64_VectorCall : CallingConv<[
723735
CCDelegateTo<CC_X86_Win64_C>
724736
]>;
725737

726-
def CC_X86_64_OCaml : CallingConv<[
738+
def CC_X86_64_OxCaml : CallingConv<[
727739
// Promote i8/i16/i32 arguments to i64.
728740
CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
729741

@@ -733,6 +745,8 @@ def CC_X86_64_OCaml : CallingConv<[
733745
// runtime) must be preserved through the run of the program. To ensure LLVM
734746
// doesn't mess with them, they are explicitly threaded through function calls
735747
// and returns. These are R14 and R15.
748+
// Note that whether frame pointers are enabled or not doesn't impact the
749+
// argument or return conventions. It only changes the callee-saved registers.
736750
CCIfType<[i64], CCAssignToReg<[R14, R15, RAX, RBX, RDI, RSI, RDX, RCX, R8, R9, R12, R13]>>,
737751

738752
CCIfType<[f32, f64], CCAssignToReg<[
@@ -741,9 +755,21 @@ def CC_X86_64_OCaml : CallingConv<[
741755
]>>
742756
]>;
743757

744-
def CC_X86_64_OCaml_C_Call : CallingConv<[
745-
// OCaml wraps C calls with another function that transfers stack arguments.
746-
// RAX contains the function address, and R12 contains the size of the stack arguments.
758+
def CC_X86_64_OxCaml_C_Call : CallingConv<[
759+
// Calling conventions followed by [caml_c_call] which wraps non-noalloc C calls.
760+
// RAX contains the function address to call.
761+
CCIfType<[i64], CCAssignToReg<[R14, R15, RAX]>>,
762+
763+
// Follow C convention normally otherwise
764+
CCDelegateTo<CC_X86_64_C>
765+
]>;
766+
767+
def CC_X86_64_OxCaml_C_Call_StackArgs : CallingConv<[
768+
// Calling conventions followed by [caml_c_call_stack_args] to additionally handle
769+
// transfer of stack arguments. Note that this function normally takes a pair of
770+
// pointers on the stack, but since LLVM makes it hard to directly meddle with the
771+
// stack, this in reality calls yet anothr wrapper which calculates this range given
772+
// the number of stack arguments in bytes in R12.
747773
CCIfType<[i64], CCAssignToReg<[R14, R15, RAX, R12]>>,
748774

749775
// Follow C convention normally otherwise
@@ -1152,8 +1178,19 @@ def CC_X86_64 : CallingConv<[
11521178
CCIfSubtarget<"isTargetWin64()", CCDelegateTo<CC_X86_Win64_RegCall>>>,
11531179
CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo<CC_X86_SysV64_RegCall>>,
11541180
CCIfCC<"CallingConv::X86_INTR", CCCustom<"CC_X86_Intr">>,
1155-
CCIfCC<"CallingConv::OCaml", CCDelegateTo<CC_X86_64_OCaml>>,
1156-
CCIfCC<"CallingConv::OCaml_C_Call", CCDelegateTo<CC_X86_64_OCaml_C_Call>>,
1181+
1182+
// OxCaml calling conventions
1183+
CCIfCC<"CallingConv::OxCaml_WithFP", CCDelegateTo<CC_X86_64_OxCaml>>,
1184+
CCIfCC<"CallingConv::OxCaml_WithoutFP", CCDelegateTo<CC_X86_64_OxCaml>>,
1185+
CCIfCC<"CallingConv::OxCaml_C_Call", CCDelegateTo<CC_X86_64_OxCaml_C_Call>>,
1186+
CCIfCC<"CallingConv::OxCaml_C_Call_StackArgs",
1187+
CCDelegateTo<CC_X86_64_OxCaml_C_Call_StackArgs>>,
1188+
1189+
// OxCaml_Alloc follows the same CC as OxCaml, but doesn't pass arguments
1190+
// (or return) in any non-runtime register. So, as long as it is used that way,
1191+
// it is safe for it to follow OxCaml's arg and ret CCs and have a different
1192+
// CSR mask.
1193+
CCIfCC<"CallingConv::OxCaml_Alloc", CCDelegateTo<CC_X86_64_OxCaml>>,
11571194

11581195
// Mingw64 and native Win64 use Win64 CC
11591196
CCIfSubtarget<"isTargetWin64()", CCDelegateTo<CC_X86_Win64_C>>,
@@ -1179,9 +1216,6 @@ def CSR_NoRegs : CalleeSavedRegs<(add)>;
11791216
def CSR_32 : CalleeSavedRegs<(add ESI, EDI, EBX, EBP)>;
11801217
def CSR_64 : CalleeSavedRegs<(add RBX, R12, R13, R14, R15, RBP)>;
11811218

1182-
// R14 and R15 are used as return registers, so they aren't callee saved.
1183-
def CSR_64_OCaml_C_Call : CalleeSavedRegs<(sub CSR_64, R14, R15)>;
1184-
11851219
def CSR_64_SwiftError : CalleeSavedRegs<(sub CSR_64, R12)>;
11861220
def CSR_64_SwiftTail : CalleeSavedRegs<(sub CSR_64, R13, R14)>;
11871221

@@ -1281,3 +1315,16 @@ def CSR_SysV64_RegCall_NoSSE : CalleeSavedRegs<(add RBX, RBP,
12811315
(sequence "R%u", 12, 15))>;
12821316
def CSR_SysV64_RegCall : CalleeSavedRegs<(add CSR_SysV64_RegCall_NoSSE,
12831317
(sequence "XMM%u", 8, 15))>;
1318+
1319+
def CSR_64_OxCaml_WithFP : CalleeSavedRegs<(add RBP)>;
1320+
def CSR_64_OxCaml_WithoutFP : CalleeSavedRegs<(add)>;
1321+
1322+
// R14 and R15 (and also R12 in the latter) are used as return registers,
1323+
// so they aren't callee saved.
1324+
def CSR_64_OxCaml_C_Call : CalleeSavedRegs<(sub CSR_64, R14, R15)>;
1325+
def CSR_64_OxCaml_C_Call_StackArgs : CalleeSavedRegs<(sub CSR_64, R14, R15, R12)>;
1326+
1327+
// See [Proc.destroyed_at_alloc_or_poll] for more details:
1328+
// https://github.com/oxcaml/oxcaml/blob/main/backend/amd64/proc.ml#L457
1329+
// Note that R14 and R15 are also not saved since they are passed as arguments.
1330+
def CSR_64_OxCaml_Alloc : CalleeSavedRegs<(sub CSR_64_AllRegs, R10, R11, R14, R15)>;

llvm/lib/Target/X86/X86FastISel.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3140,7 +3140,8 @@ static unsigned computeBytesPoppedByCalleeForSRet(const X86Subtarget *Subtarget,
31403140
return 0;
31413141
if (CC == CallingConv::Fast || CC == CallingConv::GHC ||
31423142
CC == CallingConv::HiPE || CC == CallingConv::Tail ||
3143-
CC == CallingConv::SwiftTail || CC == CallingConv::OCaml)
3143+
CC == CallingConv::SwiftTail || CC == CallingConv::OxCaml_WithFP ||
3144+
CC == CallingConv::OxCaml_WithoutFP)
31443145
return 0;
31453146

31463147
if (CB)

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3670,7 +3670,8 @@ static bool canGuaranteeTCO(CallingConv::ID CC) {
36703670
return (CC == CallingConv::Fast || CC == CallingConv::GHC ||
36713671
CC == CallingConv::X86_RegCall || CC == CallingConv::HiPE ||
36723672
CC == CallingConv::HHVM || CC == CallingConv::Tail ||
3673-
CC == CallingConv::SwiftTail || CC == CallingConv::OCaml);
3673+
CC == CallingConv::SwiftTail || CC == CallingConv::OxCaml_WithFP ||
3674+
CC == CallingConv::OxCaml_WithoutFP);
36743675
}
36753676

36763677
/// Return true if we might ever do TCO for calls with this calling convention.

llvm/lib/Target/X86/X86RegisterInfo.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,17 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
300300
switch (CC) {
301301
case CallingConv::GHC:
302302
case CallingConv::HiPE:
303-
case CallingConv::OCaml:
304303
return CSR_NoRegs_SaveList;
305-
case CallingConv::OCaml_C_Call:
306-
return CSR_64_OCaml_C_Call_SaveList;
304+
case CallingConv::OxCaml_WithFP:
305+
return CSR_64_OxCaml_WithFP_SaveList;
306+
case CallingConv::OxCaml_WithoutFP:
307+
return CSR_64_OxCaml_WithoutFP_SaveList;
308+
case CallingConv::OxCaml_C_Call:
309+
return CSR_64_OxCaml_C_Call_SaveList;
310+
case CallingConv::OxCaml_C_Call_StackArgs:
311+
return CSR_64_OxCaml_C_Call_StackArgs_SaveList;
312+
case CallingConv::OxCaml_Alloc:
313+
return CSR_64_OxCaml_Alloc_SaveList;
307314
case CallingConv::AnyReg:
308315
if (HasAVX)
309316
return CSR_64_AllRegs_AVX_SaveList;
@@ -426,10 +433,17 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
426433
switch (CC) {
427434
case CallingConv::GHC:
428435
case CallingConv::HiPE:
429-
case CallingConv::OCaml:
430436
return CSR_NoRegs_RegMask;
431-
case CallingConv::OCaml_C_Call:
432-
return CSR_64_OCaml_C_Call_RegMask;
437+
case CallingConv::OxCaml_WithFP:
438+
return CSR_64_OxCaml_WithFP_RegMask;
439+
case CallingConv::OxCaml_WithoutFP:
440+
return CSR_64_OxCaml_WithoutFP_RegMask;
441+
case CallingConv::OxCaml_C_Call:
442+
return CSR_64_OxCaml_C_Call_RegMask;
443+
case CallingConv::OxCaml_C_Call_StackArgs:
444+
return CSR_64_OxCaml_C_Call_StackArgs_RegMask;
445+
case CallingConv::OxCaml_Alloc:
446+
return CSR_64_OxCaml_Alloc_RegMask;
433447
case CallingConv::AnyReg:
434448
if (HasAVX)
435449
return CSR_64_AllRegs_AVX_RegMask;

0 commit comments

Comments
 (0)