diff --git a/src/Makefile b/src/Makefile index b9101a74..fa5aed1c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -479,7 +479,8 @@ TARGET_DEP= $(LIB_VMDEF) $(LUAJIT_SO) ifeq (Windows,$(TARGET_SYS)) TARGET_DYNCC= $(STATIC_CC) - LJVM_MODE= coffasm + LJVM_MODE= peobj + LJVM_BOUT= $(LJVM_O) LUAJIT_T= luajit.exe ifeq (cygwin,$(HOST_MSYS)) LUAJIT_SO= cyg$(TARGET_DLLNAME) 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 @@ #else +#if LJ_TARGET_OSX + +#define CCALL_HANDLE_STRUCTRET \ + /* Return structs of size 1, 2, 4 or 8 in registers. */ \ + cc->retref = !(sz == 1 || sz == 2 || sz == 4 || sz == 8); \ + if (cc->retref) { \ + if (ngpr < maxgpr) \ + cc->gpr[ngpr++] = (GPRArg)dp; \ + else \ + cc->stack[nsp++] = (GPRArg)dp; \ + } else { /* Struct with single FP field ends up in FPR. */ \ + cc->resx87 = ccall_classify_struct(cts, ctr); \ + } + +#define CCALL_HANDLE_STRUCTRET2 \ + if (cc->resx87) sp = (uint8_t *)&cc->fpr[0]; \ + memcpy(dp, sp, ctr->size); + +#else + #define CCALL_HANDLE_STRUCTRET \ cc->retref = 1; /* Return all structs by reference (in reg or on stack). */ \ if (ngpr < maxgpr) \ @@ -38,6 +58,8 @@ else \ cc->stack[nsp++] = (GPRArg)dp; +#endif + #define CCALL_HANDLE_COMPLEXRET \ /* Return complex float in GPRs and complex double by reference. */ \ cc->retref = (sz > 8); \ @@ -102,9 +124,9 @@ /* Windows/x64 argument registers are strictly positional (use ngpr). */ #define CCALL_HANDLE_REGARG \ if (isfp) { \ - if (ngpr < 4) { dp = &cc->fpr[ngpr++]; nfpr = ngpr; goto done; } \ + if (ngpr < maxgpr) { dp = &cc->fpr[ngpr++]; nfpr = ngpr; goto done; } \ } else { \ - if (ngpr < 4) { dp = &cc->gpr[ngpr++]; goto done; } \ + if (ngpr < maxgpr) { dp = &cc->gpr[ngpr++]; goto done; } \ } #elif LJ_TARGET_X64 @@ -413,6 +435,42 @@ memcpy(dp, sp, ctr->size); /* Copy struct return value from GPRs. */ #endif +/* -- x86 OSX ABI struct classification ----------------------------------- */ + +#if LJ_TARGET_X86 && LJ_TARGET_OSX + +/* Check for struct with single FP field. */ +static int ccall_classify_struct(CTState *cts, CType *ct) +{ + CTSize sz = ct->size; + if (!(sz == sizeof(float) || sz == sizeof(double))) return 0; + if ((ct->info & CTF_UNION)) return 0; + while (ct->sib) { + ct = ctype_get(cts, ct->sib); + if (ctype_isfield(ct->info)) { + CType *sct = ctype_rawchild(cts, ct); + if (ctype_isfp(sct->info)) { + if (sct->size == sz) + return (sz >> 2); /* Return 1 for float or 2 for double. */ + } else if (ctype_isstruct(sct->info)) { + if (sct->size) + return ccall_classify_struct(cts, sct); + } else { + break; + } + } else if (ctype_isbitfield(ct->info)) { + break; + } else if (ctype_isxattrib(ct->info, CTA_SUBTYPE)) { + CType *sct = ctype_rawchild(cts, ct); + if (sct->size) + return ccall_classify_struct(cts, sct); + } + } + return 0; +} + +#endif + /* -- x64 struct classification ------------------------------------------- */ #if LJ_TARGET_X64 && !LJ_ABI_WIN diff --git a/src/lj_ccallback.c b/src/lj_ccallback.c index a3a0d798..00109923 100644 --- a/src/lj_ccallback.c +++ b/src/lj_ccallback.c @@ -286,9 +286,9 @@ void lj_ccallback_mcode_free(CTState *cts) /* Windows/x64 argument registers are strictly positional (use ngpr). */ #define CALLBACK_HANDLE_REGARG \ if (isfp) { \ - if (ngpr < 4) { sp = &cts->cb.fpr[ngpr++]; nfpr = ngpr; goto done; } \ + if (ngpr < maxgpr) { sp = &cts->cb.fpr[ngpr++]; UNUSED(nfpr); goto done; } \ } else { \ - if (ngpr < 4) { sp = &cts->cb.gpr[ngpr++]; goto done; } \ + if (ngpr < maxgpr) { sp = &cts->cb.gpr[ngpr++]; goto done; } \ } #elif LJ_TARGET_X64 diff --git a/src/lj_err.c b/src/lj_err.c index 8ff0a455..7ae87a82 100644 --- a/src/lj_err.c +++ b/src/lj_err.c @@ -386,12 +386,17 @@ typedef struct UndocumentedDispatcherContext { ULONG Fill0; } UndocumentedDispatcherContext; -#ifdef _MSC_VER /* Another wild guess. */ -extern __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); +extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); + +#ifdef MINGW_SDK_INIT +/* Workaround for broken MinGW64 declaration. */ +VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); +#define RtlUnwindEx RtlUnwindEx_FIXED #endif #define LJ_MSVC_EXCODE ((DWORD)0xe06d7363) +#define LJ_GCC_EXCODE ((DWORD)0x20474343) #define LJ_EXCODE ((DWORD)0xe24c4a00) #define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c)) @@ -411,10 +416,9 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, } else { void *cf2 = err_unwind(L, cf, 0); if (cf2) { /* We catch it, so start unwinding the upper frames. */ - if (rec->ExceptionCode == LJ_MSVC_EXCODE) { -#ifdef _MSC_VER + if (rec->ExceptionCode == LJ_MSVC_EXCODE || + rec->ExceptionCode == LJ_GCC_EXCODE) { __DestructExceptionObject(rec, 1); -#endif setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); } else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) { /* Don't catch access violations etc. */ @@ -427,7 +431,7 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ? lj_vm_unwind_ff_eh : lj_vm_unwind_c_eh), - rec, (void *)errcode, ctx, dispatch->HistoryTable); + rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); /* RtlUnwindEx should never return. */ } }