diff options
author | Mike Pall <mike> | 2023-09-11 16:35:28 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2023-09-11 16:35:28 +0200 |
commit | 1c33f46314cc4e3cb52ac83c5b27419bc06b5154 (patch) | |
tree | dc0a2609e21612839aa657cf9129009247bfc9c5 /src | |
parent | f63bc569fab1450def4c817f100e580dddb425c5 (diff) | |
download | luajit-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.h | 17 | ||||
-rw-r--r-- | src/lj_ccall.c | 18 | ||||
-rw-r--r-- | src/lj_crecord.c | 6 | ||||
-rw-r--r-- | src/lj_emit_arm64.h | 4 |
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 | ||
127 | static void emit_lso(ASMState *as, A64Ins ai, Reg rd, Reg rn, int64_t ofs) | 127 | static 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) && |