aboutsummaryrefslogtreecommitdiff
path: root/src/lj_ccallback.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_ccallback.c')
-rw-r--r--src/lj_ccallback.c239
1 files changed, 191 insertions, 48 deletions
diff --git a/src/lj_ccallback.c b/src/lj_ccallback.c
index 26377f82..4edd8a35 100644
--- a/src/lj_ccallback.c
+++ b/src/lj_ccallback.c
@@ -27,7 +27,7 @@
27 27
28#if LJ_OS_NOJIT 28#if LJ_OS_NOJIT
29 29
30/* Disabled callback support. */ 30/* Callbacks disabled. */
31#define CALLBACK_SLOT2OFS(slot) (0*(slot)) 31#define CALLBACK_SLOT2OFS(slot) (0*(slot))
32#define CALLBACK_OFS2SLOT(ofs) (0*(ofs)) 32#define CALLBACK_OFS2SLOT(ofs) (0*(ofs))
33#define CALLBACK_MAX_SLOT 0 33#define CALLBACK_MAX_SLOT 0
@@ -35,7 +35,7 @@
35#elif LJ_TARGET_X86ORX64 35#elif LJ_TARGET_X86ORX64
36 36
37#define CALLBACK_MCODE_HEAD (LJ_64 ? 8 : 0) 37#define CALLBACK_MCODE_HEAD (LJ_64 ? 8 : 0)
38#define CALLBACK_MCODE_GROUP (-2+1+2+5+(LJ_64 ? 6 : 5)) 38#define CALLBACK_MCODE_GROUP (-2+1+2+(LJ_GC64 ? 10 : 5)+(LJ_64 ? 6 : 5))
39 39
40#define CALLBACK_SLOT2OFS(slot) \ 40#define CALLBACK_SLOT2OFS(slot) \
41 (CALLBACK_MCODE_HEAD + CALLBACK_MCODE_GROUP*((slot)/32) + 4*(slot)) 41 (CALLBACK_MCODE_HEAD + CALLBACK_MCODE_GROUP*((slot)/32) + 4*(slot))
@@ -54,23 +54,22 @@ static MSize CALLBACK_OFS2SLOT(MSize ofs)
54#elif LJ_TARGET_ARM 54#elif LJ_TARGET_ARM
55 55
56#define CALLBACK_MCODE_HEAD 32 56#define CALLBACK_MCODE_HEAD 32
57#define CALLBACK_SLOT2OFS(slot) (CALLBACK_MCODE_HEAD + 8*(slot)) 57
58#define CALLBACK_OFS2SLOT(ofs) (((ofs)-CALLBACK_MCODE_HEAD)/8) 58#elif LJ_TARGET_ARM64
59#define CALLBACK_MAX_SLOT (CALLBACK_OFS2SLOT(CALLBACK_MCODE_SIZE)) 59
60#define CALLBACK_MCODE_HEAD 32
60 61
61#elif LJ_TARGET_PPC 62#elif LJ_TARGET_PPC
62 63
63#define CALLBACK_MCODE_HEAD 24 64#define CALLBACK_MCODE_HEAD 24
64#define CALLBACK_SLOT2OFS(slot) (CALLBACK_MCODE_HEAD + 8*(slot))
65#define CALLBACK_OFS2SLOT(ofs) (((ofs)-CALLBACK_MCODE_HEAD)/8)
66#define CALLBACK_MAX_SLOT (CALLBACK_OFS2SLOT(CALLBACK_MCODE_SIZE))
67 65
68#elif LJ_TARGET_MIPS 66#elif LJ_TARGET_MIPS32
69 67
70#define CALLBACK_MCODE_HEAD 24 68#define CALLBACK_MCODE_HEAD 20
71#define CALLBACK_SLOT2OFS(slot) (CALLBACK_MCODE_HEAD + 8*(slot)) 69
72#define CALLBACK_OFS2SLOT(ofs) (((ofs)-CALLBACK_MCODE_HEAD)/8) 70#elif LJ_TARGET_MIPS64
73#define CALLBACK_MAX_SLOT (CALLBACK_OFS2SLOT(CALLBACK_MCODE_SIZE)) 71
72#define CALLBACK_MCODE_HEAD 52
74 73
75#else 74#else
76 75
@@ -81,6 +80,12 @@ static MSize CALLBACK_OFS2SLOT(MSize ofs)
81 80
82#endif 81#endif
83 82
83#ifndef CALLBACK_SLOT2OFS
84#define CALLBACK_SLOT2OFS(slot) (CALLBACK_MCODE_HEAD + 8*(slot))
85#define CALLBACK_OFS2SLOT(ofs) (((ofs)-CALLBACK_MCODE_HEAD)/8)
86#define CALLBACK_MAX_SLOT (CALLBACK_OFS2SLOT(CALLBACK_MCODE_SIZE))
87#endif
88
84/* Convert callback slot number to callback function pointer. */ 89/* Convert callback slot number to callback function pointer. */
85static void *callback_slot2ptr(CTState *cts, MSize slot) 90static void *callback_slot2ptr(CTState *cts, MSize slot)
86{ 91{
@@ -119,8 +124,13 @@ static void callback_mcode_init(global_State *g, uint8_t *page)
119 /* push ebp/rbp; mov ah, slot>>8; mov ebp, &g. */ 124 /* push ebp/rbp; mov ah, slot>>8; mov ebp, &g. */
120 *p++ = XI_PUSH + RID_EBP; 125 *p++ = XI_PUSH + RID_EBP;
121 *p++ = XI_MOVrib | (RID_EAX+4); *p++ = (uint8_t)(slot >> 8); 126 *p++ = XI_MOVrib | (RID_EAX+4); *p++ = (uint8_t)(slot >> 8);
127#if LJ_GC64
128 *p++ = 0x48; *p++ = XI_MOVri | RID_EBP;
129 *(uint64_t *)p = (uint64_t)(g); p += 8;
130#else
122 *p++ = XI_MOVri | RID_EBP; 131 *p++ = XI_MOVri | RID_EBP;
123 *(int32_t *)p = i32ptr(g); p += 4; 132 *(int32_t *)p = i32ptr(g); p += 4;
133#endif
124#if LJ_64 134#if LJ_64
125 /* jmp [rip-pageofs] where lj_vm_ffi_callback is stored. */ 135 /* jmp [rip-pageofs] where lj_vm_ffi_callback is stored. */
126 *p++ = XI_GROUP5; *p++ = XM_OFS0 + (XOg_JMP<<3) + RID_EBP; 136 *p++ = XI_GROUP5; *p++ = XM_OFS0 + (XOg_JMP<<3) + RID_EBP;
@@ -157,6 +167,26 @@ static void callback_mcode_init(global_State *g, uint32_t *page)
157 } 167 }
158 lua_assert(p - page <= CALLBACK_MCODE_SIZE); 168 lua_assert(p - page <= CALLBACK_MCODE_SIZE);
159} 169}
170#elif LJ_TARGET_ARM64
171static void callback_mcode_init(global_State *g, uint32_t *page)
172{
173 uint32_t *p = page;
174 void *target = (void *)lj_vm_ffi_callback;
175 MSize slot;
176 *p++ = A64I_LE(A64I_LDRLx | A64F_D(RID_X11) | A64F_S19(4));
177 *p++ = A64I_LE(A64I_LDRLx | A64F_D(RID_X10) | A64F_S19(5));
178 *p++ = A64I_LE(A64I_BR | A64F_N(RID_X11));
179 *p++ = A64I_LE(A64I_NOP);
180 ((void **)p)[0] = target;
181 ((void **)p)[1] = g;
182 p += 4;
183 for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
184 *p++ = A64I_LE(A64I_MOVZw | A64F_D(RID_X9) | A64F_U16(slot));
185 *p = A64I_LE(A64I_B | A64F_S26((page-p) & 0x03ffffffu));
186 p++;
187 }
188 lua_assert(p - page <= CALLBACK_MCODE_SIZE);
189}
160#elif LJ_TARGET_PPC 190#elif LJ_TARGET_PPC
161static void callback_mcode_init(global_State *g, uint32_t *page) 191static void callback_mcode_init(global_State *g, uint32_t *page)
162{ 192{
@@ -180,14 +210,27 @@ static void callback_mcode_init(global_State *g, uint32_t *page)
180static void callback_mcode_init(global_State *g, uint32_t *page) 210static void callback_mcode_init(global_State *g, uint32_t *page)
181{ 211{
182 uint32_t *p = page; 212 uint32_t *p = page;
183 void *target = (void *)lj_vm_ffi_callback; 213 uintptr_t target = (uintptr_t)(void *)lj_vm_ffi_callback;
214 uintptr_t ug = (uintptr_t)(void *)g;
184 MSize slot; 215 MSize slot;
185 *p++ = MIPSI_SW | MIPSF_T(RID_R1)|MIPSF_S(RID_SP) | 0; 216#if LJ_TARGET_MIPS32
186 *p++ = MIPSI_LUI | MIPSF_T(RID_R3) | (u32ptr(target) >> 16); 217 *p++ = MIPSI_LUI | MIPSF_T(RID_R3) | (target >> 16);
187 *p++ = MIPSI_LUI | MIPSF_T(RID_R2) | (u32ptr(g) >> 16); 218 *p++ = MIPSI_LUI | MIPSF_T(RID_R2) | (ug >> 16);
188 *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) |(u32ptr(target)&0xffff); 219#else
220 *p++ = MIPSI_LUI | MIPSF_T(RID_R3) | (target >> 48);
221 *p++ = MIPSI_LUI | MIPSF_T(RID_R2) | (ug >> 48);
222 *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) | ((target >> 32) & 0xffff);
223 *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | ((ug >> 32) & 0xffff);
224 *p++ = MIPSI_DSLL | MIPSF_D(RID_R3)|MIPSF_T(RID_R3) | MIPSF_A(16);
225 *p++ = MIPSI_DSLL | MIPSF_D(RID_R2)|MIPSF_T(RID_R2) | MIPSF_A(16);
226 *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) | ((target >> 16) & 0xffff);
227 *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | ((ug >> 16) & 0xffff);
228 *p++ = MIPSI_DSLL | MIPSF_D(RID_R3)|MIPSF_T(RID_R3) | MIPSF_A(16);
229 *p++ = MIPSI_DSLL | MIPSF_D(RID_R2)|MIPSF_T(RID_R2) | MIPSF_A(16);
230#endif
231 *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) | (target & 0xffff);
189 *p++ = MIPSI_JR | MIPSF_S(RID_R3); 232 *p++ = MIPSI_JR | MIPSF_S(RID_R3);
190 *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | (u32ptr(g)&0xffff); 233 *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | (ug & 0xffff);
191 for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) { 234 for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
192 *p = MIPSI_B | ((page-p-1) & 0x0000ffffu); 235 *p = MIPSI_B | ((page-p-1) & 0x0000ffffu);
193 p++; 236 p++;
@@ -224,7 +267,7 @@ static void callback_mcode_new(CTState *cts)
224 if (CALLBACK_MAX_SLOT == 0) 267 if (CALLBACK_MAX_SLOT == 0)
225 lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV); 268 lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV);
226#if LJ_TARGET_WINDOWS 269#if LJ_TARGET_WINDOWS
227 p = VirtualAlloc(NULL, sz, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 270 p = LJ_WIN_VALLOC(NULL, sz, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
228 if (!p) 271 if (!p)
229 lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV); 272 lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV);
230#elif LJ_TARGET_POSIX 273#elif LJ_TARGET_POSIX
@@ -242,7 +285,7 @@ static void callback_mcode_new(CTState *cts)
242#if LJ_TARGET_WINDOWS 285#if LJ_TARGET_WINDOWS
243 { 286 {
244 DWORD oprot; 287 DWORD oprot;
245 VirtualProtect(p, sz, PAGE_EXECUTE_READ, &oprot); 288 LJ_WIN_VPROTECT(p, sz, PAGE_EXECUTE_READ, &oprot);
246 } 289 }
247#elif LJ_TARGET_POSIX 290#elif LJ_TARGET_POSIX
248 mprotect(p, sz, (PROT_READ|PROT_EXEC)); 291 mprotect(p, sz, (PROT_READ|PROT_EXEC));
@@ -351,33 +394,77 @@ void lj_ccallback_mcode_free(CTState *cts)
351 goto done; \ 394 goto done; \
352 } CALLBACK_HANDLE_REGARG_FP2 395 } CALLBACK_HANDLE_REGARG_FP2
353 396
354#elif LJ_TARGET_PPC 397#elif LJ_TARGET_ARM64
355 398
356#define CALLBACK_HANDLE_REGARG \ 399#define CALLBACK_HANDLE_REGARG \
357 if (isfp) { \ 400 if (isfp) { \
358 if (nfpr + 1 <= CCALL_NARG_FPR) { \ 401 if (nfpr + n <= CCALL_NARG_FPR) { \
359 sp = &cts->cb.fpr[nfpr++]; \ 402 sp = &cts->cb.fpr[nfpr]; \
360 cta = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */ \ 403 nfpr += n; \
361 goto done; \ 404 goto done; \
405 } else { \
406 nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \
362 } \ 407 } \
363 } else { /* Try to pass argument in GPRs. */ \ 408 } else { \
364 if (n > 1) { \ 409 if (!LJ_TARGET_IOS && n > 1) \
365 lua_assert(ctype_isinteger(cta->info) && n == 2); /* int64_t. */ \ 410 ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
366 ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
367 } \
368 if (ngpr + n <= maxgpr) { \ 411 if (ngpr + n <= maxgpr) { \
369 sp = &cts->cb.gpr[ngpr]; \ 412 sp = &cts->cb.gpr[ngpr]; \
370 ngpr += n; \ 413 ngpr += n; \
371 goto done; \ 414 goto done; \
415 } else { \
416 ngpr = CCALL_NARG_GPR; /* Prevent reordering. */ \
417 } \
418 }
419
420#elif LJ_TARGET_PPC
421
422#define CALLBACK_HANDLE_GPR \
423 if (n > 1) { \
424 lua_assert(((LJ_ABI_SOFTFP && ctype_isnum(cta->info)) || /* double. */ \
425 ctype_isinteger(cta->info)) && n == 2); /* int64_t. */ \
426 ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
427 } \
428 if (ngpr + n <= maxgpr) { \
429 sp = &cts->cb.gpr[ngpr]; \
430 ngpr += n; \
431 goto done; \
432 }
433
434#if LJ_ABI_SOFTFP
435#define CALLBACK_HANDLE_REGARG \
436 CALLBACK_HANDLE_GPR \
437 UNUSED(isfp);
438#else
439#define CALLBACK_HANDLE_REGARG \
440 if (isfp) { \
441 if (nfpr + 1 <= CCALL_NARG_FPR) { \
442 sp = &cts->cb.fpr[nfpr++]; \
443 cta = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */ \
444 goto done; \
372 } \ 445 } \
446 } else { /* Try to pass argument in GPRs. */ \
447 CALLBACK_HANDLE_GPR \
373 } 448 }
449#endif
374 450
451#if !LJ_ABI_SOFTFP
375#define CALLBACK_HANDLE_RET \ 452#define CALLBACK_HANDLE_RET \
376 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \ 453 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
377 *(double *)dp = *(float *)dp; /* FPRs always hold doubles. */ 454 *(double *)dp = *(float *)dp; /* FPRs always hold doubles. */
455#endif
378 456
379#elif LJ_TARGET_MIPS 457#elif LJ_TARGET_MIPS32
380 458
459#define CALLBACK_HANDLE_GPR \
460 if (n > 1) ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
461 if (ngpr + n <= maxgpr) { \
462 sp = &cts->cb.gpr[ngpr]; \
463 ngpr += n; \
464 goto done; \
465 }
466
467#if !LJ_ABI_SOFTFP /* MIPS32 hard-float */
381#define CALLBACK_HANDLE_REGARG \ 468#define CALLBACK_HANDLE_REGARG \
382 if (isfp && nfpr < CCALL_NARG_FPR) { /* Try to pass argument in FPRs. */ \ 469 if (isfp && nfpr < CCALL_NARG_FPR) { /* Try to pass argument in FPRs. */ \
383 sp = (void *)((uint8_t *)&cts->cb.fpr[nfpr] + ((LJ_BE && n==1) ? 4 : 0)); \ 470 sp = (void *)((uint8_t *)&cts->cb.fpr[nfpr] + ((LJ_BE && n==1) ? 4 : 0)); \
@@ -385,13 +472,36 @@ void lj_ccallback_mcode_free(CTState *cts)
385 goto done; \ 472 goto done; \
386 } else { /* Try to pass argument in GPRs. */ \ 473 } else { /* Try to pass argument in GPRs. */ \
387 nfpr = CCALL_NARG_FPR; \ 474 nfpr = CCALL_NARG_FPR; \
388 if (n > 1) ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \ 475 CALLBACK_HANDLE_GPR \
389 if (ngpr + n <= maxgpr) { \ 476 }
390 sp = &cts->cb.gpr[ngpr]; \ 477#else /* MIPS32 soft-float */
391 ngpr += n; \ 478#define CALLBACK_HANDLE_REGARG \
392 goto done; \ 479 CALLBACK_HANDLE_GPR \
393 } \ 480 UNUSED(isfp);
481#endif
482
483#define CALLBACK_HANDLE_RET \
484 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
485 ((float *)dp)[1] = *(float *)dp;
486
487#elif LJ_TARGET_MIPS64
488
489#if !LJ_ABI_SOFTFP /* MIPS64 hard-float */
490#define CALLBACK_HANDLE_REGARG \
491 if (ngpr + n <= maxgpr) { \
492 sp = isfp ? (void*) &cts->cb.fpr[ngpr] : (void*) &cts->cb.gpr[ngpr]; \
493 ngpr += n; \
494 goto done; \
394 } 495 }
496#else /* MIPS64 soft-float */
497#define CALLBACK_HANDLE_REGARG \
498 if (ngpr + n <= maxgpr) { \
499 UNUSED(isfp); \
500 sp = (void*) &cts->cb.gpr[ngpr]; \
501 ngpr += n; \
502 goto done; \
503 }
504#endif
395 505
396#define CALLBACK_HANDLE_RET \ 506#define CALLBACK_HANDLE_RET \
397 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \ 507 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
@@ -411,6 +521,7 @@ static void callback_conv_args(CTState *cts, lua_State *L)
411 int gcsteps = 0; 521 int gcsteps = 0;
412 CType *ct; 522 CType *ct;
413 GCfunc *fn; 523 GCfunc *fn;
524 int fntp;
414 MSize ngpr = 0, nsp = 0, maxgpr = CCALL_NARG_GPR; 525 MSize ngpr = 0, nsp = 0, maxgpr = CCALL_NARG_GPR;
415#if CCALL_NARG_FPR 526#if CCALL_NARG_FPR
416 MSize nfpr = 0; 527 MSize nfpr = 0;
@@ -421,18 +532,27 @@ static void callback_conv_args(CTState *cts, lua_State *L)
421 532
422 if (slot < cts->cb.sizeid && (id = cts->cb.cbid[slot]) != 0) { 533 if (slot < cts->cb.sizeid && (id = cts->cb.cbid[slot]) != 0) {
423 ct = ctype_get(cts, id); 534 ct = ctype_get(cts, id);
424 rid = ctype_cid(ct->info); 535 rid = ctype_cid(ct->info); /* Return type. x86: +(spadj<<16). */
425 fn = funcV(lj_tab_getint(cts->miscmap, (int32_t)slot)); 536 fn = funcV(lj_tab_getint(cts->miscmap, (int32_t)slot));
537 fntp = LJ_TFUNC;
426 } else { /* Must set up frame first, before throwing the error. */ 538 } else { /* Must set up frame first, before throwing the error. */
427 ct = NULL; 539 ct = NULL;
428 rid = 0; 540 rid = 0;
429 fn = (GCfunc *)L; 541 fn = (GCfunc *)L;
542 fntp = LJ_TTHREAD;
543 }
544 /* Continuation returns from callback. */
545 if (LJ_FR2) {
546 (o++)->u64 = LJ_CONT_FFI_CALLBACK;
547 (o++)->u64 = rid;
548 o++;
549 } else {
550 o->u32.lo = LJ_CONT_FFI_CALLBACK;
551 o->u32.hi = rid;
552 o++;
430 } 553 }
431 o->u32.lo = LJ_CONT_FFI_CALLBACK; /* Continuation returns from callback. */ 554 setframe_gc(o, obj2gco(fn), fntp);
432 o->u32.hi = rid; /* Return type. x86: +(spadj<<16). */ 555 setframe_ftsz(o, ((char *)(o+1) - (char *)L->base) + FRAME_CONT);
433 o++;
434 setframe_gc(o, obj2gco(fn));
435 setframe_ftsz(o, (int)((char *)(o+1) - (char *)L->base) + FRAME_CONT);
436 L->top = L->base = ++o; 556 L->top = L->base = ++o;
437 if (!ct) 557 if (!ct)
438 lj_err_caller(cts->L, LJ_ERR_FFI_BADCBACK); 558 lj_err_caller(cts->L, LJ_ERR_FFI_BADCBACK);
@@ -474,7 +594,11 @@ static void callback_conv_args(CTState *cts, lua_State *L)
474 nsp += n; 594 nsp += n;
475 595
476 done: 596 done:
477 if (LJ_BE && cta->size < CTSIZE_PTR) 597 if (LJ_BE && cta->size < CTSIZE_PTR
598#if LJ_TARGET_MIPS64
599 && !(isfp && nsp)
600#endif
601 )
478 sp = (void *)((uint8_t *)sp + CTSIZE_PTR-cta->size); 602 sp = (void *)((uint8_t *)sp + CTSIZE_PTR-cta->size);
479 gcsteps += lj_cconv_tv_ct(cts, cta, 0, o++, sp); 603 gcsteps += lj_cconv_tv_ct(cts, cta, 0, o++, sp);
480 } 604 }
@@ -483,9 +607,14 @@ static void callback_conv_args(CTState *cts, lua_State *L)
483 L->top = o; 607 L->top = o;
484#if LJ_TARGET_X86 608#if LJ_TARGET_X86
485 /* Store stack adjustment for returns from non-cdecl callbacks. */ 609 /* Store stack adjustment for returns from non-cdecl callbacks. */
486 if (ctype_cconv(ct->info) != CTCC_CDECL) 610 if (ctype_cconv(ct->info) != CTCC_CDECL) {
611#if LJ_FR2
612 (L->base-3)->u64 |= (nsp << (16+2));
613#else
487 (L->base-2)->u32.hi |= (nsp << (16+2)); 614 (L->base-2)->u32.hi |= (nsp << (16+2));
488#endif 615#endif
616 }
617#endif
489 while (gcsteps-- > 0) 618 while (gcsteps-- > 0)
490 lj_gc_check(L); 619 lj_gc_check(L);
491} 620}
@@ -493,7 +622,11 @@ static void callback_conv_args(CTState *cts, lua_State *L)
493/* Convert Lua object to callback result. */ 622/* Convert Lua object to callback result. */
494static void callback_conv_result(CTState *cts, lua_State *L, TValue *o) 623static void callback_conv_result(CTState *cts, lua_State *L, TValue *o)
495{ 624{
625#if LJ_FR2
626 CType *ctr = ctype_raw(cts, (uint16_t)(L->base-3)->u64);
627#else
496 CType *ctr = ctype_raw(cts, (uint16_t)(L->base-2)->u32.hi); 628 CType *ctr = ctype_raw(cts, (uint16_t)(L->base-2)->u32.hi);
629#endif
497#if LJ_TARGET_X86 630#if LJ_TARGET_X86
498 cts->cb.gpr[2] = 0; 631 cts->cb.gpr[2] = 0;
499#endif 632#endif
@@ -503,6 +636,10 @@ static void callback_conv_result(CTState *cts, lua_State *L, TValue *o)
503 if (ctype_isfp(ctr->info)) 636 if (ctype_isfp(ctr->info))
504 dp = (uint8_t *)&cts->cb.fpr[0]; 637 dp = (uint8_t *)&cts->cb.fpr[0];
505#endif 638#endif
639#if LJ_TARGET_ARM64 && LJ_BE
640 if (ctype_isfp(ctr->info) && ctr->size == sizeof(float))
641 dp = (uint8_t *)&cts->cb.fpr[0].f[1];
642#endif
506 lj_cconv_ct_tv(cts, ctr, dp, o, 0); 643 lj_cconv_ct_tv(cts, ctr, dp, o, 0);
507#ifdef CALLBACK_HANDLE_RET 644#ifdef CALLBACK_HANDLE_RET
508 CALLBACK_HANDLE_RET 645 CALLBACK_HANDLE_RET
@@ -516,6 +653,12 @@ static void callback_conv_result(CTState *cts, lua_State *L, TValue *o)
516 *(int32_t *)dp = ctr->size == 1 ? (int32_t)*(int8_t *)dp : 653 *(int32_t *)dp = ctr->size == 1 ? (int32_t)*(int8_t *)dp :
517 (int32_t)*(int16_t *)dp; 654 (int32_t)*(int16_t *)dp;
518 } 655 }
656#if LJ_TARGET_MIPS64 || (LJ_TARGET_ARM64 && LJ_BE)
657 /* Always sign-extend results to 64 bits. Even a soft-fp 'float'. */
658 if (ctr->size <= 4 &&
659 (LJ_ABI_SOFTFP || ctype_isinteger_or_bool(ctr->info)))
660 *(int64_t *)dp = (int64_t)*(int32_t *)dp;
661#endif
519#if LJ_TARGET_X86 662#if LJ_TARGET_X86
520 if (ctype_isfp(ctr->info)) 663 if (ctype_isfp(ctr->info))
521 cts->cb.gpr[2] = ctr->size == sizeof(float) ? 1 : 2; 664 cts->cb.gpr[2] = ctr->size == sizeof(float) ? 1 : 2;
@@ -529,7 +672,7 @@ lua_State * LJ_FASTCALL lj_ccallback_enter(CTState *cts, void *cf)
529 lua_State *L = cts->L; 672 lua_State *L = cts->L;
530 global_State *g = cts->g; 673 global_State *g = cts->g;
531 lua_assert(L != NULL); 674 lua_assert(L != NULL);
532 if (gcref(g->jit_L)) { 675 if (tvref(g->jit_base)) {
533 setstrV(L, L->top++, lj_err_str(L, LJ_ERR_FFI_BADCBACK)); 676 setstrV(L, L->top++, lj_err_str(L, LJ_ERR_FFI_BADCBACK));
534 if (g->panic) g->panic(L); 677 if (g->panic) g->panic(L);
535 exit(EXIT_FAILURE); 678 exit(EXIT_FAILURE);
@@ -562,9 +705,9 @@ void LJ_FASTCALL lj_ccallback_leave(CTState *cts, TValue *o)
562 } 705 }
563 callback_conv_result(cts, L, o); 706 callback_conv_result(cts, L, o);
564 /* Finally drop C frame and continuation frame. */ 707 /* Finally drop C frame and continuation frame. */
565 L->cframe = cframe_prev(L->cframe); 708 L->top -= 2+2*LJ_FR2;
566 L->top -= 2;
567 L->base = obase; 709 L->base = obase;
710 L->cframe = cframe_prev(L->cframe);
568 cts->cb.slot = 0; /* Blacklist C function that called the callback. */ 711 cts->cb.slot = 0; /* Blacklist C function that called the callback. */
569} 712}
570 713