diff options
author | Mike Pall <mike> | 2023-08-29 02:21:51 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2023-08-29 02:21:51 +0200 |
commit | 83954100dba9fc0cf5eeaf122f007df35ec9a604 (patch) | |
tree | 49b738b500e50dbd96f9959c4cb50492bbc69114 /src/lj_asm_arm64.h | |
parent | cf903edb30e0cbd620ebd4bac02d4e2b4410fd02 (diff) | |
download | luajit-83954100dba9fc0cf5eeaf122f007df35ec9a604.tar.gz luajit-83954100dba9fc0cf5eeaf122f007df35ec9a604.tar.bz2 luajit-83954100dba9fc0cf5eeaf122f007df35ec9a604.zip |
FFI/ARM64/OSX: Handle non-standard OSX C calling conventions.
Contributed by Peter Cawley. #205
Diffstat (limited to 'src/lj_asm_arm64.h')
-rw-r--r-- | src/lj_asm_arm64.h | 75 |
1 files changed, 60 insertions, 15 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 | ||