From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 702C06ECF5; Sat, 30 May 2026 19:05:48 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 702C06ECF5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1780157148; bh=CjpN0RmZwYzcVvH97XgMArmvkhFLwYqDsVu0nVOO3HE=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=B/rePzLoKX4+NhoUde/oysPBsQN8XUbLAKC/OvbRR+d6XzkvRDi5+Tb4c/fLgFrFI /muYwZYoFl6jucMzi+aI/roZUkd1ASQ6wNcuIlYhDAcYickQZsJkhjNi03rcqmVTgk VU3+Cv/nExV6jEIaXZGRFysAjBebwXnOvpoDFImM= Received: from send104.i.mail.ru (send104.i.mail.ru [89.221.237.199]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id AF8CF6ECF5 for ; Sat, 30 May 2026 19:04:47 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org AF8CF6ECF5 Received: by exim-smtp-5b85998476-w27zp with esmtpa (envelope-from ) id 1wTMB4-00000000NxS-28kq; Sat, 30 May 2026 19:04:47 +0300 To: Sergey Bronnikov , Evgeniy Temirgaleev Date: Sat, 30 May 2026 19:04:06 +0300 Message-ID: <20260530160409.4043089-3-skaplun@tarantool.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260530160409.4043089-1-skaplun@tarantool.org> References: <20260530160409.4043089-1-skaplun@tarantool.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailru-Src: smtp X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD9402BF17F4A9A44D6AD82277AB1EF80057AC569570370E8A800894C459B0CD1B9EFBF534F92FC82D766FA44935DFD41249EB2F7CFAE4083348063F32B492FEB80B04C393452CF6677 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7832AD58179B12F4FEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637AC83A81C8FD4AD23D82A6BABE6F325AC2E85FA5F3EDFCBAA7353EFBB55337566A66E13412CE89A70BA250FF959CF95C483B4A56FFE45714BAAC0A6937103D689389733CBF5DBD5E913377AFFFEAFD269176DF2183F8FC7C06030C3405640F6718941B15DA834481FCF19DD082D7633A0EF3E4896CB9E6436389733CBF5DBD5E9D5E8D9A59859A8B6BAA8CD687FCDB2EBCC7F00164DA146DA6F5DAA56C3B73B237318B6A418E8EAB86D1867E19FE14079C09775C1D3CA48CF3D321E7403792E342EB15956EA79C166A417C69337E82CC275ECD9A6C639B01B78DA827A17800CE71F4E386938175FB9731C566533BA786AA5CC5B56E945C8DA X-C1DE0DAB: 0D63561A33F958A5375C038DFEB990E45002B1117B3ED696526DDD0947C7B9B547A99E6294EE8661823CB91A9FED034534781492E4B8EEADA7D01B58E6BF979CC79554A2A72441328621D336A7BC284946AD531847A6065A535571D14F44ED41 X-C8649E89: 1C3962B70DF3F0AD73CAD6646DEDE191716CD42B3DD1D34CAB70F9BE574AE9C625B6776AC983F447FC0B9F89525902EE6F57B2FD27647F25E66C117BDB76D65965367E97CB890435B093E2867420C0C7143512DBE1296FFDB88376CAB1F4939654AC67B2299B25F8B8341EE9D5BE9A0AC53FD2B06EC541794EEFE4E6A881BF006DCCAB25F2B614ADC7CEAA0681F5848F4C41F94D744909CECFA6C6B0C050A61A8CAF69B82BA93681CD72808BE417F3B9E0E7457915DAA85F X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu53w8ahmwBjZKM/YPHZyZHvz5uv+WouB9+ObcCpyrx6l7KImUglyhkEat/+ysWwi0gdhEs0JGjl6ggRWTy1haxBpVdbIX1nthFXMZebaIdHP2ghjoIc/363UZI6Kf1ptIMVRI2994ruhLUK4Yr1jOJcUI= X-DA7885C5: 86F3D9748E961CDFF255D290C0D534F9F2EF0D835F9EF3DF011AFD2E85B3E06D0A7FA24AB565860D5B1A4C17EAA7BC4BEF2421ABFA55128DAF83EF9164C44C7E X-Mailru-Sender: 689FA8AB762F7393520AF17B8A65FDE2F1BD4FF13AE946F108715E8504D67BFA9D3733D8AF7A7DBCE49D44BB4BD9522A059A1ED8796F048DB274557F927329BE89D5A3BC2B10C37545BD1C3CC395C826B4A721A3011E896F X-Mras: Ok Subject: [Tarantool-patches] [PATCH luajit 2/5] FFI/ARM64/OSX: Handle non-standard OSX C calling conventions. X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Kaplun via Tarantool-patches Reply-To: Sergey Kaplun Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" From: Mike Pall 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 + 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; +} + 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) + 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) -- 2.54.0