aboutsummaryrefslogtreecommitdiff
path: root/src/lj_ccall.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_ccall.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c
index 34866dd2..a3ad1974 100644
--- a/src/lj_ccall.c
+++ b/src/lj_ccall.c
@@ -31,6 +31,26 @@
31 31
32#else 32#else
33 33
34#if LJ_TARGET_OSX
35
36#define CCALL_HANDLE_STRUCTRET \
37 /* Return structs of size 1, 2, 4 or 8 in registers. */ \
38 cc->retref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); \
39 if (cc->retref) { \
40 if (ngpr < maxgpr) \
41 cc->gpr[ngpr++] = (GPRArg)dp; \
42 else \
43 cc->stack[nsp++] = (GPRArg)dp; \
44 } else { /* Struct with single FP field ends up in FPR. */ \
45 cc->resx87 = ccall_classify_struct(cts, ctr); \
46 }
47
48#define CCALL_HANDLE_STRUCTRET2 \
49 if (cc->resx87) sp = (uint8_t *)&cc->fpr[0]; \
50 memcpy(dp, sp, ctr->size);
51
52#else
53
34#define CCALL_HANDLE_STRUCTRET \ 54#define CCALL_HANDLE_STRUCTRET \
35 cc->retref = 1; /* Return all structs by reference (in reg or on stack). */ \ 55 cc->retref = 1; /* Return all structs by reference (in reg or on stack). */ \
36 if (ngpr < maxgpr) \ 56 if (ngpr < maxgpr) \
@@ -38,6 +58,8 @@
38 else \ 58 else \
39 cc->stack[nsp++] = (GPRArg)dp; 59 cc->stack[nsp++] = (GPRArg)dp;
40 60
61#endif
62
41#define CCALL_HANDLE_COMPLEXRET \ 63#define CCALL_HANDLE_COMPLEXRET \
42 /* Return complex float in GPRs and complex double by reference. */ \ 64 /* Return complex float in GPRs and complex double by reference. */ \
43 cc->retref = (sz > 8); \ 65 cc->retref = (sz > 8); \
@@ -102,9 +124,9 @@
102/* Windows/x64 argument registers are strictly positional (use ngpr). */ 124/* Windows/x64 argument registers are strictly positional (use ngpr). */
103#define CCALL_HANDLE_REGARG \ 125#define CCALL_HANDLE_REGARG \
104 if (isfp) { \ 126 if (isfp) { \
105 if (ngpr < 4) { dp = &cc->fpr[ngpr++]; nfpr = ngpr; goto done; } \ 127 if (ngpr < maxgpr) { dp = &cc->fpr[ngpr++]; nfpr = ngpr; goto done; } \
106 } else { \ 128 } else { \
107 if (ngpr < 4) { dp = &cc->gpr[ngpr++]; goto done; } \ 129 if (ngpr < maxgpr) { dp = &cc->gpr[ngpr++]; goto done; } \
108 } 130 }
109 131
110#elif LJ_TARGET_X64 132#elif LJ_TARGET_X64
@@ -413,6 +435,42 @@
413 memcpy(dp, sp, ctr->size); /* Copy struct return value from GPRs. */ 435 memcpy(dp, sp, ctr->size); /* Copy struct return value from GPRs. */
414#endif 436#endif
415 437
438/* -- x86 OSX ABI struct classification ----------------------------------- */
439
440#if LJ_TARGET_X86 && LJ_TARGET_OSX
441
442/* Check for struct with single FP field. */
443static int ccall_classify_struct(CTState *cts, CType *ct)
444{
445 CTSize sz = ct->size;
446 if (!(sz == sizeof(float) || sz == sizeof(double))) return 0;
447 if ((ct->info & CTF_UNION)) return 0;
448 while (ct->sib) {
449 ct = ctype_get(cts, ct->sib);
450 if (ctype_isfield(ct->info)) {
451 CType *sct = ctype_rawchild(cts, ct);
452 if (ctype_isfp(sct->info)) {
453 if (sct->size == sz)
454 return (sz >> 2); /* Return 1 for float or 2 for double. */
455 } else if (ctype_isstruct(sct->info)) {
456 if (sct->size)
457 return ccall_classify_struct(cts, sct);
458 } else {
459 break;
460 }
461 } else if (ctype_isbitfield(ct->info)) {
462 break;
463 } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
464 CType *sct = ctype_rawchild(cts, ct);
465 if (sct->size)
466 return ccall_classify_struct(cts, sct);
467 }
468 }
469 return 0;
470}
471
472#endif
473
416/* -- x64 struct classification ------------------------------------------- */ 474/* -- x64 struct classification ------------------------------------------- */
417 475
418#if LJ_TARGET_X64 && !LJ_ABI_WIN 476#if LJ_TARGET_X64 && !LJ_ABI_WIN