diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_asm_arm64.h | 75 | ||||
| -rw-r--r-- | src/lj_ccall.c | 11 | ||||
| -rw-r--r-- | src/lj_ccall.h | 6 | ||||
| -rw-r--r-- | src/lj_crecord.c | 27 |
4 files changed, 98 insertions, 21 deletions
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h index 1d5cca4f..3889883d 100644 --- a/src/lj_asm_arm64.h +++ b/src/lj_asm_arm64.h | |||
| @@ -419,7 +419,7 @@ static int asm_fuseorshift(ASMState *as, IRIns *ir) | |||
| 419 | static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | 419 | static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) |
| 420 | { | 420 | { |
| 421 | uint32_t n, nargs = CCI_XNARGS(ci); | 421 | uint32_t n, nargs = CCI_XNARGS(ci); |
| 422 | int32_t ofs = 0; | 422 | int32_t spofs = 0, spalign = LJ_HASFFI && LJ_TARGET_OSX ? 0 : 7; |
| 423 | Reg gpr, fpr = REGARG_FIRSTFPR; | 423 | Reg gpr, fpr = REGARG_FIRSTFPR; |
| 424 | if (ci->func) | 424 | if (ci->func) |
| 425 | emit_call(as, ci->func); | 425 | emit_call(as, ci->func); |
| @@ -438,8 +438,14 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
| 438 | fpr++; | 438 | fpr++; |
| 439 | } else { | 439 | } else { |
| 440 | Reg r = ra_alloc1(as, ref, RSET_FPR); | 440 | Reg r = ra_alloc1(as, ref, RSET_FPR); |
| 441 | emit_spstore(as, ir, r, ofs + ((LJ_BE && !irt_isnum(ir->t)) ? 4 : 0)); | 441 | int32_t al = spalign; |
| 442 | ofs += 8; | 442 | #if LJ_HASFFI && LJ_TARGET_OSX |
| 443 | al |= irt_isnum(ir->t) ? 7 : 3; | ||
| 444 | #endif | ||
| 445 | spofs = (spofs + al) & ~al; | ||
| 446 | if (LJ_BE && al >= 7 && !irt_isnum(ir->t)) spofs += 4, al -= 4; | ||
| 447 | emit_spstore(as, ir, r, spofs); | ||
| 448 | spofs += al + 1; | ||
| 443 | } | 449 | } |
| 444 | } else { | 450 | } else { |
| 445 | if (gpr <= REGARG_LASTGPR) { | 451 | if (gpr <= REGARG_LASTGPR) { |
| @@ -449,10 +455,27 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
| 449 | gpr++; | 455 | gpr++; |
| 450 | } else { | 456 | } else { |
| 451 | Reg r = ra_alloc1(as, ref, RSET_GPR); | 457 | Reg r = ra_alloc1(as, ref, RSET_GPR); |
| 452 | emit_spstore(as, ir, r, ofs + ((LJ_BE && !irt_is64(ir->t)) ? 4 : 0)); | 458 | int32_t al = spalign; |
| 453 | ofs += 8; | 459 | #if LJ_HASFFI && LJ_TARGET_OSX |
| 460 | al |= irt_size(ir->t) - 1; | ||
| 461 | #endif | ||
| 462 | spofs = (spofs + al) & ~al; | ||
| 463 | if (al >= 3) { | ||
| 464 | if (LJ_BE && al >= 7 && !irt_is64(ir->t)) spofs += 4, al -= 4; | ||
| 465 | emit_spstore(as, ir, r, spofs); | ||
| 466 | } else { | ||
| 467 | lj_assertA(al == 0 || al == 1, "size %d unexpected", al + 1); | ||
| 468 | emit_lso(as, al ? A64I_STRH : A64I_STRB, r, RID_SP, spofs); | ||
| 469 | } | ||
| 470 | spofs += al + 1; | ||
| 454 | } | 471 | } |
| 455 | } | 472 | } |
| 473 | #if LJ_HASFFI && LJ_TARGET_OSX | ||
| 474 | } else { /* Marker for start of varargs. */ | ||
| 475 | gpr = REGARG_LASTGPR+1; | ||
| 476 | fpr = REGARG_LASTFPR+1; | ||
| 477 | spalign = 7; | ||
| 478 | #endif | ||
| 456 | } | 479 | } |
| 457 | } | 480 | } |
| 458 | } | 481 | } |
| @@ -1976,19 +1999,41 @@ static void asm_tail_prep(ASMState *as) | |||
| 1976 | /* Ensure there are enough stack slots for call arguments. */ | 1999 | /* Ensure there are enough stack slots for call arguments. */ |
| 1977 | static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) | 2000 | static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) |
| 1978 | { | 2001 | { |
| 1979 | IRRef args[CCI_NARGS_MAX*2]; | 2002 | #if LJ_HASFFI |
| 1980 | uint32_t i, nargs = CCI_XNARGS(ci); | 2003 | uint32_t i, nargs = CCI_XNARGS(ci); |
| 1981 | int nslots = 0, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; | 2004 | if (nargs > (REGARG_NUMGPR < REGARG_NUMFPR ? REGARG_NUMGPR : REGARG_NUMFPR) || |
| 1982 | asm_collectargs(as, ir, ci, args); | 2005 | (LJ_TARGET_OSX && (ci->flags & CCI_VARARG))) { |
| 1983 | for (i = 0; i < nargs; i++) { | 2006 | IRRef args[CCI_NARGS_MAX*2]; |
| 1984 | if (args[i] && irt_isfp(IR(args[i])->t)) { | 2007 | int ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; |
| 1985 | if (nfpr > 0) nfpr--; else nslots += 2; | 2008 | int spofs = 0, spalign = LJ_TARGET_OSX ? 0 : 7, nslots; |
| 1986 | } else { | 2009 | asm_collectargs(as, ir, ci, args); |
| 1987 | if (ngpr > 0) ngpr--; else nslots += 2; | 2010 | for (i = 0; i < nargs; i++) { |
| 2011 | int al = spalign; | ||
| 2012 | if (!args[i]) { | ||
| 2013 | #if LJ_TARGET_OSX | ||
| 2014 | /* Marker for start of varaargs. */ | ||
| 2015 | nfpr = 0; | ||
| 2016 | ngpr = 0; | ||
| 2017 | spalign = 7; | ||
| 2018 | #endif | ||
| 2019 | } else if (irt_isfp(IR(args[i])->t)) { | ||
| 2020 | if (nfpr > 0) { nfpr--; continue; } | ||
| 2021 | #if LJ_TARGET_OSX | ||
| 2022 | al |= irt_isnum(IR(args[i])->t) ? 7 : 3; | ||
| 2023 | #endif | ||
| 2024 | } else { | ||
| 2025 | if (ngpr > 0) { ngpr--; continue; } | ||
| 2026 | #if LJ_TARGET_OSX | ||
| 2027 | al |= irt_size(IR(args[i])->t) - 1; | ||
| 2028 | #endif | ||
| 2029 | } | ||
| 2030 | spofs = (spofs + 2*al+1) & ~al; /* Align and bump stack pointer. */ | ||
| 1988 | } | 2031 | } |
| 2032 | nslots = (spofs + 3) >> 2; | ||
| 2033 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ | ||
| 2034 | as->evenspill = nslots; | ||
| 1989 | } | 2035 | } |
| 1990 | if (nslots > as->evenspill) /* Leave room for args in stack slots. */ | 2036 | #endif |
| 1991 | as->evenspill = nslots; | ||
| 1992 | return REGSP_HINT(RID_RET); | 2037 | return REGSP_HINT(RID_RET); |
| 1993 | } | 2038 | } |
| 1994 | 2039 | ||
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 9001cb5a..00e753b9 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
| @@ -348,7 +348,6 @@ | |||
| 348 | goto done; \ | 348 | goto done; \ |
| 349 | } else { \ | 349 | } else { \ |
| 350 | nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \ | 350 | nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \ |
| 351 | if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \ | ||
| 352 | } \ | 351 | } \ |
| 353 | } else { /* Try to pass argument in GPRs. */ \ | 352 | } else { /* Try to pass argument in GPRs. */ \ |
| 354 | if (!LJ_TARGET_OSX && (d->info & CTF_ALIGN) > CTALIGN_PTR) \ | 353 | if (!LJ_TARGET_OSX && (d->info & CTF_ALIGN) > CTALIGN_PTR) \ |
| @@ -359,7 +358,6 @@ | |||
| 359 | goto done; \ | 358 | goto done; \ |
| 360 | } else { \ | 359 | } else { \ |
| 361 | ngpr = maxgpr; /* Prevent reordering. */ \ | 360 | ngpr = maxgpr; /* Prevent reordering. */ \ |
| 362 | if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \ | ||
| 363 | } \ | 361 | } \ |
| 364 | } | 362 | } |
| 365 | 363 | ||
| @@ -1023,7 +1021,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 1023 | CCALL_HANDLE_STRUCTARG | 1021 | CCALL_HANDLE_STRUCTARG |
| 1024 | } else if (ctype_iscomplex(d->info)) { | 1022 | } else if (ctype_iscomplex(d->info)) { |
| 1025 | CCALL_HANDLE_COMPLEXARG | 1023 | CCALL_HANDLE_COMPLEXARG |
| 1026 | } else { | 1024 | } else if (!(CCALL_PACK_STACKARG && ctype_isenum(d->info))) { |
| 1027 | sz = CTSIZE_PTR; | 1025 | sz = CTSIZE_PTR; |
| 1028 | } | 1026 | } |
| 1029 | n = (sz + CTSIZE_PTR-1) / CTSIZE_PTR; /* Number of GPRs or stack slots needed. */ | 1027 | n = (sz + CTSIZE_PTR-1) / CTSIZE_PTR; /* Number of GPRs or stack slots needed. */ |
| @@ -1033,12 +1031,12 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 1033 | /* Otherwise pass argument on stack. */ | 1031 | /* Otherwise pass argument on stack. */ |
| 1034 | if (CCALL_ALIGN_STACKARG) { /* Align argument on stack. */ | 1032 | if (CCALL_ALIGN_STACKARG) { /* Align argument on stack. */ |
| 1035 | MSize align = (1u << ctype_align(d->info)) - 1; | 1033 | MSize align = (1u << ctype_align(d->info)) - 1; |
| 1036 | if (rp) | 1034 | if (rp || (CCALL_PACK_STACKARG && isva && align < CTSIZE_PTR-1)) |
| 1037 | align = CTSIZE_PTR-1; | 1035 | align = CTSIZE_PTR-1; |
| 1038 | nsp = (nsp + align) & ~align; | 1036 | nsp = (nsp + align) & ~align; |
| 1039 | } | 1037 | } |
| 1040 | dp = ((uint8_t *)cc->stack) + nsp; | 1038 | dp = ((uint8_t *)cc->stack) + nsp; |
| 1041 | nsp += n * CTSIZE_PTR; | 1039 | nsp += CCALL_PACK_STACKARG ? sz : n * CTSIZE_PTR; |
| 1042 | if (nsp > CCALL_SIZE_STACK) { /* Too many arguments. */ | 1040 | if (nsp > CCALL_SIZE_STACK) { /* Too many arguments. */ |
| 1043 | err_nyi: | 1041 | err_nyi: |
| 1044 | lj_err_caller(L, LJ_ERR_FFI_NYICALL); | 1042 | lj_err_caller(L, LJ_ERR_FFI_NYICALL); |
| @@ -1053,7 +1051,8 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 1053 | } | 1051 | } |
| 1054 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); | 1052 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); |
| 1055 | /* Extend passed integers to 32 bits at least. */ | 1053 | /* Extend passed integers to 32 bits at least. */ |
| 1056 | if (ctype_isinteger_or_bool(d->info) && d->size < 4) { | 1054 | if (ctype_isinteger_or_bool(d->info) && d->size < 4 && |
| 1055 | (!CCALL_PACK_STACKARG || !((uintptr_t)dp & 3))) { /* Assumes LJ_LE. */ | ||
| 1057 | if (d->info & CTF_UNSIGNED) | 1056 | if (d->info & CTF_UNSIGNED) |
| 1058 | *(uint32_t *)dp = d->size == 1 ? (uint32_t)*(uint8_t *)dp : | 1057 | *(uint32_t *)dp = d->size == 1 ? (uint32_t)*(uint8_t *)dp : |
| 1059 | (uint32_t)*(uint16_t *)dp; | 1058 | (uint32_t)*(uint16_t *)dp; |
diff --git a/src/lj_ccall.h b/src/lj_ccall.h index 57300817..24646d90 100644 --- a/src/lj_ccall.h +++ b/src/lj_ccall.h | |||
| @@ -75,6 +75,9 @@ typedef union FPRArg { | |||
| 75 | #define CCALL_NARG_FPR 8 | 75 | #define CCALL_NARG_FPR 8 |
| 76 | #define CCALL_NRET_FPR 4 | 76 | #define CCALL_NRET_FPR 4 |
| 77 | #define CCALL_SPS_FREE 0 | 77 | #define CCALL_SPS_FREE 0 |
| 78 | #if LJ_TARGET_OSX | ||
| 79 | #define CCALL_PACK_STACKARG 1 | ||
| 80 | #endif | ||
| 78 | 81 | ||
| 79 | typedef intptr_t GPRArg; | 82 | typedef intptr_t GPRArg; |
| 80 | typedef union FPRArg { | 83 | typedef union FPRArg { |
| @@ -139,6 +142,9 @@ typedef union FPRArg { | |||
| 139 | #ifndef CCALL_ALIGN_STACKARG | 142 | #ifndef CCALL_ALIGN_STACKARG |
| 140 | #define CCALL_ALIGN_STACKARG 1 | 143 | #define CCALL_ALIGN_STACKARG 1 |
| 141 | #endif | 144 | #endif |
| 145 | #ifndef CCALL_PACK_STACKARG | ||
| 146 | #define CCALL_PACK_STACKARG 0 | ||
| 147 | #endif | ||
| 142 | #ifndef CCALL_ALIGN_CALLSTATE | 148 | #ifndef CCALL_ALIGN_CALLSTATE |
| 143 | #define CCALL_ALIGN_CALLSTATE 8 | 149 | #define CCALL_ALIGN_CALLSTATE 8 |
| 144 | #endif | 150 | #endif |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 04bc895d..d7a522fb 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
| @@ -1118,6 +1118,12 @@ 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 | ||
| 1122 | #if LJ_ABI_WIN | ||
| 1123 | #error "NYI: ARM64 Windows ABI calling conventions" | ||
| 1124 | #elif LJ_TARGET_OSX | ||
| 1125 | int ngpr = CCALL_NARG_GPR; | ||
| 1126 | #endif | ||
| 1121 | #endif | 1127 | #endif |
| 1122 | 1128 | ||
| 1123 | /* Skip initial attributes. */ | 1129 | /* Skip initial attributes. */ |
| @@ -1143,6 +1149,14 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
| 1143 | } else { | 1149 | } else { |
| 1144 | if (!(ct->info & CTF_VARARG)) | 1150 | if (!(ct->info & CTF_VARARG)) |
| 1145 | lj_trace_err(J, LJ_TRERR_NYICALL); /* Too many arguments. */ | 1151 | lj_trace_err(J, LJ_TRERR_NYICALL); /* Too many arguments. */ |
| 1152 | #if LJ_TARGET_ARM64 && LJ_TARGET_OSX | ||
| 1153 | if (ngpr >= 0) { | ||
| 1154 | ngpr = -1; | ||
| 1155 | args[n++] = TREF_NIL; /* Marker for start of varargs. */ | ||
| 1156 | if (n >= CCI_NARGS_MAX) | ||
| 1157 | lj_trace_err(J, LJ_TRERR_NYICALL); | ||
| 1158 | } | ||
| 1159 | #endif | ||
| 1146 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ | 1160 | did = lj_ccall_ctid_vararg(cts, o); /* Infer vararg type. */ |
| 1147 | } | 1161 | } |
| 1148 | d = ctype_raw(cts, did); | 1162 | d = ctype_raw(cts, did); |
| @@ -1151,6 +1165,15 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
| 1151 | lj_trace_err(J, LJ_TRERR_NYICALL); | 1165 | lj_trace_err(J, LJ_TRERR_NYICALL); |
| 1152 | tr = crec_ct_tv(J, d, 0, *base, o); | 1166 | tr = crec_ct_tv(J, d, 0, *base, o); |
| 1153 | if (ctype_isinteger_or_bool(d->info)) { | 1167 | if (ctype_isinteger_or_bool(d->info)) { |
| 1168 | #if LJ_TARGET_ARM64 && LJ_TARGET_OSX | ||
| 1169 | if (!ngpr) { | ||
| 1170 | /* Fixed args passed on the stack use their unpromoted size. */ | ||
| 1171 | if (d->size != lj_ir_type_size[tref_type(tr)]) { | ||
| 1172 | lj_assertJ(d->size == 1 || d->size==2, "unexpected size %d", d->size); | ||
| 1173 | tr = emitconv(tr, d->size==1 ? IRT_U8 : IRT_U16, tref_type(tr), 0); | ||
| 1174 | } | ||
| 1175 | } else | ||
| 1176 | #endif | ||
| 1154 | if (d->size < 4) { | 1177 | if (d->size < 4) { |
| 1155 | if ((d->info & CTF_UNSIGNED)) | 1178 | if ((d->info & CTF_UNSIGNED)) |
| 1156 | tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0); | 1179 | tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0); |
| @@ -1188,6 +1211,10 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd, | |||
| 1188 | } | 1211 | } |
| 1189 | } | 1212 | } |
| 1190 | #endif | 1213 | #endif |
| 1214 | #elif LJ_TARGET_ARM64 && LJ_TARGET_OSX | ||
| 1215 | if (!ctype_isfp(d->info) && ngpr) { | ||
| 1216 | ngpr--; | ||
| 1217 | } | ||
| 1191 | #endif | 1218 | #endif |
| 1192 | args[n] = tr; | 1219 | args[n] = tr; |
| 1193 | } | 1220 | } |
