From e0a3a4b5f34a666ebb5e43b7900b2e841ecd9b5c Mon Sep 17 00:00:00 2001 From: usuyus Date: Tue, 29 Jul 2025 13:50:20 +0100 Subject: [PATCH 1/2] clean up diff --- llvm/include/llvm/IR/CallingConv.h | 3 +++ llvm/lib/IR/AsmWriter.cpp | 1 + llvm/lib/Target/X86/X86CallingConv.td | 29 +++++++++++++++++++++++++ llvm/lib/Target/X86/X86FastISel.cpp | 2 +- llvm/lib/Target/X86/X86ISelLowering.cpp | 2 +- llvm/lib/Target/X86/X86RegisterInfo.cpp | 2 ++ 6 files changed, 37 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h index 9fefeef05cb21..aae7b60911200 100644 --- a/llvm/include/llvm/IR/CallingConv.h +++ b/llvm/include/llvm/IR/CallingConv.h @@ -241,6 +241,9 @@ namespace CallingConv { /// Preserve X2-X15, X19-X29, SP, Z0-Z31, P0-P15. AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2 = 103, + /// Calling convention for OCaml + OCaml = 104, + /// The highest possible ID. Must be some 2^k - 1. MaxID = 1023 }; diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 6108ce09c289a..26756cd00f5ed 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -340,6 +340,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) { case CallingConv::AMDGPU_CS: Out << "amdgpu_cs"; break; case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break; case CallingConv::AMDGPU_Gfx: Out << "amdgpu_gfx"; break; + case CallingConv::OCaml: Out << "ocamlcc"; break; } } diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td index 4dd8a6cdd8982..e9375cc22252c 100644 --- a/llvm/lib/Target/X86/X86CallingConv.td +++ b/llvm/lib/Target/X86/X86CallingConv.td @@ -440,6 +440,19 @@ def RetCC_X86_64_HHVM: CallingConv<[ RAX, R10, R11, R13, R14, R15]>> ]>; +def RetCC_X86_64_OCaml : CallingConv<[ + // Promote all types to i64 + CCIfType<[i8, i16, i32], CCPromoteToType>, + + // Every function preserves the necessary function arguments + CCIfType<[i64], CCAssignToReg<[R14, RAX, RBX, RDI, RSI, RDX, RCX, R8, R9, R12, R13]>>, + + CCIfType<[f32, f64], CCAssignToReg<[ + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15 + ]>> +]>; + defm X86_32_RegCall : X86_RegCall_base; @@ -494,6 +507,9 @@ def RetCC_X86_64 : CallingConv<[ // Mingw64 and native Win64 use Win64 CC CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, + // Handle OCaml calls + CCIfCC<"CallingConv::OCaml", CCDelegateTo>, + // Otherwise, drop to normal X86-64 CC CCDelegateTo ]>; @@ -700,6 +716,18 @@ def CC_X86_Win64_VectorCall : CallingConv<[ CCDelegateTo ]>; +def CC_X86_64_OCaml : CallingConv<[ + // Promote i8/i16/i32 arguments to i64. + CCIfType<[i8, i16, i32], CCPromoteToType>, + + // Pass in runtime registers first + CCIfType<[i64], CCAssignToReg<[R14, RAX, RBX, RDI, RSI, RDX, RCX, R8, R9, R12, R13]>>, + + CCIfType<[f32, f64], CCAssignToReg<[ + XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15 + ]>> +]>; def CC_X86_64_GHC : CallingConv<[ // Promote i8/i16/i32 arguments to i64. @@ -1103,6 +1131,7 @@ def CC_X86_64 : CallingConv<[ CCIfSubtarget<"isTargetWin64()", CCDelegateTo>>, CCIfCC<"CallingConv::X86_RegCall", CCDelegateTo>, CCIfCC<"CallingConv::X86_INTR", CCCustom<"CC_X86_Intr">>, + CCIfCC<"CallingConv::OCaml", CCDelegateTo>, // Mingw64 and native Win64 use Win64 CC CCIfSubtarget<"isTargetWin64()", CCDelegateTo>, diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp index ade4ff61762af..5dad0a22326f5 100644 --- a/llvm/lib/Target/X86/X86FastISel.cpp +++ b/llvm/lib/Target/X86/X86FastISel.cpp @@ -3140,7 +3140,7 @@ static unsigned computeBytesPoppedByCalleeForSRet(const X86Subtarget *Subtarget, return 0; if (CC == CallingConv::Fast || CC == CallingConv::GHC || CC == CallingConv::HiPE || CC == CallingConv::Tail || - CC == CallingConv::SwiftTail) + CC == CallingConv::SwiftTail || CC == CallingConv::OCaml) return 0; if (CB) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index e43b33eed4707..98f4c983d589a 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -3670,7 +3670,7 @@ static bool canGuaranteeTCO(CallingConv::ID CC) { return (CC == CallingConv::Fast || CC == CallingConv::GHC || CC == CallingConv::X86_RegCall || CC == CallingConv::HiPE || CC == CallingConv::HHVM || CC == CallingConv::Tail || - CC == CallingConv::SwiftTail); + CC == CallingConv::SwiftTail || CC == CallingConv::OCaml); } /// Return true if we might ever do TCO for calls with this calling convention. diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index 7ce3dca7f3a79..3ca9a0b09a24a 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -300,6 +300,7 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { switch (CC) { case CallingConv::GHC: case CallingConv::HiPE: + case CallingConv::OCaml: return CSR_NoRegs_SaveList; case CallingConv::AnyReg: if (HasAVX) @@ -423,6 +424,7 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction &MF, switch (CC) { case CallingConv::GHC: case CallingConv::HiPE: + case CallingConv::OCaml: return CSR_NoRegs_RegMask; case CallingConv::AnyReg: if (HasAVX) From 1387e34c9275fd9f8407f30a1ae0ecb5f694c42d Mon Sep 17 00:00:00 2001 From: usuyus Date: Wed, 30 Jul 2025 14:21:13 +0100 Subject: [PATCH 2/2] more informative comment --- llvm/lib/Target/X86/X86CallingConv.td | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td index e9375cc22252c..b77154bf31e05 100644 --- a/llvm/lib/Target/X86/X86CallingConv.td +++ b/llvm/lib/Target/X86/X86CallingConv.td @@ -720,7 +720,13 @@ def CC_X86_64_OCaml : CallingConv<[ // Promote i8/i16/i32 arguments to i64. CCIfType<[i8, i16, i32], CCPromoteToType>, - // Pass in runtime registers first + // See https://github.com/oxcaml/oxcaml/blob/main/backend/amd64/proc.ml#L34 + // for further details on the registers and their meaning. Runtime registers + // (registers containing pointers to data structures maintained by the + // runtime) must be preserved through the run of the program. To ensure LLVM + // doesn't mess with them, they are explicitly threaded through function calls + // and returns. These are R14 and R15. Note that R15 isn't listed since it is + // not implemented yet. CCIfType<[i64], CCAssignToReg<[R14, RAX, RBX, RDI, RSI, RDX, RCX, R8, R9, R12, R13]>>, CCIfType<[f32, f64], CCAssignToReg<[