aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2023-09-11 16:35:28 +0200
committerMike Pall <mike>2023-09-11 16:35:28 +0200
commit1c33f46314cc4e3cb52ac83c5b27419bc06b5154 (patch)
treedc0a2609e21612839aa657cf9129009247bfc9c5 /src
parentf63bc569fab1450def4c817f100e580dddb425c5 (diff)
downloadluajit-1c33f46314cc4e3cb52ac83c5b27419bc06b5154.tar.gz
luajit-1c33f46314cc4e3cb52ac83c5b27419bc06b5154.tar.bz2
luajit-1c33f46314cc4e3cb52ac83c5b27419bc06b5154.zip
Windows/ARM64: Support Windows calling conventions.
Dear Microsoft: your butchering of the (perfectly fine) ARM64 ABI is a disgrace. Thanks to Peter Cawley. #593
Diffstat (limited to 'src')
-rw-r--r--src/lj_asm_arm64.h17
-rw-r--r--src/lj_ccall.c18
-rw-r--r--src/lj_crecord.c6
-rw-r--r--src/lj_emit_arm64.h4
4 files changed, 36 insertions, 9 deletions
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h
index 4dd6b711..c2b17737 100644
--- a/src/lj_asm_arm64.h
+++ b/src/lj_asm_arm64.h
@@ -432,6 +432,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
432 for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++) 432 for (gpr = REGARG_FIRSTGPR; gpr <= REGARG_LASTGPR; gpr++)
433 as->cost[gpr] = REGCOST(~0u, ASMREF_L); 433 as->cost[gpr] = REGCOST(~0u, ASMREF_L);
434 gpr = REGARG_FIRSTGPR; 434 gpr = REGARG_FIRSTGPR;
435#if LJ_HASFFI && LJ_ABI_WIN
436 if ((ci->flags & CCI_VARARG)) {
437 fpr = REGARG_LASTFPR+1;
438 }
439#endif
435 for (n = 0; n < nargs; n++) { /* Setup args. */ 440 for (n = 0; n < nargs; n++) { /* Setup args. */
436 IRRef ref = args[n]; 441 IRRef ref = args[n];
437 IRIns *ir = IR(ref); 442 IRIns *ir = IR(ref);
@@ -442,6 +447,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
442 "reg %d not free", fpr); /* Must have been evicted. */ 447 "reg %d not free", fpr); /* Must have been evicted. */
443 ra_leftov(as, fpr, ref); 448 ra_leftov(as, fpr, ref);
444 fpr++; 449 fpr++;
450#if LJ_HASFFI && LJ_ABI_WIN
451 } else if ((ci->flags & CCI_VARARG) && (gpr <= REGARG_LASTGPR)) {
452 Reg rf = ra_alloc1(as, ref, RSET_FPR);
453 emit_dn(as, A64I_FMOV_R_D, gpr++, rf & 31);
454#endif
445 } else { 455 } else {
446 Reg r = ra_alloc1(as, ref, RSET_FPR); 456 Reg r = ra_alloc1(as, ref, RSET_FPR);
447 int32_t al = spalign; 457 int32_t al = spalign;
@@ -1943,6 +1953,9 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
1943 int ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; 1953 int ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
1944 int spofs = 0, spalign = LJ_TARGET_OSX ? 0 : 7, nslots; 1954 int spofs = 0, spalign = LJ_TARGET_OSX ? 0 : 7, nslots;
1945 asm_collectargs(as, ir, ci, args); 1955 asm_collectargs(as, ir, ci, args);
1956#if LJ_ABI_WIN
1957 if ((ci->flags & CCI_VARARG)) nfpr = 0;
1958#endif
1946 for (i = 0; i < nargs; i++) { 1959 for (i = 0; i < nargs; i++) {
1947 int al = spalign; 1960 int al = spalign;
1948 if (!args[i]) { 1961 if (!args[i]) {
@@ -1954,7 +1967,9 @@ static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
1954#endif 1967#endif
1955 } else if (irt_isfp(IR(args[i])->t)) { 1968 } else if (irt_isfp(IR(args[i])->t)) {
1956 if (nfpr > 0) { nfpr--; continue; } 1969 if (nfpr > 0) { nfpr--; continue; }
1957#if LJ_TARGET_OSX 1970#if LJ_ABI_WIN
1971 if ((ci->flags & CCI_VARARG) && ngpr > 0) { ngpr--; continue; }
1972#elif LJ_TARGET_OSX
1958 al |= irt_isnum(IR(args[i])->t) ? 7 : 3; 1973 al |= irt_isnum(IR(args[i])->t) ? 7 : 3;
1959#endif 1974#endif
1960 } else { 1975 } else {
diff --git a/src/lj_ccall.c b/src/lj_ccall.c
index 00e753b9..5f95f5d8 100644
--- a/src/lj_ccall.c
+++ b/src/lj_ccall.c
@@ -985,6 +985,14 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
985 fid = ctf->sib; 985 fid = ctf->sib;
986 } 986 }
987 987
988#if LJ_TARGET_ARM64 && LJ_ABI_WIN
989 if ((ct->info & CTF_VARARG)) {
990 nsp -= maxgpr * CTSIZE_PTR; /* May end up with negative nsp. */
991 ngpr = maxgpr;
992 nfpr = CCALL_NARG_FPR;
993 }
994#endif
995
988 /* Walk through all passed arguments. */ 996 /* Walk through all passed arguments. */
989 for (o = L->base+1, narg = 1; o < top; o++, narg++) { 997 for (o = L->base+1, narg = 1; o < top; o++, narg++) {
990 CTypeID did; 998 CTypeID did;
@@ -1035,9 +1043,14 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
1035 align = CTSIZE_PTR-1; 1043 align = CTSIZE_PTR-1;
1036 nsp = (nsp + align) & ~align; 1044 nsp = (nsp + align) & ~align;
1037 } 1045 }
1046#if LJ_TARGET_ARM64 && LJ_ABI_WIN
1047 /* A negative nsp points into cc->gpr. Blame MS for their messy ABI. */
1048 dp = ((uint8_t *)cc->stack) + (int32_t)nsp;
1049#else
1038 dp = ((uint8_t *)cc->stack) + nsp; 1050 dp = ((uint8_t *)cc->stack) + nsp;
1051#endif
1039 nsp += CCALL_PACK_STACKARG ? sz : n * CTSIZE_PTR; 1052 nsp += CCALL_PACK_STACKARG ? sz : n * CTSIZE_PTR;
1040 if (nsp > CCALL_SIZE_STACK) { /* Too many arguments. */ 1053 if ((int32_t)nsp > CCALL_SIZE_STACK) { /* Too many arguments. */
1041 err_nyi: 1054 err_nyi:
1042 lj_err_caller(L, LJ_ERR_FFI_NYICALL); 1055 lj_err_caller(L, LJ_ERR_FFI_NYICALL);
1043 } 1056 }
@@ -1099,6 +1112,9 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
1099#endif 1112#endif
1100 } 1113 }
1101 if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too few arguments. */ 1114 if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too few arguments. */
1115#if LJ_TARGET_ARM64 && LJ_ABI_WIN
1116 if ((int32_t)nsp < 0) nsp = 0;
1117#endif
1102 1118
1103#if LJ_TARGET_X64 || (LJ_TARGET_PPC && !LJ_ABI_SOFTFP) 1119#if LJ_TARGET_X64 || (LJ_TARGET_PPC && !LJ_ABI_SOFTFP)
1104 cc->nfpr = nfpr; /* Required for vararg functions. */ 1120 cc->nfpr = nfpr; /* Required for vararg functions. */
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index d7a522fb..55d0b3ef 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -1118,13 +1118,9 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
1118 ngpr = 1; 1118 ngpr = 1;
1119 else if (ctype_cconv(ct->info) == CTCC_FASTCALL) 1119 else if (ctype_cconv(ct->info) == CTCC_FASTCALL)
1120 ngpr = 2; 1120 ngpr = 2;
1121#elif LJ_TARGET_ARM64 1121#elif LJ_TARGET_ARM64 && LJ_TARGET_OSX
1122#if LJ_ABI_WIN
1123#error "NYI: ARM64 Windows ABI calling conventions"
1124#elif LJ_TARGET_OSX
1125 int ngpr = CCALL_NARG_GPR; 1122 int ngpr = CCALL_NARG_GPR;
1126#endif 1123#endif
1127#endif
1128 1124
1129 /* Skip initial attributes. */ 1125 /* Skip initial attributes. */
1130 fid = ct->sib; 1126 fid = ct->sib;
diff --git a/src/lj_emit_arm64.h b/src/lj_emit_arm64.h
index fef5d973..3c510492 100644
--- a/src/lj_emit_arm64.h
+++ b/src/lj_emit_arm64.h
@@ -124,9 +124,9 @@ static LJ_AINLINE uint32_t emit_lso_pair_candidate(A64Ins ai, int ofs, int sc)
124 } 124 }
125} 125}
126 126
127static void emit_lso(ASMState *as, A64Ins ai, Reg rd, Reg rn, int64_t ofs) 127static void emit_lso(ASMState *as, A64Ins ai, Reg rd, Reg rn, int64_t ofs64)
128{ 128{
129 int ot = emit_checkofs(ai, ofs), sc = (ai >> 30) & 3; 129 int ot = emit_checkofs(ai, ofs64), sc = (ai >> 30) & 3, ofs = (int)ofs64;
130 lj_assertA(ot, "load/store offset %d out of range", ofs); 130 lj_assertA(ot, "load/store offset %d out of range", ofs);
131 /* Combine LDR/STR pairs to LDP/STP. */ 131 /* Combine LDR/STR pairs to LDP/STP. */
132 if ((sc == 2 || sc == 3) && 132 if ((sc == 2 || sc == 3) &&