aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lj_ccall.c59
-rw-r--r--src/lj_cparse.c9
-rw-r--r--src/lj_ctype.h2
3 files changed, 57 insertions, 13 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c
index f5379e960..2446ed132 100644
--- a/src/lj_ccall.c
+++ b/src/lj_ccall.c
@@ -168,7 +168,9 @@
168 if (ccall_struct_arg(cc, cts, d, rcl, o, narg)) goto err_nyi; \ 168 if (ccall_struct_arg(cc, cts, d, rcl, o, narg)) goto err_nyi; \
169 nsp = cc->nsp; ngpr = cc->ngpr; nfpr = cc->nfpr; \ 169 nsp = cc->nsp; ngpr = cc->ngpr; nfpr = cc->nfpr; \
170 continue; \ 170 continue; \
171 } /* Pass all other structs by value on stack. */ 171 } else { /* Pass all other structs by value on stack. */ \
172 onstack = 1; \
173 }
172 174
173#define CCALL_HANDLE_COMPLEXARG \ 175#define CCALL_HANDLE_COMPLEXARG \
174 isfp = 2; /* Pass complex in FPRs or on stack. Needs postprocessing. */ 176 isfp = 2; /* Pass complex in FPRs or on stack. Needs postprocessing. */
@@ -183,7 +185,7 @@
183 } \ 185 } \
184 } else { /* Try to pass argument in GPRs. */ \ 186 } else { /* Try to pass argument in GPRs. */ \
185 /* Note that reordering is explicitly allowed in the x64 ABI. */ \ 187 /* Note that reordering is explicitly allowed in the x64 ABI. */ \
186 if (n <= 2 && ngpr + n <= maxgpr) { \ 188 if (!onstack && n <= 2 && ngpr + n <= maxgpr) { \
187 dp = &cc->gpr[ngpr]; \ 189 dp = &cc->gpr[ngpr]; \
188 ngpr += n; \ 190 ngpr += n; \
189 goto done; \ 191 goto done; \
@@ -350,7 +352,7 @@
350 nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \ 352 nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \
351 } \ 353 } \
352 } else { /* Try to pass argument in GPRs. */ \ 354 } else { /* Try to pass argument in GPRs. */ \
353 if (!LJ_TARGET_OSX && (d->info & CTF_ALIGN) > CTALIGN_PTR) \ 355 if (!LJ_TARGET_OSX && !rp && ccall_struct_align(cts, d) > CTALIGN_PTR) \
354 ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \ 356 ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
355 if (ngpr + n <= maxgpr) { \ 357 if (ngpr + n <= maxgpr) { \
356 dp = &cc->gpr[ngpr]; \ 358 dp = &cc->gpr[ngpr]; \
@@ -661,7 +663,7 @@ static int ccall_classify_struct(CTState *cts, CType *ct, int *rcl, CTSize ofs)
661 fofs = ofs+ct->size; 663 fofs = ofs+ct->size;
662 if (ctype_isfield(ct->info)) 664 if (ctype_isfield(ct->info))
663 ccall_classify_ct(cts, ctype_rawchild(cts, ct), rcl, fofs); 665 ccall_classify_ct(cts, ctype_rawchild(cts, ct), rcl, fofs);
664 else if (ctype_isbitfield(ct->info)) 666 else if (ctype_isbitfield(ct->info) && ctype_bitbsz(ct->info))
665 rcl[(fofs >= 8)] |= CCALL_RCL_INT; /* NYI: unaligned bitfields? */ 667 rcl[(fofs >= 8)] |= CCALL_RCL_INT; /* NYI: unaligned bitfields? */
666 else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) 668 else if (ctype_isxattrib(ct->info, CTA_SUBTYPE))
667 ccall_classify_struct(cts, ctype_rawchild(cts, ct), rcl, fofs); 669 ccall_classify_struct(cts, ctype_rawchild(cts, ct), rcl, fofs);
@@ -700,8 +702,11 @@ static int ccall_struct_arg(CCallState *cc, CTState *cts, CType *d, int *rcl,
700 if (ccall_struct_reg(cc, cts, dp, rcl)) { 702 if (ccall_struct_reg(cc, cts, dp, rcl)) {
701 /* Register overflow? Pass on stack. */ 703 /* Register overflow? Pass on stack. */
702 MSize nsp = cc->nsp, sz = rcl[1] ? 2*CTSIZE_PTR : CTSIZE_PTR; 704 MSize nsp = cc->nsp, sz = rcl[1] ? 2*CTSIZE_PTR : CTSIZE_PTR;
705 MSize align = (1u << ctype_align(d->info)) - 1;
703 if (nsp + sz > CCALL_SIZE_STACK) 706 if (nsp + sz > CCALL_SIZE_STACK)
704 return 1; /* Too many arguments. */ 707 return 1; /* Too many arguments. */
708 if (CCALL_ALIGN_STACKARG && align > CTSIZE_PTR-1)
709 nsp = (nsp + align) & ~align; /* Align argument on stack. */
705 cc->nsp = nsp + sz; 710 cc->nsp = nsp + sz;
706 memcpy((uint8_t *)cc->stack + nsp, dp, sz); 711 memcpy((uint8_t *)cc->stack + nsp, dp, sz);
707 } 712 }
@@ -776,6 +781,31 @@ noth: /* Not a homogeneous float/double aggregate. */
776 781
777#if LJ_TARGET_ARM64 782#if LJ_TARGET_ARM64
778 783
784#if !LJ_TARGET_OSX
785/* Alignment of pass-by-value structs: 8 or 16. */
786static CTInfo ccall_struct_align_arm64(CTState *cts, CType *ct)
787{
788 CTSize sz;
789 if (ct->sib) {
790 while (ct->sib) {
791 ct = ctype_get(cts, ct->sib);
792 if (ctype_isfield(ct->info)) {
793 if ((ct->info & CTF_ALIGN) > CTALIGN_PTR) return CTALIGN(4);
794 } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
795 CType *sct = ctype_rawchild(cts, ct);
796 CTInfo info = lj_ctype_info(cts, ctype_typeid(cts, sct), &sz);
797 if ((info & CTF_ALIGN) > CTALIGN_PTR) return CTALIGN(4);
798 }
799 }
800 } else {
801 CTInfo info = lj_ctype_info(cts, ctype_typeid(cts, ct), &sz);
802 if ((info & CTF_ALIGN) > CTALIGN_PTR) return CTALIGN(4);
803 }
804 return CTALIGN_PTR;
805}
806#define ccall_struct_align(cts, ct) ccall_struct_align_arm64((cts), (ct))
807#endif
808
779/* Classify a struct based on its fields. */ 809/* Classify a struct based on its fields. */
780static unsigned int ccall_classify_struct(CTState *cts, CType *ct) 810static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
781{ 811{
@@ -787,10 +817,10 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
787 ct = ctype_get(cts, ct->sib); 817 ct = ctype_get(cts, ct->sib);
788 if (ctype_isfield(ct->info)) { 818 if (ctype_isfield(ct->info)) {
789 sct = ctype_rawchild(cts, ct); 819 sct = ctype_rawchild(cts, ct);
790 if (ctype_isarray(sct->info)) { 820 if (ctype_isarray(sct->info) && !sct->size) goto noth;
821 while (ctype_isarray(sct->info)) {
791 CType *cct = ctype_rawchild(cts, sct); 822 CType *cct = ctype_rawchild(cts, sct);
792 if (!cct->size) continue; 823 m *= sct->size / cct->size;
793 m = sct->size / cct->size;
794 sct = cct; 824 sct = cct;
795 } 825 }
796 if (ctype_isfp(sct->info)) { 826 if (ctype_isfp(sct->info)) {
@@ -804,7 +834,7 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct)
804 } else { 834 } else {
805 goto noth; 835 goto noth;
806 } 836 }
807 } else if (ctype_isbitfield(ct->info)) { 837 } else if (ctype_isbitfield(ct->info) && ctype_bitbsz(ct->info)) {
808 goto noth; 838 goto noth;
809 } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) { 839 } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
810 sct = ctype_rawchild(cts, ct); 840 sct = ctype_rawchild(cts, ct);
@@ -899,6 +929,11 @@ static void ccall_copy_struct(CCallState *cc, CType *ctr, void *dp, void *sp,
899 929
900#endif 930#endif
901 931
932#ifndef ccall_struct_align
933/* Alignment of pass-by-value structs. */
934#define ccall_struct_align(cts, ct) ((ct)->info & CTF_ALIGN)
935#endif
936
902/* -- Common C call handling ---------------------------------------------- */ 937/* -- Common C call handling ---------------------------------------------- */
903 938
904/* Infer the destination CTypeID for a vararg argument. 939/* Infer the destination CTypeID for a vararg argument.
@@ -1013,6 +1048,9 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
1013 CTSize sz; 1048 CTSize sz;
1014 MSize n, isfp = 0, isva = 0; 1049 MSize n, isfp = 0, isva = 0;
1015 void *dp, *rp = NULL; 1050 void *dp, *rp = NULL;
1051#if LJ_TARGET_X64 && !LJ_ABI_WIN
1052 int onstack = 0;
1053#endif
1016 1054
1017 if (fid) { /* Get argument type from field. */ 1055 if (fid) { /* Get argument type from field. */
1018 CType *ctf = ctype_get(cts, fid); 1056 CType *ctf = ctype_get(cts, fid);
@@ -1051,7 +1089,10 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
1051 1089
1052 /* Otherwise pass argument on stack. */ 1090 /* Otherwise pass argument on stack. */
1053 if (CCALL_ALIGN_STACKARG) { /* Align argument on stack. */ 1091 if (CCALL_ALIGN_STACKARG) { /* Align argument on stack. */
1054 MSize align = (1u << ctype_align(d->info)) - 1; 1092 MSize align = (1u << ctype_align(ccall_struct_align(cts, d))) - 1;
1093#if LJ_TARGET_ARM64 && LJ_TARGET_OSX
1094 isva = 1;
1095#endif
1055 if (rp || (CCALL_PACK_STACKARG && isva && align < CTSIZE_PTR-1)) 1096 if (rp || (CCALL_PACK_STACKARG && isva && align < CTSIZE_PTR-1))
1056 align = CTSIZE_PTR-1; 1097 align = CTSIZE_PTR-1;
1057 nsp = (nsp + align) & ~align; 1098 nsp = (nsp + align) & ~align;
diff --git a/src/lj_cparse.c b/src/lj_cparse.c
index a1361a128..56e3e8491 100644
--- a/src/lj_cparse.c
+++ b/src/lj_cparse.c
@@ -1309,14 +1309,16 @@ static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
1309 align = ctype_align(attr); 1309 align = ctype_align(attr);
1310 if (cp->packstack[cp->curpack] < align) 1310 if (cp->packstack[cp->curpack] < align)
1311 align = cp->packstack[cp->curpack]; 1311 align = cp->packstack[cp->curpack];
1312 if (align > maxalign) maxalign = align; 1312 bsz = ctype_bitcsz(ct->info); /* Bitfield size (temp.). */
1313 if (align > maxalign && bsz) maxalign = align;
1313 amask = (8u << align) - 1; 1314 amask = (8u << align) - 1;
1314 1315
1315 bsz = ctype_bitcsz(ct->info); /* Bitfield size (temp.). */
1316 if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) { 1316 if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) {
1317 bsz = csz; /* Regular fields or subtypes always fill the container. */ 1317 bsz = csz; /* Regular fields or subtypes always fill the container. */
1318 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */ 1318 bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
1319 ct->size = (bofs >> 3); /* Store field offset. */ 1319 ct->size = (bofs >> 3); /* Store field offset. */
1320 if (ctype_isfield(ct->info))
1321 ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info)) + CTALIGN(align);
1320 } else { /* Bitfield. */ 1322 } else { /* Bitfield. */
1321 if (bsz == 0 || (attr & CTFP_ALIGNED) || 1323 if (bsz == 0 || (attr & CTFP_ALIGNED) ||
1322 (!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz)) 1324 (!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
@@ -1324,7 +1326,8 @@ static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
1324 1326
1325 /* Prefer regular field over bitfield. */ 1327 /* Prefer regular field over bitfield. */
1326 if (bsz == csz && (bofs & amask) == 0) { 1328 if (bsz == csz && (bofs & amask) == 0) {
1327 ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info)); 1329 ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info)) +
1330 CTALIGN(lj_fls(sz));
1328 ct->size = (bofs >> 3); /* Store field offset. */ 1331 ct->size = (bofs >> 3); /* Store field offset. */
1329 } else { 1332 } else {
1330 if (csz > amask+1 && bsz <= amask+1) 1333 if (csz > amask+1 && bsz <= amask+1)
diff --git a/src/lj_ctype.h b/src/lj_ctype.h
index 912fe2152..43d507b14 100644
--- a/src/lj_ctype.h
+++ b/src/lj_ctype.h
@@ -51,7 +51,7 @@ LJ_STATIC_ASSERT(((int)CT_STRUCT & (int)CT_ARRAY) == CT_STRUCT);
51** |FUNC ....VS.. cc cid | nargs | field | name? | name? | 51** |FUNC ....VS.. cc cid | nargs | field | name? | name? |
52** |TYPEDEF cid | | | name | name | 52** |TYPEDEF cid | | | name | name |
53** |ATTRIB attrnum cid | attr | sib? | type? | | 53** |ATTRIB attrnum cid | attr | sib? | type? | |
54** |FIELD cid | offset | field | | name? | 54** |FIELD A cid | offset | field | | name? |
55** |BITFIELD B.cvU csz bsz pos | offset | field | | name? | 55** |BITFIELD B.cvU csz bsz pos | offset | field | | name? |
56** |CONSTVAL c cid | value | const | name | name | 56** |CONSTVAL c cid | value | const | name | name |
57** |EXTERN cid | | sib? | name | name | 57** |EXTERN cid | | sib? | name | name |