Skip to content

Commit 000d4b0

Browse files
authored
Implement OCaml calling conventions (#10)
1 parent 199d438 commit 000d4b0

File tree

6 files changed

+43
-2
lines changed

6 files changed

+43
-2
lines changed

llvm/include/llvm/IR/CallingConv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ 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+
244247
/// The highest possible ID. Must be some 2^k - 1.
245248
MaxID = 1023
246249
};

llvm/lib/IR/AsmWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ 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;
343344
}
344345
}
345346

llvm/lib/Target/X86/X86CallingConv.td

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

443+
def RetCC_X86_64_OCaml : CallingConv<[
444+
// Promote all types to i64
445+
CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
446+
447+
// Every function preserves the necessary function arguments
448+
CCIfType<[i64], CCAssignToReg<[R14, RAX, RBX, RDI, RSI, RDX, RCX, R8, R9, R12, R13]>>,
449+
450+
CCIfType<[f32, f64], CCAssignToReg<[
451+
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
452+
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15
453+
]>>
454+
]>;
455+
443456

444457
defm X86_32_RegCall :
445458
X86_RegCall_base<RC_X86_32_RegCall>;
@@ -494,6 +507,9 @@ def RetCC_X86_64 : CallingConv<[
494507
// Mingw64 and native Win64 use Win64 CC
495508
CCIfSubtarget<"isTargetWin64()", CCDelegateTo<RetCC_X86_Win64_C>>,
496509

510+
// Handle OCaml calls
511+
CCIfCC<"CallingConv::OCaml", CCDelegateTo<RetCC_X86_64_OCaml>>,
512+
497513
// Otherwise, drop to normal X86-64 CC
498514
CCDelegateTo<RetCC_X86_64_C>
499515
]>;
@@ -700,6 +716,24 @@ def CC_X86_Win64_VectorCall : CallingConv<[
700716
CCDelegateTo<CC_X86_Win64_C>
701717
]>;
702718

719+
def CC_X86_64_OCaml : CallingConv<[
720+
// Promote i8/i16/i32 arguments to i64.
721+
CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
722+
723+
// See https://github.com/oxcaml/oxcaml/blob/main/backend/amd64/proc.ml#L34
724+
// for further details on the registers and their meaning. Runtime registers
725+
// (registers containing pointers to data structures maintained by the
726+
// runtime) must be preserved through the run of the program. To ensure LLVM
727+
// doesn't mess with them, they are explicitly threaded through function calls
728+
// and returns. These are R14 and R15. Note that R15 isn't listed since it is
729+
// not implemented yet.
730+
CCIfType<[i64], CCAssignToReg<[R14, RAX, RBX, RDI, RSI, RDX, RCX, R8, R9, R12, R13]>>,
731+
732+
CCIfType<[f32, f64], CCAssignToReg<[
733+
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
734+
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15
735+
]>>
736+
]>;
703737

704738
def CC_X86_64_GHC : CallingConv<[
705739
// Promote i8/i16/i32 arguments to i64.
@@ -1103,6 +1137,7 @@ def CC_X86_64 : CallingConv<[
11031137
CCIfSubtarget<"isTargetWin64()", CCDelegateTo<CC_X86_Win64_RegCall>>>,
11041138
CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo<CC_X86_SysV64_RegCall>>,
11051139
CCIfCC<"CallingConv::X86_INTR", CCCustom<"CC_X86_Intr">>,
1140+
CCIfCC<"CallingConv::OCaml", CCDelegateTo<CC_X86_64_OCaml>>,
11061141

11071142
// Mingw64 and native Win64 use Win64 CC
11081143
CCIfSubtarget<"isTargetWin64()", CCDelegateTo<CC_X86_Win64_C>>,

llvm/lib/Target/X86/X86FastISel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3140,7 +3140,7 @@ 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)
3143+
CC == CallingConv::SwiftTail || CC == CallingConv::OCaml)
31443144
return 0;
31453145

31463146
if (CB)

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3670,7 +3670,7 @@ 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);
3673+
CC == CallingConv::SwiftTail || CC == CallingConv::OCaml);
36743674
}
36753675

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

llvm/lib/Target/X86/X86RegisterInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
300300
switch (CC) {
301301
case CallingConv::GHC:
302302
case CallingConv::HiPE:
303+
case CallingConv::OCaml:
303304
return CSR_NoRegs_SaveList;
304305
case CallingConv::AnyReg:
305306
if (HasAVX)
@@ -423,6 +424,7 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
423424
switch (CC) {
424425
case CallingConv::GHC:
425426
case CallingConv::HiPE:
427+
case CallingConv::OCaml:
426428
return CSR_NoRegs_RegMask;
427429
case CallingConv::AnyReg:
428430
if (HasAVX)

0 commit comments

Comments
 (0)