diff options
Diffstat (limited to 'src/lj_ccall.c')
-rw-r--r-- | src/lj_ccall.c | 57 |
1 files changed, 31 insertions, 26 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 04e306eb..9001cb5a 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
@@ -20,12 +20,15 @@ | |||
20 | #if LJ_TARGET_X86 | 20 | #if LJ_TARGET_X86 |
21 | /* -- x86 calling conventions --------------------------------------------- */ | 21 | /* -- x86 calling conventions --------------------------------------------- */ |
22 | 22 | ||
23 | #define CCALL_PUSH(arg) \ | ||
24 | *(GPRArg *)((uint8_t *)cc->stack + nsp) = (GPRArg)(arg), nsp += CTSIZE_PTR | ||
25 | |||
23 | #if LJ_ABI_WIN | 26 | #if LJ_ABI_WIN |
24 | 27 | ||
25 | #define CCALL_HANDLE_STRUCTRET \ | 28 | #define CCALL_HANDLE_STRUCTRET \ |
26 | /* Return structs bigger than 8 by reference (on stack only). */ \ | 29 | /* Return structs bigger than 8 by reference (on stack only). */ \ |
27 | cc->retref = (sz > 8); \ | 30 | cc->retref = (sz > 8); \ |
28 | if (cc->retref) cc->stack[nsp++] = (GPRArg)dp; | 31 | if (cc->retref) CCALL_PUSH(dp); |
29 | 32 | ||
30 | #define CCALL_HANDLE_COMPLEXRET CCALL_HANDLE_STRUCTRET | 33 | #define CCALL_HANDLE_COMPLEXRET CCALL_HANDLE_STRUCTRET |
31 | 34 | ||
@@ -40,7 +43,7 @@ | |||
40 | if (ngpr < maxgpr) \ | 43 | if (ngpr < maxgpr) \ |
41 | cc->gpr[ngpr++] = (GPRArg)dp; \ | 44 | cc->gpr[ngpr++] = (GPRArg)dp; \ |
42 | else \ | 45 | else \ |
43 | cc->stack[nsp++] = (GPRArg)dp; \ | 46 | CCALL_PUSH(dp); \ |
44 | } else { /* Struct with single FP field ends up in FPR. */ \ | 47 | } else { /* Struct with single FP field ends up in FPR. */ \ |
45 | cc->resx87 = ccall_classify_struct(cts, ctr); \ | 48 | cc->resx87 = ccall_classify_struct(cts, ctr); \ |
46 | } | 49 | } |
@@ -56,7 +59,7 @@ | |||
56 | if (ngpr < maxgpr) \ | 59 | if (ngpr < maxgpr) \ |
57 | cc->gpr[ngpr++] = (GPRArg)dp; \ | 60 | cc->gpr[ngpr++] = (GPRArg)dp; \ |
58 | else \ | 61 | else \ |
59 | cc->stack[nsp++] = (GPRArg)dp; | 62 | CCALL_PUSH(dp); |
60 | 63 | ||
61 | #endif | 64 | #endif |
62 | 65 | ||
@@ -67,7 +70,7 @@ | |||
67 | if (ngpr < maxgpr) \ | 70 | if (ngpr < maxgpr) \ |
68 | cc->gpr[ngpr++] = (GPRArg)dp; \ | 71 | cc->gpr[ngpr++] = (GPRArg)dp; \ |
69 | else \ | 72 | else \ |
70 | cc->stack[nsp++] = (GPRArg)dp; \ | 73 | CCALL_PUSH(dp); \ |
71 | } | 74 | } |
72 | 75 | ||
73 | #endif | 76 | #endif |
@@ -278,8 +281,8 @@ | |||
278 | if (ngpr < maxgpr) { \ | 281 | if (ngpr < maxgpr) { \ |
279 | dp = &cc->gpr[ngpr]; \ | 282 | dp = &cc->gpr[ngpr]; \ |
280 | if (ngpr + n > maxgpr) { \ | 283 | if (ngpr + n > maxgpr) { \ |
281 | nsp += ngpr + n - maxgpr; /* Assumes contiguous gpr/stack fields. */ \ | 284 | nsp += (ngpr + n - maxgpr) * CTSIZE_PTR; /* Assumes contiguous gpr/stack fields. */ \ |
282 | if (nsp > CCALL_MAXSTACK) goto err_nyi; /* Too many arguments. */ \ | 285 | if (nsp > CCALL_SIZE_STACK) goto err_nyi; /* Too many arguments. */ \ |
283 | ngpr = maxgpr; \ | 286 | ngpr = maxgpr; \ |
284 | } else { \ | 287 | } else { \ |
285 | ngpr += n; \ | 288 | ngpr += n; \ |
@@ -471,8 +474,8 @@ | |||
471 | if (ngpr < maxgpr) { \ | 474 | if (ngpr < maxgpr) { \ |
472 | dp = &cc->gpr[ngpr]; \ | 475 | dp = &cc->gpr[ngpr]; \ |
473 | if (ngpr + n > maxgpr) { \ | 476 | if (ngpr + n > maxgpr) { \ |
474 | nsp += ngpr + n - maxgpr; /* Assumes contiguous gpr/stack fields. */ \ | 477 | nsp += (ngpr + n - maxgpr) * CTSIZE_PTR; /* Assumes contiguous gpr/stack fields. */ \ |
475 | if (nsp > CCALL_MAXSTACK) goto err_nyi; /* Too many arguments. */ \ | 478 | if (nsp > CCALL_SIZE_STACK) goto err_nyi; /* Too many arguments. */ \ |
476 | ngpr = maxgpr; \ | 479 | ngpr = maxgpr; \ |
477 | } else { \ | 480 | } else { \ |
478 | ngpr += n; \ | 481 | ngpr += n; \ |
@@ -565,8 +568,8 @@ | |||
565 | if (ngpr < maxgpr) { \ | 568 | if (ngpr < maxgpr) { \ |
566 | dp = &cc->gpr[ngpr]; \ | 569 | dp = &cc->gpr[ngpr]; \ |
567 | if (ngpr + n > maxgpr) { \ | 570 | if (ngpr + n > maxgpr) { \ |
568 | nsp += ngpr + n - maxgpr; /* Assumes contiguous gpr/stack fields. */ \ | 571 | nsp += (ngpr + n - maxgpr) * CTSIZE_PTR; /* Assumes contiguous gpr/stack fields. */ \ |
569 | if (nsp > CCALL_MAXSTACK) goto err_nyi; /* Too many arguments. */ \ | 572 | if (nsp > CCALL_SIZE_STACK) goto err_nyi; /* Too many arguments. */ \ |
570 | ngpr = maxgpr; \ | 573 | ngpr = maxgpr; \ |
571 | } else { \ | 574 | } else { \ |
572 | ngpr += n; \ | 575 | ngpr += n; \ |
@@ -698,10 +701,11 @@ static int ccall_struct_arg(CCallState *cc, CTState *cts, CType *d, int *rcl, | |||
698 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); | 701 | lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg)); |
699 | if (ccall_struct_reg(cc, cts, dp, rcl)) { | 702 | if (ccall_struct_reg(cc, cts, dp, rcl)) { |
700 | /* Register overflow? Pass on stack. */ | 703 | /* Register overflow? Pass on stack. */ |
701 | MSize nsp = cc->nsp, n = rcl[1] ? 2 : 1; | 704 | MSize nsp = cc->nsp, sz = rcl[1] ? 2*CTSIZE_PTR : CTSIZE_PTR; |
702 | if (nsp + n > CCALL_MAXSTACK) return 1; /* Too many arguments. */ | 705 | if (nsp + sz > CCALL_SIZE_STACK) |
703 | cc->nsp = nsp + n; | 706 | return 1; /* Too many arguments. */ |
704 | memcpy(&cc->stack[nsp], dp, n*CTSIZE_PTR); | 707 | cc->nsp = nsp + sz; |
708 | memcpy((uint8_t *)cc->stack + nsp, dp, sz); | ||
705 | } | 709 | } |
706 | return 0; /* Ok. */ | 710 | return 0; /* Ok. */ |
707 | } | 711 | } |
@@ -1022,22 +1026,23 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
1022 | } else { | 1026 | } else { |
1023 | sz = CTSIZE_PTR; | 1027 | sz = CTSIZE_PTR; |
1024 | } | 1028 | } |
1025 | sz = (sz + CTSIZE_PTR-1) & ~(CTSIZE_PTR-1); | 1029 | n = (sz + CTSIZE_PTR-1) / CTSIZE_PTR; /* Number of GPRs or stack slots needed. */ |
1026 | n = sz / CTSIZE_PTR; /* Number of GPRs or stack slots needed. */ | ||
1027 | 1030 | ||
1028 | CCALL_HANDLE_REGARG /* Handle register arguments. */ | 1031 | CCALL_HANDLE_REGARG /* Handle register arguments. */ |
1029 | 1032 | ||
1030 | /* Otherwise pass argument on stack. */ | 1033 | /* Otherwise pass argument on stack. */ |
1031 | if (CCALL_ALIGN_STACKARG && !rp && (d->info & CTF_ALIGN) > CTALIGN_PTR) { | 1034 | if (CCALL_ALIGN_STACKARG) { /* Align argument on stack. */ |
1032 | MSize align = (1u << ctype_align(d->info-CTALIGN_PTR)) -1; | 1035 | MSize align = (1u << ctype_align(d->info)) - 1; |
1033 | nsp = (nsp + align) & ~align; /* Align argument on stack. */ | 1036 | if (rp) |
1037 | align = CTSIZE_PTR-1; | ||
1038 | nsp = (nsp + align) & ~align; | ||
1034 | } | 1039 | } |
1035 | if (nsp + n > CCALL_MAXSTACK) { /* Too many arguments. */ | 1040 | dp = ((uint8_t *)cc->stack) + nsp; |
1041 | nsp += n * CTSIZE_PTR; | ||
1042 | if (nsp > CCALL_SIZE_STACK) { /* Too many arguments. */ | ||
1036 | err_nyi: | 1043 | err_nyi: |
1037 | lj_err_caller(L, LJ_ERR_FFI_NYICALL); | 1044 | lj_err_caller(L, LJ_ERR_FFI_NYICALL); |
1038 | } | 1045 | } |
1039 | dp = &cc->stack[nsp]; | ||
1040 | nsp += n; | ||
1041 | isva = 0; | 1046 | isva = 0; |
1042 | 1047 | ||
1043 | done: | 1048 | done: |
@@ -1099,10 +1104,10 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
1099 | #if LJ_TARGET_X64 || (LJ_TARGET_PPC && !LJ_ABI_SOFTFP) | 1104 | #if LJ_TARGET_X64 || (LJ_TARGET_PPC && !LJ_ABI_SOFTFP) |
1100 | cc->nfpr = nfpr; /* Required for vararg functions. */ | 1105 | cc->nfpr = nfpr; /* Required for vararg functions. */ |
1101 | #endif | 1106 | #endif |
1102 | cc->nsp = nsp; | 1107 | cc->nsp = (nsp + CTSIZE_PTR-1) & ~(CTSIZE_PTR-1); |
1103 | cc->spadj = (CCALL_SPS_FREE + CCALL_SPS_EXTRA)*CTSIZE_PTR; | 1108 | cc->spadj = (CCALL_SPS_FREE + CCALL_SPS_EXTRA) * CTSIZE_PTR; |
1104 | if (nsp > CCALL_SPS_FREE) | 1109 | if (cc->nsp > CCALL_SPS_FREE * CTSIZE_PTR) |
1105 | cc->spadj += (((nsp-CCALL_SPS_FREE)*CTSIZE_PTR + 15u) & ~15u); | 1110 | cc->spadj += (((cc->nsp - CCALL_SPS_FREE * CTSIZE_PTR) + 15u) & ~15u); |
1106 | return gcsteps; | 1111 | return gcsteps; |
1107 | } | 1112 | } |
1108 | 1113 | ||