@@ -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)>;
11791216def CSR_32 : CalleeSavedRegs<(add ESI, EDI, EBX, EBP)>;
11801217def 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-
11851219def CSR_64_SwiftError : CalleeSavedRegs<(sub CSR_64, R12)>;
11861220def 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))>;
12821316def 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)>;
0 commit comments