diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_ccall.c | 62 |
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. */ | ||
443 | static 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 |