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