src/lj_ccall.c - luajit-2.0-src

Functions defined

Macros defined

Source code

  1. /*
  2. ** FFI C call handling.
  3. ** Copyright (C) 2005-2015 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_ctype.h"
  11. #include "lj_cconv.h"
  12. #include "lj_cdata.h"
  13. #include "lj_ccall.h"
  14. #include "lj_trace.h"

  15. /* Target-specific handling of register arguments. */
  16. #if LJ_TARGET_X86
  17. /* -- x86 calling conventions --------------------------------------------- */

  18. #if LJ_ABI_WIN

  19. #define CCALL_HANDLE_STRUCTRET \
  20.   /* Return structs bigger than 8 by reference (on stack only). */ \
  21.   cc->retref = (sz > 8); \
  22.   if (cc->retref) cc->stack[nsp++] = (GPRArg)dp;

  23. #define CCALL_HANDLE_COMPLEXRET CCALL_HANDLE_STRUCTRET

  24. #else

  25. #if LJ_TARGET_OSX

  26. #define CCALL_HANDLE_STRUCTRET \
  27.   /* Return structs of size 1, 2, 4 or 8 in registers. */ \
  28.   cc->retref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); \
  29.   if (cc->retref) { \
  30.     if (ngpr < maxgpr) \
  31.       cc->gpr[ngpr++] = (GPRArg)dp; \
  32.     else \
  33.       cc->stack[nsp++] = (GPRArg)dp; \
  34.   } else/* Struct with single FP field ends up in FPR. */ \
  35.     cc->resx87 = ccall_classify_struct(cts, ctr); \
  36.   }

  37. #define CCALL_HANDLE_STRUCTRET2 \
  38.   if (cc->resx87) sp = (uint8_t *)&cc->fpr[0]; \
  39.   memcpy(dp, sp, ctr->size);

  40. #else

  41. #define CCALL_HANDLE_STRUCTRET \
  42.   cc->retref = 1/* Return all structs by reference (in reg or on stack). */ \
  43.   if (ngpr < maxgpr) \
  44.     cc->gpr[ngpr++] = (GPRArg)dp; \
  45.   else \
  46.     cc->stack[nsp++] = (GPRArg)dp;

  47. #endif

  48. #define CCALL_HANDLE_COMPLEXRET \
  49.   /* Return complex float in GPRs and complex double by reference. */ \
  50.   cc->retref = (sz > 8); \
  51.   if (cc->retref) { \
  52.     if (ngpr < maxgpr) \
  53.       cc->gpr[ngpr++] = (GPRArg)dp; \
  54.     else \
  55.       cc->stack[nsp++] = (GPRArg)dp; \
  56.   }

  57. #endif

  58. #define CCALL_HANDLE_COMPLEXRET2 \
  59.   if (!cc->retref) \
  60.     *(int64_t *)dp = *(int64_t *)sp;  /* Copy complex float from GPRs. */

  61. #define CCALL_HANDLE_STRUCTARG \
  62.   ngpr = maxgpr;  /* Pass all structs by value on the stack. */

  63. #define CCALL_HANDLE_COMPLEXARG \
  64.   isfp = 1/* Pass complex by value on stack. */

  65. #define CCALL_HANDLE_REGARG \
  66.   if (!isfp) {  /* Only non-FP values may be passed in registers. */ \
  67.     if (n > 1) {  /* Anything > 32 bit is passed on the stack. */ \
  68.       if (!LJ_ABI_WIN) ngpr = maxgpr;  /* Prevent reordering. */ \
  69.     } else if (ngpr + 1 <= maxgpr) { \
  70.       dp = &cc->gpr[ngpr]; \
  71.       ngpr += n; \
  72.       goto done; \
  73.     } \
  74.   }

  75. #elif LJ_TARGET_X64 && LJ_ABI_WIN
  76. /* -- Windows/x64 calling conventions ------------------------------------- */

  77. #define CCALL_HANDLE_STRUCTRET \
  78.   /* Return structs of size 1, 2, 4 or 8 in a GPR. */ \
  79.   cc->retref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); \
  80.   if (cc->retref) cc->gpr[ngpr++] = (GPRArg)dp;

  81. #define CCALL_HANDLE_COMPLEXRET CCALL_HANDLE_STRUCTRET

  82. #define CCALL_HANDLE_COMPLEXRET2 \
  83.   if (!cc->retref) \
  84.     *(int64_t *)dp = *(int64_t *)sp;  /* Copy complex float from GPRs. */

  85. #define CCALL_HANDLE_STRUCTARG \
  86.   /* Pass structs of size 1, 2, 4 or 8 in a GPR by value. */ \
  87.   if (!(sz == 1 || sz == 2 || sz == 4 || sz == 8)) { \
  88.     rp = cdataptr(lj_cdata_new(cts, did, sz)); \
  89.     sz = CTSIZE_PTR/* Pass all other structs by reference. */ \
  90.   }

  91. #define CCALL_HANDLE_COMPLEXARG \
  92.   /* Pass complex float in a GPR and complex double by reference. */ \
  93.   if (sz != 2*sizeof(float)) { \
  94.     rp = cdataptr(lj_cdata_new(cts, did, sz)); \
  95.     sz = CTSIZE_PTR; \
  96.   }

  97. /* Windows/x64 argument registers are strictly positional (use ngpr). */
  98. #define CCALL_HANDLE_REGARG \
  99.   if (isfp) { \
  100.     if (ngpr < maxgpr) { dp = &cc->fpr[ngpr++]; nfpr = ngpr; goto done; } \
  101.   } else { \
  102.     if (ngpr < maxgpr) { dp = &cc->gpr[ngpr++]; goto done; } \
  103.   }

  104. #elif LJ_TARGET_X64
  105. /* -- POSIX/x64 calling conventions --------------------------------------- */

  106. #define CCALL_HANDLE_STRUCTRET \
  107.   int rcl[2]; rcl[0] = rcl[1] = 0; \
  108.   if (ccall_classify_struct(cts, ctr, rcl, 0)) { \
  109.     cc->retref = 1/* Return struct by reference. */ \
  110.     cc->gpr[ngpr++] = (GPRArg)dp; \
  111.   } else { \
  112.     cc->retref = 0/* Return small structs in registers. */ \
  113.   }

  114. #define CCALL_HANDLE_STRUCTRET2 \
  115.   int rcl[2]; rcl[0] = rcl[1] = 0; \
  116.   ccall_classify_struct(cts, ctr, rcl, 0); \
  117.   ccall_struct_ret(cc, rcl, dp, ctr->size);

  118. #define CCALL_HANDLE_COMPLEXRET \
  119.   /* Complex values are returned in one or two FPRs. */ \
  120.   cc->retref = 0;

  121. #define CCALL_HANDLE_COMPLEXRET2 \
  122.   if (ctr->size == 2*sizeof(float)) {  /* Copy complex float from FPR. */ \
  123.     *(int64_t *)dp = cc->fpr[0].l[0]; \
  124.   } else/* Copy non-contiguous complex double from FPRs. */ \
  125.     ((int64_t *)dp)[0] = cc->fpr[0].l[0]; \
  126.     ((int64_t *)dp)[1] = cc->fpr[1].l[0]; \
  127.   }

  128. #define CCALL_HANDLE_STRUCTARG \
  129.   int rcl[2]; rcl[0] = rcl[1] = 0; \
  130.   if (!ccall_classify_struct(cts, d, rcl, 0)) { \
  131.     cc->nsp = nsp; cc->ngpr = ngpr; cc->nfpr = nfpr; \
  132.     if (ccall_struct_arg(cc, cts, d, rcl, o, narg)) goto err_nyi; \
  133.     nsp = cc->nsp; ngpr = cc->ngpr; nfpr = cc->nfpr; \
  134.     continue; \
  135.   }  /* Pass all other structs by value on stack. */

  136. #define CCALL_HANDLE_COMPLEXARG \
  137.   isfp = 2/* Pass complex in FPRs or on stack. Needs postprocessing. */

  138. #define CCALL_HANDLE_REGARG \
  139.   if (isfp) {  /* Try to pass argument in FPRs. */ \
  140.     int n2 = ctype_isvector(d->info) ? 1 : n; \
  141.     if (nfpr + n2 <= CCALL_NARG_FPR) { \
  142.       dp = &cc->fpr[nfpr]; \
  143.       nfpr += n2; \
  144.       goto done; \
  145.     } \
  146.   } else/* Try to pass argument in GPRs. */ \
  147.     /* Note that reordering is explicitly allowed in the x64 ABI. */ \
  148.     if (n <= 2 && ngpr + n <= maxgpr) { \
  149.       dp = &cc->gpr[ngpr]; \
  150.       ngpr += n; \
  151.       goto done; \
  152.     } \
  153.   }

  154. #elif LJ_TARGET_ARM
  155. /* -- ARM calling conventions --------------------------------------------- */

  156. #if LJ_ABI_SOFTFP

  157. #define CCALL_HANDLE_STRUCTRET \
  158.   /* Return structs of size <= 4 in a GPR. */ \
  159.   cc->retref = !(sz <= 4); \
  160.   if (cc->retref) cc->gpr[ngpr++] = (GPRArg)dp;

  161. #define CCALL_HANDLE_COMPLEXRET \
  162.   cc->retref = 1/* Return all complex values by reference. */ \
  163.   cc->gpr[ngpr++] = (GPRArg)dp;

  164. #define CCALL_HANDLE_COMPLEXRET2 \
  165.   UNUSED(dp); /* Nothing to do. */

  166. #define CCALL_HANDLE_STRUCTARG \
  167.   /* Pass all structs by value in registers and/or on the stack. */

  168. #define CCALL_HANDLE_COMPLEXARG \
  169.   /* Pass complex by value in 2 or 4 GPRs. */

  170. #define CCALL_HANDLE_REGARG_FP1
  171. #define CCALL_HANDLE_REGARG_FP2

  172. #else

  173. #define CCALL_HANDLE_STRUCTRET \
  174.   cc->retref = !ccall_classify_struct(cts, ctr, ct); \
  175.   if (cc->retref) cc->gpr[ngpr++] = (GPRArg)dp;

  176. #define CCALL_HANDLE_STRUCTRET2 \
  177.   if (ccall_classify_struct(cts, ctr, ct) > 1) sp = (uint8_t *)&cc->fpr[0]; \
  178.   memcpy(dp, sp, ctr->size);

  179. #define CCALL_HANDLE_COMPLEXRET \
  180.   if (!(ct->info & CTF_VARARG)) cc->retref = 0/* Return complex in FPRs. */

  181. #define CCALL_HANDLE_COMPLEXRET2 \
  182.   if (!(ct->info & CTF_VARARG)) memcpy(dp, &cc->fpr[0], ctr->size);

  183. #define CCALL_HANDLE_STRUCTARG \
  184.   isfp = (ccall_classify_struct(cts, d, ct) > 1);
  185.   /* Pass all structs by value in registers and/or on the stack. */

  186. #define CCALL_HANDLE_COMPLEXARG \
  187.   isfp = 1/* Pass complex by value in FPRs or on stack. */

  188. #define CCALL_HANDLE_REGARG_FP1 \
  189.   if (isfp && !(ct->info & CTF_VARARG)) { \
  190.     if ((d->info & CTF_ALIGN) > CTALIGN_PTR) { \
  191.       if (nfpr + (n >> 1) <= CCALL_NARG_FPR) { \
  192.         dp = &cc->fpr[nfpr]; \
  193.         nfpr += (n >> 1); \
  194.         goto done; \
  195.       } \
  196.     } else { \
  197.       if (sz > 1 && fprodd != nfpr) fprodd = 0; \
  198.       if (fprodd) { \
  199.         if (2*nfpr+n <= 2*CCALL_NARG_FPR+1) { \
  200.           dp = (void *)&cc->fpr[fprodd-1].f[1]; \
  201.           nfpr += (n >> 1); \
  202.           if ((n & 1)) fprodd = 0; else fprodd = nfpr-1; \
  203.           goto done; \
  204.         } \
  205.       } else { \
  206.         if (2*nfpr+n <= 2*CCALL_NARG_FPR) { \
  207.           dp = (void *)&cc->fpr[nfpr]; \
  208.           nfpr += (n >> 1); \
  209.           if ((n & 1)) fprodd = ++nfpr; else fprodd = 0; \
  210.           goto done; \
  211.         } \
  212.       } \
  213.     } \
  214.     fprodd = 0/* No reordering after the first FP value is on stack. */ \
  215.   } else {

  216. #define CCALL_HANDLE_REGARG_FP2        }

  217. #endif

  218. #define CCALL_HANDLE_REGARG \
  219.   CCALL_HANDLE_REGARG_FP1 \
  220.   if ((d->info & CTF_ALIGN) > CTALIGN_PTR) { \
  221.     if (ngpr < maxgpr) \
  222.       ngpr = (ngpr + 1u) & ~1u/* Align to regpair. */ \
  223.   } \
  224.   if (ngpr < maxgpr) { \
  225.     dp = &cc->gpr[ngpr]; \
  226.     if (ngpr + n > maxgpr) { \
  227.       nsp += ngpr + n - maxgpr;  /* Assumes contiguous gpr/stack fields. */ \
  228.       if (nsp > CCALL_MAXSTACK) goto err_nyi;  /* Too many arguments. */ \
  229.       ngpr = maxgpr; \
  230.     } else { \
  231.       ngpr += n; \
  232.     } \
  233.     goto done; \
  234.   } CCALL_HANDLE_REGARG_FP2

  235. #define CCALL_HANDLE_RET \
  236.   if ((ct->info & CTF_VARARG)) sp = (uint8_t *)&cc->gpr[0];

  237. #elif LJ_TARGET_ARM64
  238. /* -- ARM64 calling conventions ------------------------------------------- */

  239. #define CCALL_HANDLE_STRUCTRET \
  240.   cc->retref = !ccall_classify_struct(cts, ctr); \
  241.   if (cc->retref) cc->retp = dp;

  242. #define CCALL_HANDLE_STRUCTRET2 \
  243.   unsigned int cl = ccall_classify_struct(cts, ctr); \
  244.   if ((cl & 4)) { /* Combine float HFA from separate registers. */ \
  245.     CTSize i = (cl >> 8) - 1; \
  246.     do { ((uint32_t *)dp)[i] = cc->fpr[i].u32; } while (i--); \
  247.   } else { \
  248.     if (cl > 1) sp = (uint8_t *)&cc->fpr[0]; \
  249.     memcpy(dp, sp, ctr->size); \
  250.   }

  251. #define CCALL_HANDLE_COMPLEXRET \
  252.   /* Complex values are returned in one or two FPRs. */ \
  253.   cc->retref = 0;

  254. #define CCALL_HANDLE_COMPLEXRET2 \
  255.   if (ctr->size == 2*sizeof(float)) {  /* Copy complex float from FPRs. */ \
  256.     ((float *)dp)[0] = cc->fpr[0].f; \
  257.     ((float *)dp)[1] = cc->fpr[1].f; \
  258.   } else/* Copy complex double from FPRs. */ \
  259.     ((double *)dp)[0] = cc->fpr[0].d; \
  260.     ((double *)dp)[1] = cc->fpr[1].d; \
  261.   }

  262. #define CCALL_HANDLE_STRUCTARG \
  263.   unsigned int cl = ccall_classify_struct(cts, d); \
  264.   if (cl == 0) {  /* Pass struct by reference. */ \
  265.     rp = cdataptr(lj_cdata_new(cts, did, sz)); \
  266.     sz = CTSIZE_PTR; \
  267.   } else if (cl > 1) {  /* Pass struct in FPRs or on stack. */ \
  268.     isfp = (cl & 4) ? 2 : 1; \
  269.   }  /* else: Pass struct in GPRs or on stack. */

  270. #define CCALL_HANDLE_COMPLEXARG \
  271.   /* Pass complex by value in separate (!) FPRs or on stack. */ \
  272.   isfp = ctr->size == 2*sizeof(float) ? 2 : 1;

  273. #define CCALL_HANDLE_REGARG \
  274.   if (LJ_TARGET_IOS && isva) { \
  275.     /* IOS: All variadic arguments are on the stack. */ \
  276.   } else if (isfp) {  /* Try to pass argument in FPRs. */ \
  277.     int n2 = ctype_isvector(d->info) ? 1 : n*isfp; \
  278.     if (nfpr + n2 <= CCALL_NARG_FPR) { \
  279.       dp = &cc->fpr[nfpr]; \
  280.       nfpr += n2; \
  281.       goto done; \
  282.     } else { \
  283.       nfpr = CCALL_NARG_FPR/* Prevent reordering. */ \
  284.       if (LJ_TARGET_IOS && d->size < 8) goto err_nyi; \
  285.     } \
  286.   } else/* Try to pass argument in GPRs. */ \
  287.     if (!LJ_TARGET_IOS && (d->info & CTF_ALIGN) > CTALIGN_PTR) \
  288.       ngpr = (ngpr + 1u) & ~1u/* Align to regpair. */ \
  289.     if (ngpr + n <= maxgpr) { \
  290.       dp = &cc->gpr[ngpr]; \
  291.       ngpr += n; \
  292.       goto done; \
  293.     } else { \
  294.       ngpr = maxgpr;  /* Prevent reordering. */ \
  295.       if (LJ_TARGET_IOS && d->size < 8) goto err_nyi; \
  296.     } \
  297.   }

  298. #elif LJ_TARGET_PPC
  299. /* -- PPC calling conventions --------------------------------------------- */

  300. #define CCALL_HANDLE_STRUCTRET \
  301.   cc->retref = 1/* Return all structs by reference. */ \
  302.   cc->gpr[ngpr++] = (GPRArg)dp;

  303. #define CCALL_HANDLE_COMPLEXRET \
  304.   /* Complex values are returned in 2 or 4 GPRs. */ \
  305.   cc->retref = 0;

  306. #define CCALL_HANDLE_COMPLEXRET2 \
  307.   memcpy(dp, sp, ctr->size);  /* Copy complex from GPRs. */

  308. #define CCALL_HANDLE_STRUCTARG \
  309.   rp = cdataptr(lj_cdata_new(cts, did, sz)); \
  310.   sz = CTSIZE_PTR/* Pass all structs by reference. */

  311. #define CCALL_HANDLE_COMPLEXARG \
  312.   /* Pass complex by value in 2 or 4 GPRs. */

  313. #define CCALL_HANDLE_REGARG \
  314.   if (isfp) {  /* Try to pass argument in FPRs. */ \
  315.     if (nfpr + 1 <= CCALL_NARG_FPR) { \
  316.       dp = &cc->fpr[nfpr]; \
  317.       nfpr += 1; \
  318.       d = ctype_get(cts, CTID_DOUBLE);  /* FPRs always hold doubles. */ \
  319.       goto done; \
  320.     } \
  321.   } else/* Try to pass argument in GPRs. */ \
  322.     if (n > 1) { \
  323.       lua_assert(n == 2 || n == 4);  /* int64_t or complex (float). */ \
  324.       if (ctype_isinteger(d->info)) \
  325.         ngpr = (ngpr + 1u) & ~1u/* Align int64_t to regpair. */ \
  326.       else if (ngpr + n > maxgpr) \
  327.         ngpr = maxgpr;  /* Prevent reordering. */ \
  328.     } \
  329.     if (ngpr + n <= maxgpr) { \
  330.       dp = &cc->gpr[ngpr]; \
  331.       ngpr += n; \
  332.       goto done; \
  333.     } \
  334.   }

  335. #define CCALL_HANDLE_RET \
  336.   if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
  337.     ctr = ctype_get(cts, CTID_DOUBLE);  /* FPRs always hold doubles. */

  338. #elif LJ_TARGET_MIPS
  339. /* -- MIPS calling conventions -------------------------------------------- */

  340. #define CCALL_HANDLE_STRUCTRET \
  341.   cc->retref = 1/* Return all structs by reference. */ \
  342.   cc->gpr[ngpr++] = (GPRArg)dp;

  343. #define CCALL_HANDLE_COMPLEXRET \
  344.   /* Complex values are returned in 1 or 2 FPRs. */ \
  345.   cc->retref = 0;

  346. #define CCALL_HANDLE_COMPLEXRET2 \
  347.   if (ctr->size == 2*sizeof(float)) {  /* Copy complex float from FPRs. */ \
  348.     ((float *)dp)[0] = cc->fpr[0].f; \
  349.     ((float *)dp)[1] = cc->fpr[1].f; \
  350.   } else/* Copy complex double from FPRs. */ \
  351.     ((double *)dp)[0] = cc->fpr[0].d; \
  352.     ((double *)dp)[1] = cc->fpr[1].d; \
  353.   }

  354. #define CCALL_HANDLE_STRUCTARG \
  355.   /* Pass all structs by value in registers and/or on the stack. */

  356. #define CCALL_HANDLE_COMPLEXARG \
  357.   /* Pass complex by value in 2 or 4 GPRs. */

  358. #define CCALL_HANDLE_REGARG \
  359.   if (isfp && nfpr < CCALL_NARG_FPR && !(ct->info & CTF_VARARG)) { \
  360.     /* Try to pass argument in FPRs. */ \
  361.     dp = n == 1 ? (void *)&cc->fpr[nfpr].f : (void *)&cc->fpr[nfpr].d; \
  362.     nfpr++; ngpr += n; \
  363.     goto done; \
  364.   } else/* Try to pass argument in GPRs. */ \
  365.     nfpr = CCALL_NARG_FPR; \
  366.     if ((d->info & CTF_ALIGN) > CTALIGN_PTR) \
  367.       ngpr = (ngpr + 1u) & ~1u/* Align to regpair. */ \
  368.     if (ngpr < maxgpr) { \
  369.       dp = &cc->gpr[ngpr]; \
  370.       if (ngpr + n > maxgpr) { \
  371.         nsp += ngpr + n - maxgpr;  /* Assumes contiguous gpr/stack fields. */ \
  372.         if (nsp > CCALL_MAXSTACK) goto err_nyi;  /* Too many arguments. */ \
  373.         ngpr = maxgpr; \
  374.       } else { \
  375.         ngpr += n; \
  376.       } \
  377.       goto done; \
  378.     } \
  379.   }

  380. #define CCALL_HANDLE_RET \
  381.   if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
  382.     sp = (uint8_t *)&cc->fpr[0].f;

  383. #else
  384. #error "Missing calling convention definitions for this architecture"
  385. #endif

  386. #ifndef CCALL_HANDLE_STRUCTRET2
  387. #define CCALL_HANDLE_STRUCTRET2 \
  388.   memcpy(dp, sp, ctr->size);  /* Copy struct return value from GPRs. */
  389. #endif

  390. /* -- x86 OSX ABI struct classification ----------------------------------- */

  391. #if LJ_TARGET_X86 && LJ_TARGET_OSX

  392. /* Check for struct with single FP field. */
  393. static int ccall_classify_struct(CTState *cts, CType *ct)
  394. {
  395.   CTSize sz = ct->size;
  396.   if (!(sz == sizeof(float) || sz == sizeof(double))) return 0;
  397.   if ((ct->info & CTF_UNION)) return 0;
  398.   while (ct->sib) {
  399.     ct = ctype_get(cts, ct->sib);
  400.     if (ctype_isfield(ct->info)) {
  401.       CType *sct = ctype_rawchild(cts, ct);
  402.       if (ctype_isfp(sct->info)) {
  403.         if (sct->size == sz)
  404.           return (sz >> 2);  /* Return 1 for float or 2 for double. */
  405.       } else if (ctype_isstruct(sct->info)) {
  406.         if (sct->size)
  407.           return ccall_classify_struct(cts, sct);
  408.       } else {
  409.         break;
  410.       }
  411.     } else if (ctype_isbitfield(ct->info)) {
  412.       break;
  413.     } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
  414.       CType *sct = ctype_rawchild(cts, ct);
  415.       if (sct->size)
  416.         return ccall_classify_struct(cts, sct);
  417.     }
  418.   }
  419.   return 0;
  420. }

  421. #endif

  422. /* -- x64 struct classification ------------------------------------------- */

  423. #if LJ_TARGET_X64 && !LJ_ABI_WIN

  424. /* Register classes for x64 struct classification. */
  425. #define CCALL_RCL_INT        1
  426. #define CCALL_RCL_SSE        2
  427. #define CCALL_RCL_MEM        4
  428. /* NYI: classify vectors. */

  429. static int ccall_classify_struct(CTState *cts, CType *ct, int *rcl, CTSize ofs);

  430. /* Classify a C type. */
  431. static void ccall_classify_ct(CTState *cts, CType *ct, int *rcl, CTSize ofs)
  432. {
  433.   if (ctype_isarray(ct->info)) {
  434.     CType *cct = ctype_rawchild(cts, ct);
  435.     CTSize eofs, esz = cct->size, asz = ct->size;
  436.     for (eofs = 0; eofs < asz; eofs += esz)
  437.       ccall_classify_ct(cts, cct, rcl, ofs+eofs);
  438.   } else if (ctype_isstruct(ct->info)) {
  439.     ccall_classify_struct(cts, ct, rcl, ofs);
  440.   } else {
  441.     int cl = ctype_isfp(ct->info) ? CCALL_RCL_SSE : CCALL_RCL_INT;
  442.     lua_assert(ctype_hassize(ct->info));
  443.     if ((ofs & (ct->size-1))) cl = CCALL_RCL_MEM/* Unaligned. */
  444.     rcl[(ofs >= 8)] |= cl;
  445.   }
  446. }

  447. /* Recursively classify a struct based on its fields. */
  448. static int ccall_classify_struct(CTState *cts, CType *ct, int *rcl, CTSize ofs)
  449. {
  450.   if (ct->size > 16) return CCALL_RCL_MEM/* Too big, gets memory class. */
  451.   while (ct->sib) {
  452.     CTSize fofs;
  453.     ct = ctype_get(cts, ct->sib);
  454.     fofs = ofs+ct->size;
  455.     if (ctype_isfield(ct->info))
  456.       ccall_classify_ct(cts, ctype_rawchild(cts, ct), rcl, fofs);
  457.     else if (ctype_isbitfield(ct->info))
  458.       rcl[(fofs >= 8)] |= CCALL_RCL_INT/* NYI: unaligned bitfields? */
  459.     else if (ctype_isxattrib(ct->info, CTA_SUBTYPE))
  460.       ccall_classify_struct(cts, ctype_rawchild(cts, ct), rcl, fofs);
  461.   }
  462.   return ((rcl[0]|rcl[1]) & CCALL_RCL_MEM);  /* Memory class? */
  463. }

  464. /* Try to split up a small struct into registers. */
  465. static int ccall_struct_reg(CCallState *cc, GPRArg *dp, int *rcl)
  466. {
  467.   MSize ngpr = cc->ngpr, nfpr = cc->nfpr;
  468.   uint32_t i;
  469.   for (i = 0; i < 2; i++) {
  470.     lua_assert(!(rcl[i] & CCALL_RCL_MEM));
  471.     if ((rcl[i] & CCALL_RCL_INT)) {  /* Integer class takes precedence. */
  472.       if (ngpr >= CCALL_NARG_GPR) return 1/* Register overflow. */
  473.       cc->gpr[ngpr++] = dp[i];
  474.     } else if ((rcl[i] & CCALL_RCL_SSE)) {
  475.       if (nfpr >= CCALL_NARG_FPR) return 1/* Register overflow. */
  476.       cc->fpr[nfpr++].l[0] = dp[i];
  477.     }
  478.   }
  479.   cc->ngpr = ngpr; cc->nfpr = nfpr;
  480.   return 0/* Ok. */
  481. }

  482. /* Pass a small struct argument. */
  483. static int ccall_struct_arg(CCallState *cc, CTState *cts, CType *d, int *rcl,
  484.                             TValue *o, int narg)
  485. {
  486.   GPRArg dp[2];
  487.   dp[0] = dp[1] = 0;
  488.   /* Convert to temp. struct. */
  489.   lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg));
  490.   if (ccall_struct_reg(cc, dp, rcl)) {  /* Register overflow? Pass on stack. */
  491.     MSize nsp = cc->nsp, n = rcl[1] ? 2 : 1;
  492.     if (nsp + n > CCALL_MAXSTACK) return 1/* Too many arguments. */
  493.     cc->nsp = nsp + n;
  494.     memcpy(&cc->stack[nsp], dp, n*CTSIZE_PTR);
  495.   }
  496.   return 0/* Ok. */
  497. }

  498. /* Combine returned small struct. */
  499. static void ccall_struct_ret(CCallState *cc, int *rcl, uint8_t *dp, CTSize sz)
  500. {
  501.   GPRArg sp[2];
  502.   MSize ngpr = 0, nfpr = 0;
  503.   uint32_t i;
  504.   for (i = 0; i < 2; i++) {
  505.     if ((rcl[i] & CCALL_RCL_INT)) {  /* Integer class takes precedence. */
  506.       sp[i] = cc->gpr[ngpr++];
  507.     } else if ((rcl[i] & CCALL_RCL_SSE)) {
  508.       sp[i] = cc->fpr[nfpr++].l[0];
  509.     }
  510.   }
  511.   memcpy(dp, sp, sz);
  512. }
  513. #endif

  514. /* -- ARM hard-float ABI struct classification ---------------------------- */

  515. #if LJ_TARGET_ARM && !LJ_ABI_SOFTFP

  516. /* Classify a struct based on its fields. */
  517. static unsigned int ccall_classify_struct(CTState *cts, CType *ct, CType *ctf)
  518. {
  519.   CTSize sz = ct->size;
  520.   unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION);
  521.   if ((ctf->info & CTF_VARARG)) goto noth;
  522.   while (ct->sib) {
  523.     CType *sct;
  524.     ct = ctype_get(cts, ct->sib);
  525.     if (ctype_isfield(ct->info)) {
  526.       sct = ctype_rawchild(cts, ct);
  527.       if (ctype_isfp(sct->info)) {
  528.         r |= sct->size;
  529.         if (!isu) n++; else if (n == 0) n = 1;
  530.       } else if (ctype_iscomplex(sct->info)) {
  531.         r |= (sct->size >> 1);
  532.         if (!isu) n += 2; else if (n < 2) n = 2;
  533.       } else if (ctype_isstruct(sct->info)) {
  534.         goto substruct;
  535.       } else {
  536.         goto noth;
  537.       }
  538.     } else if (ctype_isbitfield(ct->info)) {
  539.       goto noth;
  540.     } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
  541.       sct = ctype_rawchild(cts, ct);
  542.     substruct:
  543.       if (sct->size > 0) {
  544.         unsigned int s = ccall_classify_struct(cts, sct, ctf);
  545.         if (s <= 1) goto noth;
  546.         r |= (s & 255);
  547.         if (!isu) n += (s >> 8); else if (n < (s >>8)) n = (s >> 8);
  548.       }
  549.     }
  550.   }
  551.   if ((r == 4 || r == 8) && n <= 4)
  552.     return r + (n << 8);
  553. noth:  /* Not a homogeneous float/double aggregate. */
  554.   return (sz <= 4);  /* Return structs of size <= 4 in a GPR. */
  555. }

  556. #endif

  557. /* -- ARM64 ABI struct classification ------------------------------------- */

  558. #if LJ_TARGET_ARM64

  559. /* Classify a struct based on its fields. */
  560. static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
  561. {
  562.   CTSize sz = ct->size;
  563.   unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION);
  564.   while (ct->sib) {
  565.     CType *sct;
  566.     ct = ctype_get(cts, ct->sib);
  567.     if (ctype_isfield(ct->info)) {
  568.       sct = ctype_rawchild(cts, ct);
  569.       if (ctype_isfp(sct->info)) {
  570.         r |= sct->size;
  571.         if (!isu) n++; else if (n == 0) n = 1;
  572.       } else if (ctype_iscomplex(sct->info)) {
  573.         r |= (sct->size >> 1);
  574.         if (!isu) n += 2; else if (n < 2) n = 2;
  575.       } else if (ctype_isstruct(sct->info)) {
  576.         goto substruct;
  577.       } else {
  578.         goto noth;
  579.       }
  580.     } else if (ctype_isbitfield(ct->info)) {
  581.       goto noth;
  582.     } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
  583.       sct = ctype_rawchild(cts, ct);
  584.     substruct:
  585.       if (sct->size > 0) {
  586.         unsigned int s = ccall_classify_struct(cts, sct);
  587.         if (s <= 1) goto noth;
  588.         r |= (s & 255);
  589.         if (!isu) n += (s >> 8); else if (n < (s >>8)) n = (s >> 8);
  590.       }
  591.     }
  592.   }
  593.   if ((r == 4 || r == 8) && n <= 4)
  594.     return r + (n << 8);
  595. noth:  /* Not a homogeneous float/double aggregate. */
  596.   return (sz <= 16);  /* Return structs of size <= 16 in GPRs. */
  597. }

  598. #endif

  599. /* -- Common C call handling ---------------------------------------------- */

  600. /* Infer the destination CTypeID for a vararg argument. */
  601. CTypeID lj_ccall_ctid_vararg(CTState *cts, cTValue *o)
  602. {
  603.   if (tvisnumber(o)) {
  604.     return CTID_DOUBLE;
  605.   } else if (tviscdata(o)) {
  606.     CTypeID id = cdataV(o)->ctypeid;
  607.     CType *s = ctype_get(cts, id);
  608.     if (ctype_isrefarray(s->info)) {
  609.       return lj_ctype_intern(cts,
  610.                CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(s->info)), CTSIZE_PTR);
  611.     } else if (ctype_isstruct(s->info) || ctype_isfunc(s->info)) {
  612.       /* NYI: how to pass a struct by value in a vararg argument? */
  613.       return lj_ctype_intern(cts, CTINFO(CT_PTR, CTALIGN_PTR|id), CTSIZE_PTR);
  614.     } else if (ctype_isfp(s->info) && s->size == sizeof(float)) {
  615.       return CTID_DOUBLE;
  616.     } else {
  617.       return id;
  618.     }
  619.   } else if (tvisstr(o)) {
  620.     return CTID_P_CCHAR;
  621.   } else if (tvisbool(o)) {
  622.     return CTID_BOOL;
  623.   } else {
  624.     return CTID_P_VOID;
  625.   }
  626. }

  627. /* Setup arguments for C call. */
  628. static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
  629.                           CCallState *cc)
  630. {
  631.   int gcsteps = 0;
  632.   TValue *o, *top = L->top;
  633.   CTypeID fid;
  634.   CType *ctr;
  635.   MSize maxgpr, ngpr = 0, nsp = 0, narg;
  636. #if CCALL_NARG_FPR
  637.   MSize nfpr = 0;
  638. #if LJ_TARGET_ARM
  639.   MSize fprodd = 0;
  640. #endif
  641. #endif

  642.   /* Clear unused regs to get some determinism in case of misdeclaration. */
  643.   memset(cc->gpr, 0, sizeof(cc->gpr));
  644. #if CCALL_NUM_FPR
  645.   memset(cc->fpr, 0, sizeof(cc->fpr));
  646. #endif

  647. #if LJ_TARGET_X86
  648.   /* x86 has several different calling conventions. */
  649.   cc->resx87 = 0;
  650.   switch (ctype_cconv(ct->info)) {
  651.   case CTCC_FASTCALL: maxgpr = 2; break;
  652.   case CTCC_THISCALL: maxgpr = 1; break;
  653.   default: maxgpr = 0; break;
  654.   }
  655. #else
  656.   maxgpr = CCALL_NARG_GPR;
  657. #endif

  658.   /* Perform required setup for some result types. */
  659.   ctr = ctype_rawchild(cts, ct);
  660.   if (ctype_isvector(ctr->info)) {
  661.     if (!(CCALL_VECTOR_REG && (ctr->size == 8 || ctr->size == 16)))
  662.       goto err_nyi;
  663.   } else if (ctype_iscomplex(ctr->info) || ctype_isstruct(ctr->info)) {
  664.     /* Preallocate cdata object and anchor it after arguments. */
  665.     CTSize sz = ctr->size;
  666.     GCcdata *cd = lj_cdata_new(cts, ctype_cid(ct->info), sz);
  667.     void *dp = cdataptr(cd);
  668.     setcdataV(L, L->top++, cd);
  669.     if (ctype_isstruct(ctr->info)) {
  670.       CCALL_HANDLE_STRUCTRET
  671.     } else {
  672.       CCALL_HANDLE_COMPLEXRET
  673.     }
  674. #if LJ_TARGET_X86
  675.   } else if (ctype_isfp(ctr->info)) {
  676.     cc->resx87 = ctr->size == sizeof(float) ? 1 : 2;
  677. #endif
  678.   }

  679.   /* Skip initial attributes. */
  680.   fid = ct->sib;
  681.   while (fid) {
  682.     CType *ctf = ctype_get(cts, fid);
  683.     if (!ctype_isattrib(ctf->info)) break;
  684.     fid = ctf->sib;
  685.   }

  686.   /* Walk through all passed arguments. */
  687.   for (o = L->base+1, narg = 1; o < top; o++, narg++) {
  688.     CTypeID did;
  689.     CType *d;
  690.     CTSize sz;
  691.     MSize n, isfp = 0, isva = 0;
  692.     void *dp, *rp = NULL;

  693.     if (fid) {  /* Get argument type from field. */
  694.       CType *ctf = ctype_get(cts, fid);
  695.       fid = ctf->sib;
  696.       lua_assert(ctype_isfield(ctf->info));
  697.       did = ctype_cid(ctf->info);
  698.     } else {
  699.       if (!(ct->info & CTF_VARARG))
  700.         lj_err_caller(L, LJ_ERR_FFI_NUMARG);  /* Too many arguments. */
  701.       did = lj_ccall_ctid_vararg(cts, o);  /* Infer vararg type. */
  702.       isva = 1;
  703.     }
  704.     d = ctype_raw(cts, did);
  705.     sz = d->size;

  706.     /* Find out how (by value/ref) and where (GPR/FPR) to pass an argument. */
  707.     if (ctype_isnum(d->info)) {
  708.       if (sz > 8) goto err_nyi;
  709.       if ((d->info & CTF_FP))
  710.         isfp = 1;
  711.     } else if (ctype_isvector(d->info)) {
  712.       if (CCALL_VECTOR_REG && (sz == 8 || sz == 16))
  713.         isfp = 1;
  714.       else
  715.         goto err_nyi;
  716.     } else if (ctype_isstruct(d->info)) {
  717.       CCALL_HANDLE_STRUCTARG
  718.     } else if (ctype_iscomplex(d->info)) {
  719.       CCALL_HANDLE_COMPLEXARG
  720.     } else {
  721.       sz = CTSIZE_PTR;
  722.     }
  723.     sz = (sz + CTSIZE_PTR-1) & ~(CTSIZE_PTR-1);
  724.     n = sz / CTSIZE_PTR/* Number of GPRs or stack slots needed. */

  725.     CCALL_HANDLE_REGARG  /* Handle register arguments. */

  726.     /* Otherwise pass argument on stack. */
  727.     if (CCALL_ALIGN_STACKARG && !rp && (d->info & CTF_ALIGN) > CTALIGN_PTR) {
  728.       MSize align = (1u << ctype_align(d->info-CTALIGN_PTR)) -1;
  729.       nsp = (nsp + align) & ~align;  /* Align argument on stack. */
  730.     }
  731.     if (nsp + n > CCALL_MAXSTACK) {  /* Too many arguments. */
  732.     err_nyi:
  733.       lj_err_caller(L, LJ_ERR_FFI_NYICALL);
  734.     }
  735.     dp = &cc->stack[nsp];
  736.     nsp += n;
  737.     isva = 0;

  738.   done:
  739.     if (rp) {  /* Pass by reference. */
  740.       gcsteps++;
  741.       *(void **)dp = rp;
  742.       dp = rp;
  743.     }
  744.     lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg));
  745.     /* Extend passed integers to 32 bits at least. */
  746.     if (ctype_isinteger_or_bool(d->info) && d->size < 4) {
  747.       if (d->info & CTF_UNSIGNED)
  748.         *(uint32_t *)dp = d->size == 1 ? (uint32_t)*(uint8_t *)dp :
  749.                                          (uint32_t)*(uint16_t *)dp;
  750.       else
  751.         *(int32_t *)dp = d->size == 1 ? (int32_t)*(int8_t *)dp :
  752.                                         (int32_t)*(int16_t *)dp;
  753.     }
  754. #if LJ_TARGET_X64 && LJ_ABI_WIN
  755.     if (isva) {  /* Windows/x64 mirrors varargs in both register sets. */
  756.       if (nfpr == ngpr)
  757.         cc->gpr[ngpr-1] = cc->fpr[ngpr-1].l[0];
  758.       else
  759.         cc->fpr[ngpr-1].l[0] = cc->gpr[ngpr-1];
  760.     }
  761. #else
  762.     UNUSED(isva);
  763. #endif
  764. #if LJ_TARGET_X64 && !LJ_ABI_WIN
  765.     if (isfp == 2 && n == 2 && (uint8_t *)dp == (uint8_t *)&cc->fpr[nfpr-2]) {
  766.       cc->fpr[nfpr-1].d[0] = cc->fpr[nfpr-2].d[1];  /* Split complex double. */
  767.       cc->fpr[nfpr-2].d[1] = 0;
  768.     }
  769. #elif LJ_TARGET_ARM64
  770.     if (isfp == 2 && (uint8_t *)dp < (uint8_t *)cc->stack) {
  771.       /* Split float HFA or complex float into separate registers. */
  772.       CTSize i = (sz >> 2) - 1;
  773.       do { ((uint64_t *)dp)[i] = ((uint32_t *)dp)[i]; } while (i--);
  774.     }
  775. #else
  776.     UNUSED(isfp);
  777. #endif
  778.   }
  779.   if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG);  /* Too few arguments. */

  780. #if LJ_TARGET_X64 || LJ_TARGET_PPC
  781.   cc->nfpr = nfpr;  /* Required for vararg functions. */
  782. #endif
  783.   cc->nsp = nsp;
  784.   cc->spadj = (CCALL_SPS_FREE + CCALL_SPS_EXTRA)*CTSIZE_PTR;
  785.   if (nsp > CCALL_SPS_FREE)
  786.     cc->spadj += (((nsp-CCALL_SPS_FREE)*CTSIZE_PTR + 15u) & ~15u);
  787.   return gcsteps;
  788. }

  789. /* Get results from C call. */
  790. static int ccall_get_results(lua_State *L, CTState *cts, CType *ct,
  791.                              CCallState *cc, int *ret)
  792. {
  793.   CType *ctr = ctype_rawchild(cts, ct);
  794.   uint8_t *sp = (uint8_t *)&cc->gpr[0];
  795.   if (ctype_isvoid(ctr->info)) {
  796.     *ret = 0/* Zero results. */
  797.     return 0/* No additional GC step. */
  798.   }
  799.   *ret = 1/* One result. */
  800.   if (ctype_isstruct(ctr->info)) {
  801.     /* Return cdata object which is already on top of stack. */
  802.     if (!cc->retref) {
  803.       void *dp = cdataptr(cdataV(L->top-1));  /* Use preallocated object. */
  804.       CCALL_HANDLE_STRUCTRET2
  805.     }
  806.     return 1/* One GC step. */
  807.   }
  808.   if (ctype_iscomplex(ctr->info)) {
  809.     /* Return cdata object which is already on top of stack. */
  810.     void *dp = cdataptr(cdataV(L->top-1));  /* Use preallocated object. */
  811.     CCALL_HANDLE_COMPLEXRET2
  812.     return 1/* One GC step. */
  813.   }
  814.   if (LJ_BE && ctype_isinteger_or_bool(ctr->info) && ctr->size < CTSIZE_PTR)
  815.     sp += (CTSIZE_PTR - ctr->size);
  816. #if CCALL_NUM_FPR
  817.   if (ctype_isfp(ctr->info) || ctype_isvector(ctr->info))
  818.     sp = (uint8_t *)&cc->fpr[0];
  819. #endif
  820. #ifdef CCALL_HANDLE_RET
  821.   CCALL_HANDLE_RET
  822. #endif
  823.   /* No reference types end up here, so there's no need for the CTypeID. */
  824.   lua_assert(!(ctype_isrefarray(ctr->info) || ctype_isstruct(ctr->info)));
  825.   return lj_cconv_tv_ct(cts, ctr, 0, L->top-1, sp);
  826. }

  827. /* Call C function. */
  828. int lj_ccall_func(lua_State *L, GCcdata *cd)
  829. {
  830.   CTState *cts = ctype_cts(L);
  831.   CType *ct = ctype_raw(cts, cd->ctypeid);
  832.   CTSize sz = CTSIZE_PTR;
  833.   if (ctype_isptr(ct->info)) {
  834.     sz = ct->size;
  835.     ct = ctype_rawchild(cts, ct);
  836.   }
  837.   if (ctype_isfunc(ct->info)) {
  838.     CCallState cc;
  839.     int gcsteps, ret;
  840.     cc.func = (void (*)(void))cdata_getptr(cdataptr(cd), sz);
  841.     gcsteps = ccall_set_args(L, cts, ct, &cc);
  842.     ct = (CType *)((intptr_t)ct-(intptr_t)cts->tab);
  843.     cts->cb.slot = ~0u;
  844.     lj_vm_ffi_call(&cc);
  845.     if (cts->cb.slot != ~0u) {  /* Blacklist function that called a callback. */
  846.       TValue tv;
  847.       setlightudV(&tv, (void *)cc.func);
  848.       setboolV(lj_tab_set(L, cts->miscmap, &tv), 1);
  849.     }
  850.     ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab);  /* May be reallocated. */
  851.     gcsteps += ccall_get_results(L, cts, ct, &cc, &ret);
  852. #if LJ_TARGET_X86 && LJ_ABI_WIN
  853.     /* Automatically detect __stdcall and fix up C function declaration. */
  854.     if (cc.spadj && ctype_cconv(ct->info) == CTCC_CDECL) {
  855.       CTF_INSERT(ct->info, CCONV, CTCC_STDCALL);
  856.       lj_trace_abort(G(L));
  857.     }
  858. #endif
  859.     while (gcsteps-- > 0)
  860.       lj_gc_check(L);
  861.     return ret;
  862.   }
  863.   return -1/* Not a function. */
  864. }

  865. #endif