lj_ccallback.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. /*
  2. ** FFI C callback handling.
  3. ** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
  4. */
  5. #include "lj_obj.h"
  6. #if LJ_HASFFI
  7. #include "lj_gc.h"
  8. #include "lj_err.h"
  9. #include "lj_tab.h"
  10. #include "lj_state.h"
  11. #include "lj_frame.h"
  12. #include "lj_ctype.h"
  13. #include "lj_cconv.h"
  14. #include "lj_ccall.h"
  15. #include "lj_ccallback.h"
  16. #include "lj_target.h"
  17. #include "lj_mcode.h"
  18. #include "lj_trace.h"
  19. #include "lj_vm.h"
  20. /* -- Target-specific handling of callback slots -------------------------- */
  21. #define CALLBACK_MCODE_SIZE (LJ_PAGESIZE * LJ_NUM_CBPAGE)
  22. #if LJ_OS_NOJIT
  23. /* Disabled callback support. */
  24. #define CALLBACK_SLOT2OFS(slot) (0*(slot))
  25. #define CALLBACK_OFS2SLOT(ofs) (0*(ofs))
  26. #define CALLBACK_MAX_SLOT 0
  27. #elif LJ_TARGET_X86ORX64
  28. #define CALLBACK_MCODE_HEAD (LJ_64 ? 8 : 0)
  29. #define CALLBACK_MCODE_GROUP (-2+1+2+5+(LJ_64 ? 6 : 5))
  30. #define CALLBACK_SLOT2OFS(slot) \
  31. (CALLBACK_MCODE_HEAD + CALLBACK_MCODE_GROUP*((slot)/32) + 4*(slot))
  32. static MSize CALLBACK_OFS2SLOT(MSize ofs)
  33. {
  34. MSize group;
  35. ofs -= CALLBACK_MCODE_HEAD;
  36. group = ofs / (32*4 + CALLBACK_MCODE_GROUP);
  37. return (ofs % (32*4 + CALLBACK_MCODE_GROUP))/4 + group*32;
  38. }
  39. #define CALLBACK_MAX_SLOT \
  40. (((CALLBACK_MCODE_SIZE-CALLBACK_MCODE_HEAD)/(CALLBACK_MCODE_GROUP+4*32))*32)
  41. #elif LJ_TARGET_ARM
  42. #define CALLBACK_MCODE_HEAD 32
  43. #define CALLBACK_SLOT2OFS(slot) (CALLBACK_MCODE_HEAD + 8*(slot))
  44. #define CALLBACK_OFS2SLOT(ofs) (((ofs)-CALLBACK_MCODE_HEAD)/8)
  45. #define CALLBACK_MAX_SLOT (CALLBACK_OFS2SLOT(CALLBACK_MCODE_SIZE))
  46. #elif LJ_TARGET_PPC
  47. #define CALLBACK_MCODE_HEAD 24
  48. #define CALLBACK_SLOT2OFS(slot) (CALLBACK_MCODE_HEAD + 8*(slot))
  49. #define CALLBACK_OFS2SLOT(ofs) (((ofs)-CALLBACK_MCODE_HEAD)/8)
  50. #define CALLBACK_MAX_SLOT (CALLBACK_OFS2SLOT(CALLBACK_MCODE_SIZE))
  51. #elif LJ_TARGET_MIPS
  52. #define CALLBACK_MCODE_HEAD 24
  53. #define CALLBACK_SLOT2OFS(slot) (CALLBACK_MCODE_HEAD + 8*(slot))
  54. #define CALLBACK_OFS2SLOT(ofs) (((ofs)-CALLBACK_MCODE_HEAD)/8)
  55. #define CALLBACK_MAX_SLOT (CALLBACK_OFS2SLOT(CALLBACK_MCODE_SIZE))
  56. #else
  57. /* Missing support for this architecture. */
  58. #define CALLBACK_SLOT2OFS(slot) (0*(slot))
  59. #define CALLBACK_OFS2SLOT(ofs) (0*(ofs))
  60. #define CALLBACK_MAX_SLOT 0
  61. #endif
  62. /* Convert callback slot number to callback function pointer. */
  63. static void *callback_slot2ptr(CTState *cts, MSize slot)
  64. {
  65. return (uint8_t *)cts->cb.mcode + CALLBACK_SLOT2OFS(slot);
  66. }
  67. /* Convert callback function pointer to slot number. */
  68. MSize lj_ccallback_ptr2slot(CTState *cts, void *p)
  69. {
  70. uintptr_t ofs = (uintptr_t)((uint8_t *)p -(uint8_t *)cts->cb.mcode);
  71. if (ofs < CALLBACK_MCODE_SIZE) {
  72. MSize slot = CALLBACK_OFS2SLOT((MSize)ofs);
  73. if (CALLBACK_SLOT2OFS(slot) == (MSize)ofs)
  74. return slot;
  75. }
  76. return ~0u; /* Not a known callback function pointer. */
  77. }
  78. /* Initialize machine code for callback function pointers. */
  79. #if LJ_OS_NOJIT
  80. /* Disabled callback support. */
  81. #define callback_mcode_init(g, p) UNUSED(p)
  82. #elif LJ_TARGET_X86ORX64
  83. static void callback_mcode_init(global_State *g, uint8_t *page)
  84. {
  85. uint8_t *p = page;
  86. uint8_t *target = (uint8_t *)(void *)lj_vm_ffi_callback;
  87. MSize slot;
  88. #if LJ_64
  89. *(void **)p = target; p += 8;
  90. #endif
  91. for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
  92. /* mov al, slot; jmp group */
  93. *p++ = XI_MOVrib | RID_EAX; *p++ = (uint8_t)slot;
  94. if ((slot & 31) == 31 || slot == CALLBACK_MAX_SLOT-1) {
  95. /* push ebp/rbp; mov ah, slot>>8; mov ebp, &g. */
  96. *p++ = XI_PUSH + RID_EBP;
  97. *p++ = XI_MOVrib | (RID_EAX+4); *p++ = (uint8_t)(slot >> 8);
  98. *p++ = XI_MOVri | RID_EBP;
  99. *(int32_t *)p = i32ptr(g); p += 4;
  100. #if LJ_64
  101. /* jmp [rip-pageofs] where lj_vm_ffi_callback is stored. */
  102. *p++ = XI_GROUP5; *p++ = XM_OFS0 + (XOg_JMP<<3) + RID_EBP;
  103. *(int32_t *)p = (int32_t)(page-(p+4)); p += 4;
  104. #else
  105. /* jmp lj_vm_ffi_callback. */
  106. *p++ = XI_JMP; *(int32_t *)p = target-(p+4); p += 4;
  107. #endif
  108. } else {
  109. *p++ = XI_JMPs; *p++ = (uint8_t)((2+2)*(31-(slot&31)) - 2);
  110. }
  111. }
  112. lua_assert(p - page <= CALLBACK_MCODE_SIZE);
  113. }
  114. #elif LJ_TARGET_ARM
  115. static void callback_mcode_init(global_State *g, uint32_t *page)
  116. {
  117. uint32_t *p = page;
  118. void *target = (void *)lj_vm_ffi_callback;
  119. MSize slot;
  120. /* This must match with the saveregs macro in buildvm_arm.dasc. */
  121. *p++ = ARMI_SUB|ARMF_D(RID_R12)|ARMF_N(RID_R12)|ARMF_M(RID_PC);
  122. *p++ = ARMI_PUSH|ARMF_N(RID_SP)|RSET_RANGE(RID_R4,RID_R11+1)|RID2RSET(RID_LR);
  123. *p++ = ARMI_SUB|ARMI_K12|ARMF_D(RID_R12)|ARMF_N(RID_R12)|CALLBACK_MCODE_HEAD;
  124. *p++ = ARMI_STR|ARMI_LS_P|ARMI_LS_W|ARMF_D(RID_R12)|ARMF_N(RID_SP)|(CFRAME_SIZE-4*9);
  125. *p++ = ARMI_LDR|ARMI_LS_P|ARMI_LS_U|ARMF_D(RID_R12)|ARMF_N(RID_PC);
  126. *p++ = ARMI_LDR|ARMI_LS_P|ARMI_LS_U|ARMF_D(RID_PC)|ARMF_N(RID_PC);
  127. *p++ = u32ptr(g);
  128. *p++ = u32ptr(target);
  129. for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
  130. *p++ = ARMI_MOV|ARMF_D(RID_R12)|ARMF_M(RID_PC);
  131. *p = ARMI_B | ((page-p-2) & 0x00ffffffu);
  132. p++;
  133. }
  134. lua_assert(p - page <= CALLBACK_MCODE_SIZE);
  135. }
  136. #elif LJ_TARGET_PPC
  137. static void callback_mcode_init(global_State *g, uint32_t *page)
  138. {
  139. uint32_t *p = page;
  140. void *target = (void *)lj_vm_ffi_callback;
  141. MSize slot;
  142. *p++ = PPCI_LIS | PPCF_T(RID_TMP) | (u32ptr(target) >> 16);
  143. *p++ = PPCI_LIS | PPCF_T(RID_R12) | (u32ptr(g) >> 16);
  144. *p++ = PPCI_ORI | PPCF_A(RID_TMP)|PPCF_T(RID_TMP) | (u32ptr(target) & 0xffff);
  145. *p++ = PPCI_ORI | PPCF_A(RID_R12)|PPCF_T(RID_R12) | (u32ptr(g) & 0xffff);
  146. *p++ = PPCI_MTCTR | PPCF_T(RID_TMP);
  147. *p++ = PPCI_BCTR;
  148. for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
  149. *p++ = PPCI_LI | PPCF_T(RID_R11) | slot;
  150. *p = PPCI_B | (((page-p) & 0x00ffffffu) << 2);
  151. p++;
  152. }
  153. lua_assert(p - page <= CALLBACK_MCODE_SIZE);
  154. }
  155. #elif LJ_TARGET_MIPS
  156. static void callback_mcode_init(global_State *g, uint32_t *page)
  157. {
  158. uint32_t *p = page;
  159. void *target = (void *)lj_vm_ffi_callback;
  160. MSize slot;
  161. *p++ = MIPSI_SW | MIPSF_T(RID_R1)|MIPSF_S(RID_SP) | 0;
  162. *p++ = MIPSI_LUI | MIPSF_T(RID_R3) | (u32ptr(target) >> 16);
  163. *p++ = MIPSI_LUI | MIPSF_T(RID_R2) | (u32ptr(g) >> 16);
  164. *p++ = MIPSI_ORI | MIPSF_T(RID_R3)|MIPSF_S(RID_R3) |(u32ptr(target)&0xffff);
  165. *p++ = MIPSI_JR | MIPSF_S(RID_R3);
  166. *p++ = MIPSI_ORI | MIPSF_T(RID_R2)|MIPSF_S(RID_R2) | (u32ptr(g)&0xffff);
  167. for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
  168. *p = MIPSI_B | ((page-p-1) & 0x0000ffffu);
  169. p++;
  170. *p++ = MIPSI_LI | MIPSF_T(RID_R1) | slot;
  171. }
  172. lua_assert(p - page <= CALLBACK_MCODE_SIZE);
  173. }
  174. #else
  175. /* Missing support for this architecture. */
  176. #define callback_mcode_init(g, p) UNUSED(p)
  177. #endif
  178. /* -- Machine code management --------------------------------------------- */
  179. #if LJ_TARGET_WINDOWS
  180. #define WIN32_LEAN_AND_MEAN
  181. #include <windows.h>
  182. #elif LJ_TARGET_POSIX
  183. #include <sys/mman.h>
  184. #ifndef MAP_ANONYMOUS
  185. #define MAP_ANONYMOUS MAP_ANON
  186. #endif
  187. #endif
  188. /* Allocate and initialize area for callback function pointers. */
  189. static void callback_mcode_new(CTState *cts)
  190. {
  191. size_t sz = (size_t)CALLBACK_MCODE_SIZE;
  192. void *p;
  193. if (CALLBACK_MAX_SLOT == 0)
  194. lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV);
  195. #if LJ_TARGET_WINDOWS
  196. p = VirtualAlloc(NULL, sz, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
  197. if (!p)
  198. lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV);
  199. #elif LJ_TARGET_POSIX
  200. p = mmap(NULL, sz, (PROT_READ|PROT_WRITE), MAP_PRIVATE|MAP_ANONYMOUS,
  201. -1, 0);
  202. if (p == MAP_FAILED)
  203. lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV);
  204. #else
  205. /* Fallback allocator. Fails if memory is not executable by default. */
  206. p = lj_mem_new(cts->L, sz);
  207. #endif
  208. cts->cb.mcode = p;
  209. callback_mcode_init(cts->g, p);
  210. lj_mcode_sync(p, (char *)p + sz);
  211. #if LJ_TARGET_WINDOWS
  212. {
  213. DWORD oprot;
  214. VirtualProtect(p, sz, PAGE_EXECUTE_READ, &oprot);
  215. }
  216. #elif LJ_TARGET_POSIX
  217. mprotect(p, sz, (PROT_READ|PROT_EXEC));
  218. #endif
  219. }
  220. /* Free area for callback function pointers. */
  221. void lj_ccallback_mcode_free(CTState *cts)
  222. {
  223. size_t sz = (size_t)CALLBACK_MCODE_SIZE;
  224. void *p = cts->cb.mcode;
  225. if (p == NULL) return;
  226. #if LJ_TARGET_WINDOWS
  227. VirtualFree(p, 0, MEM_RELEASE);
  228. UNUSED(sz);
  229. #elif LJ_TARGET_POSIX
  230. munmap(p, sz);
  231. #else
  232. lj_mem_free(cts->g, p, sz);
  233. #endif
  234. }
  235. /* -- C callback entry ---------------------------------------------------- */
  236. /* Target-specific handling of register arguments. Similar to lj_ccall.c. */
  237. #if LJ_TARGET_X86
  238. #define CALLBACK_HANDLE_REGARG \
  239. if (!isfp) { /* Only non-FP values may be passed in registers. */ \
  240. if (n > 1) { /* Anything > 32 bit is passed on the stack. */ \
  241. if (!LJ_ABI_WIN) ngpr = maxgpr; /* Prevent reordering. */ \
  242. } else if (ngpr + 1 <= maxgpr) { \
  243. sp = &cts->cb.gpr[ngpr]; \
  244. ngpr += n; \
  245. goto done; \
  246. } \
  247. }
  248. #elif LJ_TARGET_X64 && LJ_ABI_WIN
  249. /* Windows/x64 argument registers are strictly positional (use ngpr). */
  250. #define CALLBACK_HANDLE_REGARG \
  251. if (isfp) { \
  252. if (ngpr < maxgpr) { sp = &cts->cb.fpr[ngpr++]; UNUSED(nfpr); goto done; } \
  253. } else { \
  254. if (ngpr < maxgpr) { sp = &cts->cb.gpr[ngpr++]; goto done; } \
  255. }
  256. #elif LJ_TARGET_X64
  257. #define CALLBACK_HANDLE_REGARG \
  258. if (isfp) { \
  259. if (nfpr + n <= CCALL_NARG_FPR) { \
  260. sp = &cts->cb.fpr[nfpr]; \
  261. nfpr += n; \
  262. goto done; \
  263. } \
  264. } else { \
  265. if (ngpr + n <= maxgpr) { \
  266. sp = &cts->cb.gpr[ngpr]; \
  267. ngpr += n; \
  268. goto done; \
  269. } \
  270. }
  271. #elif LJ_TARGET_ARM
  272. #if LJ_ABI_SOFTFP
  273. #define CALLBACK_HANDLE_REGARG_FP1 UNUSED(isfp);
  274. #define CALLBACK_HANDLE_REGARG_FP2
  275. #else
  276. #define CALLBACK_HANDLE_REGARG_FP1 \
  277. if (isfp) { \
  278. if (n == 1) { \
  279. if (fprodd) { \
  280. sp = &cts->cb.fpr[fprodd-1]; \
  281. fprodd = 0; \
  282. goto done; \
  283. } else if (nfpr + 1 <= CCALL_NARG_FPR) { \
  284. sp = &cts->cb.fpr[nfpr++]; \
  285. fprodd = nfpr; \
  286. goto done; \
  287. } \
  288. } else { \
  289. if (nfpr + 1 <= CCALL_NARG_FPR) { \
  290. sp = &cts->cb.fpr[nfpr++]; \
  291. goto done; \
  292. } \
  293. } \
  294. fprodd = 0; /* No reordering after the first FP value is on stack. */ \
  295. } else {
  296. #define CALLBACK_HANDLE_REGARG_FP2 }
  297. #endif
  298. #define CALLBACK_HANDLE_REGARG \
  299. CALLBACK_HANDLE_REGARG_FP1 \
  300. if (n > 1) ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
  301. if (ngpr + n <= maxgpr) { \
  302. sp = &cts->cb.gpr[ngpr]; \
  303. ngpr += n; \
  304. goto done; \
  305. } CALLBACK_HANDLE_REGARG_FP2
  306. #elif LJ_TARGET_PPC
  307. #define CALLBACK_HANDLE_REGARG \
  308. if (isfp) { \
  309. if (nfpr + 1 <= CCALL_NARG_FPR) { \
  310. sp = &cts->cb.fpr[nfpr++]; \
  311. cta = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */ \
  312. goto done; \
  313. } \
  314. } else { /* Try to pass argument in GPRs. */ \
  315. if (n > 1) { \
  316. lua_assert(ctype_isinteger(cta->info) && n == 2); /* int64_t. */ \
  317. ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
  318. } \
  319. if (ngpr + n <= maxgpr) { \
  320. sp = &cts->cb.gpr[ngpr]; \
  321. ngpr += n; \
  322. goto done; \
  323. } \
  324. }
  325. #define CALLBACK_HANDLE_RET \
  326. if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
  327. *(double *)dp = *(float *)dp; /* FPRs always hold doubles. */
  328. #elif LJ_TARGET_MIPS
  329. #define CALLBACK_HANDLE_REGARG \
  330. if (isfp && nfpr < CCALL_NARG_FPR) { /* Try to pass argument in FPRs. */ \
  331. sp = (void *)((uint8_t *)&cts->cb.fpr[nfpr] + ((LJ_BE && n==1) ? 4 : 0)); \
  332. nfpr++; ngpr += n; \
  333. goto done; \
  334. } else { /* Try to pass argument in GPRs. */ \
  335. nfpr = CCALL_NARG_FPR; \
  336. if (n > 1) ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
  337. if (ngpr + n <= maxgpr) { \
  338. sp = &cts->cb.gpr[ngpr]; \
  339. ngpr += n; \
  340. goto done; \
  341. } \
  342. }
  343. #define CALLBACK_HANDLE_RET \
  344. if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
  345. ((float *)dp)[1] = *(float *)dp;
  346. #else
  347. #error "Missing calling convention definitions for this architecture"
  348. #endif
  349. /* Convert and push callback arguments to Lua stack. */
  350. static void callback_conv_args(CTState *cts, lua_State *L)
  351. {
  352. TValue *o = L->top;
  353. intptr_t *stack = cts->cb.stack;
  354. MSize slot = cts->cb.slot;
  355. CTypeID id = 0, rid, fid;
  356. int gcsteps = 0;
  357. CType *ct;
  358. GCfunc *fn;
  359. MSize ngpr = 0, nsp = 0, maxgpr = CCALL_NARG_GPR;
  360. #if CCALL_NARG_FPR
  361. MSize nfpr = 0;
  362. #if LJ_TARGET_ARM
  363. MSize fprodd = 0;
  364. #endif
  365. #endif
  366. if (slot < cts->cb.sizeid && (id = cts->cb.cbid[slot]) != 0) {
  367. ct = ctype_get(cts, id);
  368. rid = ctype_cid(ct->info);
  369. fn = funcV(lj_tab_getint(cts->miscmap, (int32_t)slot));
  370. } else { /* Must set up frame first, before throwing the error. */
  371. ct = NULL;
  372. rid = 0;
  373. fn = (GCfunc *)L;
  374. }
  375. o->u32.lo = LJ_CONT_FFI_CALLBACK; /* Continuation returns from callback. */
  376. o->u32.hi = rid; /* Return type. x86: +(spadj<<16). */
  377. o++;
  378. setframe_gc(o, obj2gco(fn));
  379. setframe_ftsz(o, (int)((char *)(o+1) - (char *)L->base) + FRAME_CONT);
  380. L->top = L->base = ++o;
  381. if (!ct)
  382. lj_err_caller(cts->L, LJ_ERR_FFI_BADCBACK);
  383. if (isluafunc(fn))
  384. setcframe_pc(L->cframe, proto_bc(funcproto(fn))+1);
  385. lj_state_checkstack(L, LUA_MINSTACK); /* May throw. */
  386. o = L->base; /* Might have been reallocated. */
  387. #if LJ_TARGET_X86
  388. /* x86 has several different calling conventions. */
  389. switch (ctype_cconv(ct->info)) {
  390. case CTCC_FASTCALL: maxgpr = 2; break;
  391. case CTCC_THISCALL: maxgpr = 1; break;
  392. default: maxgpr = 0; break;
  393. }
  394. #endif
  395. fid = ct->sib;
  396. while (fid) {
  397. CType *ctf = ctype_get(cts, fid);
  398. if (!ctype_isattrib(ctf->info)) {
  399. CType *cta;
  400. void *sp;
  401. CTSize sz;
  402. int isfp;
  403. MSize n;
  404. lua_assert(ctype_isfield(ctf->info));
  405. cta = ctype_rawchild(cts, ctf);
  406. isfp = ctype_isfp(cta->info);
  407. sz = (cta->size + CTSIZE_PTR-1) & ~(CTSIZE_PTR-1);
  408. n = sz / CTSIZE_PTR; /* Number of GPRs or stack slots needed. */
  409. CALLBACK_HANDLE_REGARG /* Handle register arguments. */
  410. /* Otherwise pass argument on stack. */
  411. if (CCALL_ALIGN_STACKARG && LJ_32 && sz == 8)
  412. nsp = (nsp + 1) & ~1u; /* Align 64 bit argument on stack. */
  413. sp = &stack[nsp];
  414. nsp += n;
  415. done:
  416. if (LJ_BE && cta->size < CTSIZE_PTR)
  417. sp = (void *)((uint8_t *)sp + CTSIZE_PTR-cta->size);
  418. gcsteps += lj_cconv_tv_ct(cts, cta, 0, o++, sp);
  419. }
  420. fid = ctf->sib;
  421. }
  422. L->top = o;
  423. #if LJ_TARGET_X86
  424. /* Store stack adjustment for returns from non-cdecl callbacks. */
  425. if (ctype_cconv(ct->info) != CTCC_CDECL)
  426. (L->base-2)->u32.hi |= (nsp << (16+2));
  427. #endif
  428. while (gcsteps-- > 0)
  429. lj_gc_check(L);
  430. }
  431. /* Convert Lua object to callback result. */
  432. static void callback_conv_result(CTState *cts, lua_State *L, TValue *o)
  433. {
  434. CType *ctr = ctype_raw(cts, (uint16_t)(L->base-2)->u32.hi);
  435. #if LJ_TARGET_X86
  436. cts->cb.gpr[2] = 0;
  437. #endif
  438. if (!ctype_isvoid(ctr->info)) {
  439. uint8_t *dp = (uint8_t *)&cts->cb.gpr[0];
  440. #if CCALL_NUM_FPR
  441. if (ctype_isfp(ctr->info))
  442. dp = (uint8_t *)&cts->cb.fpr[0];
  443. #endif
  444. lj_cconv_ct_tv(cts, ctr, dp, o, 0);
  445. #ifdef CALLBACK_HANDLE_RET
  446. CALLBACK_HANDLE_RET
  447. #endif
  448. /* Extend returned integers to (at least) 32 bits. */
  449. if (ctype_isinteger_or_bool(ctr->info) && ctr->size < 4) {
  450. if (ctr->info & CTF_UNSIGNED)
  451. *(uint32_t *)dp = ctr->size == 1 ? (uint32_t)*(uint8_t *)dp :
  452. (uint32_t)*(uint16_t *)dp;
  453. else
  454. *(int32_t *)dp = ctr->size == 1 ? (int32_t)*(int8_t *)dp :
  455. (int32_t)*(int16_t *)dp;
  456. }
  457. #if LJ_TARGET_X86
  458. if (ctype_isfp(ctr->info))
  459. cts->cb.gpr[2] = ctr->size == sizeof(float) ? 1 : 2;
  460. #endif
  461. }
  462. }
  463. /* Enter callback. */
  464. lua_State * LJ_FASTCALL lj_ccallback_enter(CTState *cts, void *cf)
  465. {
  466. lua_State *L = cts->L;
  467. global_State *g = cts->g;
  468. lua_assert(L != NULL);
  469. if (gcref(g->jit_L)) {
  470. setstrV(L, L->top++, lj_err_str(L, LJ_ERR_FFI_BADCBACK));
  471. if (g->panic) g->panic(L);
  472. exit(EXIT_FAILURE);
  473. }
  474. lj_trace_abort(g); /* Never record across callback. */
  475. /* Setup C frame. */
  476. cframe_prev(cf) = L->cframe;
  477. setcframe_L(cf, L);
  478. cframe_errfunc(cf) = -1;
  479. cframe_nres(cf) = 0;
  480. L->cframe = cf;
  481. callback_conv_args(cts, L);
  482. return L; /* Now call the function on this stack. */
  483. }
  484. /* Leave callback. */
  485. void LJ_FASTCALL lj_ccallback_leave(CTState *cts, TValue *o)
  486. {
  487. lua_State *L = cts->L;
  488. GCfunc *fn;
  489. TValue *obase = L->base;
  490. L->base = L->top; /* Keep continuation frame for throwing errors. */
  491. if (o >= L->base) {
  492. /* PC of RET* is lost. Point to last line for result conv. errors. */
  493. fn = curr_func(L);
  494. if (isluafunc(fn)) {
  495. GCproto *pt = funcproto(fn);
  496. setcframe_pc(L->cframe, proto_bc(pt)+pt->sizebc+1);
  497. }
  498. }
  499. callback_conv_result(cts, L, o);
  500. /* Finally drop C frame and continuation frame. */
  501. L->cframe = cframe_prev(L->cframe);
  502. L->top -= 2;
  503. L->base = obase;
  504. cts->cb.slot = 0; /* Blacklist C function that called the callback. */
  505. }
  506. /* -- C callback management ----------------------------------------------- */
  507. /* Get an unused slot in the callback slot table. */
  508. static MSize callback_slot_new(CTState *cts, CType *ct)
  509. {
  510. CTypeID id = ctype_typeid(cts, ct);
  511. CTypeID1 *cbid = cts->cb.cbid;
  512. MSize top;
  513. for (top = cts->cb.topid; top < cts->cb.sizeid; top++)
  514. if (LJ_LIKELY(cbid[top] == 0))
  515. goto found;
  516. #if CALLBACK_MAX_SLOT
  517. if (top >= CALLBACK_MAX_SLOT)
  518. #endif
  519. lj_err_caller(cts->L, LJ_ERR_FFI_CBACKOV);
  520. if (!cts->cb.mcode)
  521. callback_mcode_new(cts);
  522. lj_mem_growvec(cts->L, cbid, cts->cb.sizeid, CALLBACK_MAX_SLOT, CTypeID1);
  523. cts->cb.cbid = cbid;
  524. memset(cbid+top, 0, (cts->cb.sizeid-top)*sizeof(CTypeID1));
  525. found:
  526. cbid[top] = id;
  527. cts->cb.topid = top+1;
  528. return top;
  529. }
  530. /* Check for function pointer and supported argument/result types. */
  531. static CType *callback_checkfunc(CTState *cts, CType *ct)
  532. {
  533. int narg = 0;
  534. if (!ctype_isptr(ct->info) || (LJ_64 && ct->size != CTSIZE_PTR))
  535. return NULL;
  536. ct = ctype_rawchild(cts, ct);
  537. if (ctype_isfunc(ct->info)) {
  538. CType *ctr = ctype_rawchild(cts, ct);
  539. CTypeID fid = ct->sib;
  540. if (!(ctype_isvoid(ctr->info) || ctype_isenum(ctr->info) ||
  541. ctype_isptr(ctr->info) || (ctype_isnum(ctr->info) && ctr->size <= 8)))
  542. return NULL;
  543. if ((ct->info & CTF_VARARG))
  544. return NULL;
  545. while (fid) {
  546. CType *ctf = ctype_get(cts, fid);
  547. if (!ctype_isattrib(ctf->info)) {
  548. CType *cta;
  549. lua_assert(ctype_isfield(ctf->info));
  550. cta = ctype_rawchild(cts, ctf);
  551. if (!(ctype_isenum(cta->info) || ctype_isptr(cta->info) ||
  552. (ctype_isnum(cta->info) && cta->size <= 8)) ||
  553. ++narg >= LUA_MINSTACK-3)
  554. return NULL;
  555. }
  556. fid = ctf->sib;
  557. }
  558. return ct;
  559. }
  560. return NULL;
  561. }
  562. /* Create a new callback and return the callback function pointer. */
  563. void *lj_ccallback_new(CTState *cts, CType *ct, GCfunc *fn)
  564. {
  565. ct = callback_checkfunc(cts, ct);
  566. if (ct) {
  567. MSize slot = callback_slot_new(cts, ct);
  568. GCtab *t = cts->miscmap;
  569. setfuncV(cts->L, lj_tab_setint(cts->L, t, (int32_t)slot), fn);
  570. lj_gc_anybarriert(cts->L, t);
  571. return callback_slot2ptr(cts, slot);
  572. }
  573. return NULL; /* Bad conversion. */
  574. }
  575. #endif