aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm_arm64.h
diff options
context:
space:
mode:
authorMike Pall <mike>2023-08-29 02:21:51 +0200
committerMike Pall <mike>2023-08-29 02:21:51 +0200
commit83954100dba9fc0cf5eeaf122f007df35ec9a604 (patch)
tree49b738b500e50dbd96f9959c4cb50492bbc69114 /src/lj_asm_arm64.h
parentcf903edb30e0cbd620ebd4bac02d4e2b4410fd02 (diff)
downloadluajit-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.h75
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)
419static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) 419static 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. */
1977static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) 2000static 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