Tarantool development patches archive
 help / color / mirror / Atom feed
From: Sergey Bronnikov via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: Sergey Kaplun <skaplun@tarantool.org>,
	Evgeniy Temirgaleev <e.temirgaleev@tarantool.org>
Cc: tarantool-patches@dev.tarantool.org
Subject: Re: [Tarantool-patches] [PATCH luajit 2/5] FFI/ARM64/OSX: Handle non-standard OSX C calling conventions.
Date: Mon, 1 Jun 2026 14:40:15 +0300	[thread overview]
Message-ID: <ef0938ef-c671-4885-8b01-c491d9d6bb88@tarantool.org> (raw)
In-Reply-To: <20260530160409.4043089-3-skaplun@tarantool.org>

[-- Attachment #1: Type: text/plain, Size: 18638 bytes --]

Hi, Sergey,

thanks for the patch! LGTM with two minor comments.

Sergey

On 5/30/26 19:04, Sergey Kaplun wrote:
> From: Mike Pall <mike>
>
> Contributed by Peter Cawley.
>
> (cherry picked from commit 83954100dba9fc0cf5eeaf122f007df35ec9a604)
>
> This patch adds FFI support for passing small (< 8 bytes) parameters on
> the stack on the OSX arm64 architecture. Also, it fixes the compilation
> of FFI vararg functions, since before the patch arguments were passed in
> registers instead of the stack [1] for them. JIT machinery now uses
> `TREF_NIL` as a marker for the slot from which the variadic arguments
> begin.
>
> [1]:https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Update-code-that-passes-arguments-to-variadic-functions
>
> Sergey Kaplun:
> * added the description and the test for the problem
>
> Resolves tarantool/tarantool#6097
> Part of tarantool/tarantool#12480
> ---
>   src/lj_asm_arm64.h                            | 75 +++++++++++++++----
>   src/lj_ccall.c                                | 11 ++-
>   src/lj_ccall.h                                |  6 ++
>   src/lj_crecord.c                              | 27 +++++++
>   test/tarantool-tests/ffi-ccall/CMakeLists.txt |  8 +-
>   test/tarantool-tests/ffi-ccall/libfficcall.c  | 51 +++++++++++++
>   .../gh-6097-arm64-osx-ffi-vararg.test.lua     | 43 +++++++++++
>   .../lj-205-arm64-osx-ffi-enum-arg.test.lua    | 63 ++++++++++++++++
>   .../lj-205-arm64-osx-ffi-small-arg.test.lua   | 29 +++++++
>   9 files changed, 291 insertions(+), 22 deletions(-)
>   create mode 100644 test/tarantool-tests/gh-6097-arm64-osx-ffi-vararg.test.lua
>   create mode 100644 test/tarantool-tests/lj-205-arm64-osx-ffi-enum-arg.test.lua
>   create mode 100644 test/tarantool-tests/lj-205-arm64-osx-ffi-small-arg.test.lua
>
> diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h
> index 313b4a96..f731ab05 100644
> --- a/src/lj_asm_arm64.h
> +++ b/src/lj_asm_arm64.h
> @@ -416,7 +416,7 @@ static int asm_fuseorshift(ASMState *as, IRIns *ir)
>   static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
>   {
>     uint32_t n, nargs = CCI_XNARGS(ci);
> -  int32_t ofs = 0;
> +  int32_t spofs = 0, spalign = LJ_HASFFI && LJ_TARGET_OSX ? 0 : 7;
>     Reg gpr, fpr = REGARG_FIRSTFPR;
>     if ((void *)ci->func)
>       emit_call(as, (void *)ci->func);
> @@ -435,8 +435,14 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
>   	  fpr++;
>   	} else {
>   	  Reg r = ra_alloc1(as, ref, RSET_FPR);
> -	  emit_spstore(as, ir, r, ofs + ((LJ_BE && !irt_isnum(ir->t)) ? 4 : 0));
> -	  ofs += 8;
> +	  int32_t al = spalign;
> +#if LJ_HASFFI && LJ_TARGET_OSX
> +	  al |= irt_isnum(ir->t) ? 7 : 3;
> +#endif
> +	  spofs = (spofs + al) & ~al;
> +	  if (LJ_BE && al >= 7 && !irt_isnum(ir->t)) spofs += 4, al -= 4;
> +	  emit_spstore(as, ir, r, spofs);
> +	  spofs += al + 1;
>   	}
>         } else {
>   	if (gpr <= REGARG_LASTGPR) {
> @@ -446,10 +452,27 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
>   	  gpr++;
>   	} else {
>   	  Reg r = ra_alloc1(as, ref, RSET_GPR);
> -	  emit_spstore(as, ir, r, ofs + ((LJ_BE && !irt_is64(ir->t)) ? 4 : 0));
> -	  ofs += 8;
> +	  int32_t al = spalign;
> +#if LJ_HASFFI && LJ_TARGET_OSX
> +	  al |= irt_size(ir->t) - 1;
> +#endif
> +	  spofs = (spofs + al) & ~al;
> +	  if (al >= 3) {
> +	    if (LJ_BE && al >= 7 && !irt_is64(ir->t)) spofs += 4, al -= 4;
> +	    emit_spstore(as, ir, r, spofs);
> +	  } else {
> +	    lj_assertA(al == 0 || al == 1, "size %d unexpected", al + 1);
> +	    emit_lso(as, al ? A64I_STRH : A64I_STRB, r, RID_SP, spofs);
> +	  }
> +	  spofs += al + 1;
>   	}
>         }
> +#if LJ_HASFFI && LJ_TARGET_OSX
> +    } else {  /* Marker for start of varargs. */
> +      gpr = REGARG_LASTGPR+1;
> +      fpr = REGARG_LASTFPR+1;
> +      spalign = 7;
> +#endif
>       }
>     }
>   }
> @@ -1928,19 +1951,41 @@ static void asm_tail_prep(ASMState *as)
>   /* Ensure there are enough stack slots for call arguments. */
>   static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
>   {
> -  IRRef args[CCI_NARGS_MAX*2];
> +#if LJ_HASFFI
>     uint32_t i, nargs = CCI_XNARGS(ci);
> -  int nslots = 0, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
> -  asm_collectargs(as, ir, ci, args);
> -  for (i = 0; i < nargs; i++) {
> -    if (args[i] && irt_isfp(IR(args[i])->t)) {
> -      if (nfpr > 0) nfpr--; else nslots += 2;
> -    } else {
> -      if (ngpr > 0) ngpr--; else nslots += 2;
> +  if (nargs > (REGARG_NUMGPR < REGARG_NUMFPR ? REGARG_NUMGPR : REGARG_NUMFPR) ||
> +      (LJ_TARGET_OSX && (ci->flags & CCI_VARARG))) {
> +    IRRef args[CCI_NARGS_MAX*2];
> +    int ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
> +    int spofs = 0, spalign = LJ_TARGET_OSX ? 0 : 7, nslots;
> +    asm_collectargs(as, ir, ci, args);
> +    for (i = 0; i < nargs; i++) {
> +      int al = spalign;
> +      if (!args[i]) {
> +#if LJ_TARGET_OSX
> +	/* Marker for start of varaargs. */
> +	nfpr = 0;
> +	ngpr = 0;
> +	spalign = 7;
> +#endif
> +      } else if (irt_isfp(IR(args[i])->t)) {
> +	if (nfpr > 0) { nfpr--; continue; }
> +#if LJ_TARGET_OSX
> +	al |= irt_isnum(IR(args[i])->t) ? 7 : 3;
> +#endif
> +      } else {
> +	if (ngpr > 0) { ngpr--; continue; }
> +#if LJ_TARGET_OSX
> +	al |= irt_size(IR(args[i])->t) - 1;
> +#endif
> +      }
> +      spofs = (spofs + 2*al+1) & ~al;  /* Align and bump stack pointer. */
>       }
> +    nslots = (spofs + 3) >> 2;
> +    if (nslots > as->evenspill)  /* Leave room for args in stack slots. */
> +      as->evenspill = nslots;
>     }
> -  if (nslots > as->evenspill)  /* Leave room for args in stack slots. */
> -    as->evenspill = nslots;
> +#endif
>     return REGSP_HINT(RID_RET);
>   }
>   
> diff --git a/src/lj_ccall.c b/src/lj_ccall.c
> index 394255eb..b2705de5 100644
> --- a/src/lj_ccall.c
> +++ b/src/lj_ccall.c
> @@ -348,7 +348,6 @@
>         goto done; \
>       } else { \
>         nfpr = CCALL_NARG_FPR;  /* Prevent reordering. */ \
> -      if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \
>       } \
>     } else {  /* Try to pass argument in GPRs. */ \
>       if (!LJ_TARGET_OSX && (d->info & CTF_ALIGN) > CTALIGN_PTR) \
> @@ -359,7 +358,6 @@
>         goto done; \
>       } else { \
>         ngpr = maxgpr;  /* Prevent reordering. */ \
> -      if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \
>       } \
>     }
>   
> @@ -1027,7 +1025,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
>         CCALL_HANDLE_STRUCTARG
>       } else if (ctype_iscomplex(d->info)) {
>         CCALL_HANDLE_COMPLEXARG
> -    } else {
> +    } else if (!(CCALL_PACK_STACKARG && ctype_isenum(d->info))) {
>         sz = CTSIZE_PTR;
>       }
>       n = (sz + CTSIZE_PTR-1) / CTSIZE_PTR;  /* Number of GPRs or stack slots needed. */
> @@ -1037,12 +1035,12 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
>       /* Otherwise pass argument on stack. */
>       if (CCALL_ALIGN_STACKARG) {  /* Align argument on stack. */
>         MSize align = (1u << ctype_align(d->info)) - 1;
> -      if (rp)
> +      if (rp || (CCALL_PACK_STACKARG && isva && align < CTSIZE_PTR-1))
>   	align = CTSIZE_PTR-1;
>         nsp = (nsp + align) & ~align;
>       }
>       dp = ((uint8_t *)cc->stack) + nsp;
> -    nsp += n * CTSIZE_PTR;
> +    nsp += CCALL_PACK_STACKARG ? sz : n * CTSIZE_PTR;
>       if (nsp > CCALL_SIZE_STACK) {  /* Too many arguments. */
>       err_nyi:
>         lj_err_caller(L, LJ_ERR_FFI_NYICALL);
> @@ -1057,7 +1055,8 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
>       }
>       lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg));
>       /* Extend passed integers to 32 bits at least. */
> -    if (ctype_isinteger_or_bool(d->info) && d->size < 4) {
> +    if (ctype_isinteger_or_bool(d->info) && d->size < 4 &&
> +	(!CCALL_PACK_STACKARG || !((uintptr_t)dp & 3))) {  /* Assumes LJ_LE. */
>         if (d->info & CTF_UNSIGNED)
>   	*(uint32_t *)dp = d->size == 1 ? (uint32_t)*(uint8_t *)dp :
>   					 (uint32_t)*(uint16_t *)dp;
> diff --git a/src/lj_ccall.h b/src/lj_ccall.h
> index af7a8e84..10d93b65 100644
> --- a/src/lj_ccall.h
> +++ b/src/lj_ccall.h
> @@ -75,6 +75,9 @@ typedef union FPRArg {
>   #define CCALL_NARG_FPR		8
>   #define CCALL_NRET_FPR		4
>   #define CCALL_SPS_FREE		0
> +#if LJ_TARGET_OSX
> +#define CCALL_PACK_STACKARG	1
> +#endif
>   
>   typedef intptr_t GPRArg;
>   typedef union FPRArg {
> @@ -139,6 +142,9 @@ typedef union FPRArg {
>   #ifndef CCALL_ALIGN_STACKARG
>   #define CCALL_ALIGN_STACKARG	1
>   #endif
> +#ifndef CCALL_PACK_STACKARG
> +#define CCALL_PACK_STACKARG	0
> +#endif
>   #ifndef CCALL_ALIGN_CALLSTATE
>   #define CCALL_ALIGN_CALLSTATE	8
>   #endif
> diff --git a/src/lj_crecord.c b/src/lj_crecord.c
> index d486ee85..7d9421a6 100644
> --- a/src/lj_crecord.c
> +++ b/src/lj_crecord.c
> @@ -1122,6 +1122,12 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
>       ngpr = 1;
>     else if (ctype_cconv(info) == CTCC_FASTCALL)
>       ngpr = 2;
> +#elif LJ_TARGET_ARM64
> +#if LJ_ABI_WIN
> +#error "NYI: ARM64 Windows ABI calling conventions"
> +#elif LJ_TARGET_OSX
> +  int ngpr = CCALL_NARG_GPR;
> +#endif
>   #endif
>   
>     /* Skip initial attributes. */
> @@ -1147,6 +1153,14 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
>       } else {
>         if (!(info & CTF_VARARG))
>   	lj_trace_err(J, LJ_TRERR_NYICALL);  /* Too many arguments. */
> +#if LJ_TARGET_ARM64 && LJ_TARGET_OSX
> +      if (ngpr >= 0) {
> +	ngpr = -1;
> +	args[n++] = TREF_NIL;  /* Marker for start of varargs. */
> +	if (n >= CCI_NARGS_MAX)
> +	  lj_trace_err(J, LJ_TRERR_NYICALL);
> +      }
> +#endif
>         did = lj_ccall_ctid_vararg(cts, o);  /* Infer vararg type. */
>       }
>       d = ctype_raw(cts, did);
> @@ -1155,6 +1169,15 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
>         lj_trace_err(J, LJ_TRERR_NYICALL);
>       tr = crec_ct_tv(J, d, 0, *base, o);
>       if (ctype_isinteger_or_bool(d->info)) {
> +#if LJ_TARGET_ARM64 && LJ_TARGET_OSX
> +      if (!ngpr) {
> +	/* Fixed args passed on the stack use their unpromoted size. */
> +	if (d->size != lj_ir_type_size[tref_type(tr)]) {
> +	  lj_assertJ(d->size == 1 || d->size==2, "unexpected size %d", d->size);
> +	  tr = emitconv(tr, d->size==1 ? IRT_U8 : IRT_U16, tref_type(tr), 0);
> +	}
> +      } else
> +#endif
>         if (d->size < 4) {
>   	if ((d->info & CTF_UNSIGNED))
>   	  tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_U8 : IRT_U16, 0);
> @@ -1192,6 +1215,10 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
>         }
>       }
>   #endif
> +#elif LJ_TARGET_ARM64 && LJ_TARGET_OSX
> +    if (!ctype_isfp(d->info) && ngpr) {
> +      ngpr--;
> +    }
>   #endif
>       args[n] = tr;
>     }
> diff --git a/test/tarantool-tests/ffi-ccall/CMakeLists.txt b/test/tarantool-tests/ffi-ccall/CMakeLists.txt
> index 8acd8fe4..27de07ac 100644
> --- a/test/tarantool-tests/ffi-ccall/CMakeLists.txt
> +++ b/test/tarantool-tests/ffi-ccall/CMakeLists.txt
> @@ -1 +1,7 @@
> -BuildTestCLib(libfficcall libfficcall.c ffi-ccall-arm64-fp-convention.test.lua)
> +list(APPEND tests
> +  ffi-ccall-arm64-fp-convention.test.lua
> +  lj-205-arm64-osx-ffi-enum-arg.test.lua
> +  lj-205-arm64-osx-ffi-small-arg.test.lua
> +)
> +
> +BuildTestCLib(libfficcall libfficcall.c "${tests}")
> diff --git a/test/tarantool-tests/ffi-ccall/libfficcall.c b/test/tarantool-tests/ffi-ccall/libfficcall.c
> index 6c23f7d1..fd2d4711 100644
> --- a/test/tarantool-tests/ffi-ccall/libfficcall.c
> +++ b/test/tarantool-tests/ffi-ccall/libfficcall.c
> @@ -1,3 +1,5 @@
> +#include <stdint.h>
> +
>   struct sz12_t {
>   	float f1;
>   	float f2;
> @@ -26,3 +28,52 @@ struct sz12_t sum3sz12(struct sz12_t a, struct sz12_t b, struct sz12_t c)
>   	res.f3 = a.f3 + b.f3 + c.f3;
>   	return res;
>   }
> +
> +/****************************************************************/
> +/*                           Enums.                             */
> +/****************************************************************/
> +
> +typedef enum {
> +	E1 = 1,
> +	E2 = 2,
> +	E3 = 3,
> +	E4 = 4,
> +	E5 = 5,
> +	E6 = 6,
> +	E7 = 7,
> +	E8 = 8,
> +	E9 = 9,
> +	E10 = 10,
> +	E11 = 11
> +} enum_t;
> +
> +int test_enum_reg(enum_t e1, enum_t e2, enum_t e3)
> +{
> +	return e1 + e2 + e3;
> +}
> +
> +int test_enum_stack(enum_t e1, enum_t e2, enum_t e3, enum_t e4, enum_t e5,
> +		    enum_t e6, enum_t e7, enum_t e8, enum_t e9, enum_t e10,
> +		    enum_t e11)
> +{
> +	return e1 + e2 + e3 + e4 + e5 + e6 + e7 + e8 + e9 + e10 + e11;
> +}
> +
> +/****************************************************************/
> +/*                  Basic types (< 8 bytes).                    */
> +/****************************************************************/
> +
> +uint8_t test_u8_stack(uint8_t u1, uint8_t u2, uint8_t u3, uint8_t u4,
> +		      uint8_t u5, uint8_t u6, uint8_t u7, uint8_t u8,
> +		      uint8_t u9, uint8_t u10, uint8_t u11)
> +{
> +	return u1 + u2 + u3 + u4 + u5 + u6 + u7 + u8 + u9 + u10 + u11;
> +}
> +
> +float test_float_stack(float f1, float f2, float f3, float f4, float f5,
> +		       float f6, float f7, float f8, float f9, float f10,
> +		       float f11)
> +{
> +	return f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11;
> +}
> +
newline is not needed
> diff --git a/test/tarantool-tests/gh-6097-arm64-osx-ffi-vararg.test.lua b/test/tarantool-tests/gh-6097-arm64-osx-ffi-vararg.test.lua
> new file mode 100644
> index 00000000..fc44d253
> --- /dev/null
> +++ b/test/tarantool-tests/gh-6097-arm64-osx-ffi-vararg.test.lua
> @@ -0,0 +1,43 @@
> +local tap = require('tap')
> +
> +-- The test file to demonstrate LuaJIT incorrect FFI vararg call
> +-- on macOS M1.
> +-- See also:https://github.com/tarantool/tarantool/issues/6097.
> +local test = tap.test('gh-6097-arm64-osx-ffi-vararg'):skipcond({
> +  ['Test requires JIT enabled'] = not jit.status(),
> +})
> +
> +test:plan(4)
> +
> +local ffi = require('ffi')
> +
> +ffi.cdef('int sprintf(char *str, const char *format, ...)')
> +
> +local EXPECTED = '1'
> +local EXPECTED_LEN = #EXPECTED
> +
> +local str = ffi.new(string.format('char[256]'))
> +
> +jit.opt.start('hotloop=1')
> +
> +local results = {}
> +for i = 1, 4 do
> +  local strlen = ffi.C.sprintf(str, '%d', 1LL)
honestly, I didn't get why the resulted buffer is named "strlen". The 
same is below.
> +  assert(strlen == EXPECTED_LEN, 'correct string length for result')
> +  results[i] = ffi.string(str)
> +end
> +
> +test:is(results[1], EXPECTED, 'correct result of FFI vararg call for int')
> +test:samevalues(results, 'consistent behaviour JIT and VM for vararg int arg')
> +
> +results = {}
> +for i = 1, 4 do
> +  local strlen = ffi.C.sprintf(str, '%c', ffi.new('char', string.byte('1')))
> +  assert(strlen == EXPECTED_LEN, 'correct string length for result')
> +  results[i] = ffi.string(str)
> +end
> +
> +test:is(results[1], EXPECTED, 'correct result of FFI vararg call for char')
> +test:samevalues(results, 'consistent behaviour JIT and VM for vararg char arg')
> +
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-205-arm64-osx-ffi-enum-arg.test.lua b/test/tarantool-tests/lj-205-arm64-osx-ffi-enum-arg.test.lua
> new file mode 100644
> index 00000000..4ba4f69d
> --- /dev/null
> +++ b/test/tarantool-tests/lj-205-arm64-osx-ffi-enum-arg.test.lua
> @@ -0,0 +1,63 @@
> +local ffi = require('ffi')
> +local tap = require('tap')
> +
> +local ffi_ccall = ffi.load('libfficcall')
> +
> +-- The test file to check the FFI call for enum arguments.
> +-- See also:https://github.com/LuaJIT/LuaJIT/issues/205.
> +local test = tap.test('lj-205-arm64-osx-ffi-enum-arg'):skipcond({
> +  ['Test requires JIT enabled'] = not jit.status(),
> +})
> +
> +test:plan(4)
> +
> +ffi.cdef[[
> +  int sprintf(char *str, const char *format, ...);
> +
> +  typedef enum {
> +    E1 = 1,
> +    E2 = 2,
> +    E3 = 3,
> +    E4 = 4,
> +    E5 = 5,
> +    E6 = 6,
> +    E7 = 7,
> +    E8 = 8,
> +    E9 = 9,
> +    E10 = 10,
> +    E11 = 11
> +  } enum_t;
> +
> +  int test_enum_reg(enum_t e1, enum_t e2, enum_t e3);
> +
> +  int test_enum_stack(enum_t e1, enum_t e2, enum_t e3, enum_t e4, enum_t e5,
> +                      enum_t e6, enum_t e7, enum_t e8, enum_t e9, enum_t e10,
> +                      enum_t e11);
> +]]
> +
> +
> +local str = ffi.new(string.format('char[256]'))
> +
> +jit.opt.start('hotloop=1')
> +
> +local enum_t = ffi.typeof('enum_t')
> +
> +local results = {}
> +for i = 1, 4 do
> +  local strlen = ffi.C.sprintf(str, '%d', enum_t(1))
> +  assert(strlen == 1, 'correct string length for result')
> +  results[i] = ffi.string(str)
> +end
> +
> +test:is(results[1], '1', 'correct result of FFI vararg call for enum')
> +test:samevalues(results, 'consistent behaviour JIT and VM for vararg enum arg')
> +
> +test:is(ffi_ccall.test_enum_reg(enum_t(1), enum_t(2), enum_t(3)), 6,
> +        'correct enum reg pass')
> +
> +test:is(ffi_ccall.test_enum_stack(enum_t(1), enum_t(2), enum_t(3), enum_t(4),
> +                                  enum_t(5), enum_t(6), enum_t(7), enum_t(8),
> +                                  enum_t(9), enum_t(10), enum_t(11)),
> +        66, 'correct enum stack pass')
> +
> +test:done(true)
> diff --git a/test/tarantool-tests/lj-205-arm64-osx-ffi-small-arg.test.lua b/test/tarantool-tests/lj-205-arm64-osx-ffi-small-arg.test.lua
> new file mode 100644
> index 00000000..be60de93
> --- /dev/null
> +++ b/test/tarantool-tests/lj-205-arm64-osx-ffi-small-arg.test.lua
> @@ -0,0 +1,29 @@
> +local ffi = require('ffi')
> +local tap = require('tap')
> +
> +local ffi_ccall = ffi.load('libfficcall')
> +
> +-- The test file to check the FFI call for small (<8 bytes)
> +-- arguments give on stack.
> +-- See also:https://github.com/LuaJIT/LuaJIT/issues/205.
> +local test = tap.test('lj-205-arm64-osx-ffi-small-arg')
> +test:plan(2)
> +
> +ffi.cdef[[
> +  uint8_t test_u8_stack(uint8_t u1, uint8_t u2, uint8_t u3, uint8_t u4,
> +                        uint8_t u5, uint8_t u6, uint8_t u7, uint8_t u8,
> +                        uint8_t u9, uint8_t u10, uint8_t u11);
> +
> +  float test_float_stack(float f1, float f2, float f3, float f4, float f5,
> +                         float f6, float f7, float f8, float f9, float f10,
> +                         float f11);
> +]]
> +
> +test:is(ffi_ccall.test_u8_stack(1ULL, 2ULL, 3ULL, 4ULL, 5ULL, 6ULL, 7ULL,
> +                                8ULL, 9ULL, 10ULL, 11ULL),
> +        66, 'correct uint8_t stack pass')
> +
> +test:is(ffi_ccall.test_float_stack(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), 66,
> +        'correct float stack pass')
> +
> +test:done(true)

[-- Attachment #2: Type: text/html, Size: 19222 bytes --]

  reply	other threads:[~2026-06-01 11:40 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-30 16:04 [Tarantool-patches] [PATCH luajit 0/5] Various FFI ABI calling conventions fixes Sergey Kaplun via Tarantool-patches
2026-05-30 16:04 ` [Tarantool-patches] [PATCH luajit 1/5] FFI: Unify stack setup for C calls in interpreter Sergey Kaplun via Tarantool-patches
2026-05-30 16:04 ` [Tarantool-patches] [PATCH luajit 2/5] FFI/ARM64/OSX: Handle non-standard OSX C calling conventions Sergey Kaplun via Tarantool-patches
2026-06-01 11:40   ` Sergey Bronnikov via Tarantool-patches [this message]
2026-05-30 16:04 ` [Tarantool-patches] [PATCH luajit 3/5] ARM64: Fix pass-by-value struct " Sergey Kaplun via Tarantool-patches
2026-06-01 12:27   ` Sergey Bronnikov via Tarantool-patches
2026-05-30 16:04 ` [Tarantool-patches] [PATCH luajit 4/5] FFI: Various ABI and calling convention fixes Sergey Kaplun via Tarantool-patches
2026-06-01 13:02   ` Sergey Bronnikov via Tarantool-patches
2026-05-30 16:04 ` [Tarantool-patches] [PATCH luajit 5/5] FFI/MacOS: Fix calling convention for enums Sergey Kaplun via Tarantool-patches
2026-06-01 13:07   ` Sergey Bronnikov via Tarantool-patches

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ef0938ef-c671-4885-8b01-c491d9d6bb88@tarantool.org \
    --to=tarantool-patches@dev.tarantool.org \
    --cc=e.temirgaleev@tarantool.org \
    --cc=sergeyb@tarantool.org \
    --cc=skaplun@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH luajit 2/5] FFI/ARM64/OSX: Handle non-standard OSX C calling conventions.' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox