summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2016-05-07 12:32:15 +0200
committerMike Pall <mike>2016-05-07 12:32:15 +0200
commit35b09e692ead67181755795352f1df12547fd4fa (patch)
treed120dd561f649f955ddbbe844fe00a97f7b9e625 /src
parent6a9973203c55daa4c1fcd611718bc5df09e4e5b5 (diff)
downloadluajit-35b09e692ead67181755795352f1df12547fd4fa.tar.gz
luajit-35b09e692ead67181755795352f1df12547fd4fa.tar.bz2
luajit-35b09e692ead67181755795352f1df12547fd4fa.zip
Windows/x86: Add full exception interoperability.
Contributed by Peter Cawley.
Diffstat (limited to 'src')
-rw-r--r--src/host/buildvm.c2
-rw-r--r--src/host/buildvm_peobj.c28
-rw-r--r--src/lj_err.c38
-rw-r--r--src/lj_frame.h12
-rw-r--r--src/lj_vm.h4
-rw-r--r--src/vm_x86.dasc77
6 files changed, 147 insertions, 14 deletions
diff --git a/src/host/buildvm.c b/src/host/buildvm.c
index 6d9e09e1..57b4dc97 100644
--- a/src/host/buildvm.c
+++ b/src/host/buildvm.c
@@ -110,7 +110,7 @@ static const char *sym_decorate(BuildCtx *ctx,
110 if (p) { 110 if (p) {
111#if LJ_TARGET_X86ORX64 111#if LJ_TARGET_X86ORX64
112 if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj)) 112 if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj))
113 name[0] = '@'; 113 name[0] = name[1] == 'R' ? '_' : '@'; /* Just for _RtlUnwind@16. */
114 else 114 else
115 *p = '\0'; 115 *p = '\0';
116#elif LJ_TARGET_PPC && !LJ_TARGET_CONSOLE 116#elif LJ_TARGET_PPC && !LJ_TARGET_CONSOLE
diff --git a/src/host/buildvm_peobj.c b/src/host/buildvm_peobj.c
index e8c927d8..42f6ac84 100644
--- a/src/host/buildvm_peobj.c
+++ b/src/host/buildvm_peobj.c
@@ -109,6 +109,8 @@ enum {
109#if LJ_TARGET_X64 109#if LJ_TARGET_X64
110 PEOBJ_SECT_PDATA, 110 PEOBJ_SECT_PDATA,
111 PEOBJ_SECT_XDATA, 111 PEOBJ_SECT_XDATA,
112#elif LJ_TARGET_X86
113 PEOBJ_SECT_SXDATA,
112#endif 114#endif
113 PEOBJ_SECT_RDATA_Z, 115 PEOBJ_SECT_RDATA_Z,
114 PEOBJ_NSECTIONS 116 PEOBJ_NSECTIONS
@@ -208,6 +210,13 @@ void emit_peobj(BuildCtx *ctx)
208 sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE; 210 sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
209 /* Flags: 40 = read, 30 = align4, 40 = initialized data. */ 211 /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
210 pesect[PEOBJ_SECT_XDATA].flags = 0x40300040; 212 pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
213#elif LJ_TARGET_X86
214 memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1);
215 pesect[PEOBJ_SECT_SXDATA].ofs = sofs;
216 sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4);
217 pesect[PEOBJ_SECT_SXDATA].relocofs = sofs;
218 /* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */
219 pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240;
211#endif 220#endif
212 221
213 memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1); 222 memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1);
@@ -232,7 +241,7 @@ void emit_peobj(BuildCtx *ctx)
232 nrsym = ctx->nrelocsym; 241 nrsym = ctx->nrelocsym;
233 pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym; 242 pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym;
234#if LJ_TARGET_X64 243#if LJ_TARGET_X64
235 pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */ 244 pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */
236#endif 245#endif
237 246
238 /* Write PE object header and all sections. */ 247 /* Write PE object header and all sections. */
@@ -312,6 +321,19 @@ void emit_peobj(BuildCtx *ctx)
312 reloc.type = PEOBJ_RELOC_ADDR32NB; 321 reloc.type = PEOBJ_RELOC_ADDR32NB;
313 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE); 322 owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
314 } 323 }
324#elif LJ_TARGET_X86
325 /* Write .sxdata section. */
326 for (i = 0; i < nrsym; i++) {
327 if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) {
328 uint32_t symidx = 1+2+i;
329 owrite(ctx, &symidx, 4);
330 break;
331 }
332 }
333 if (i == nrsym) {
334 fprintf(stderr, "Error: extern lj_err_unwind_win not used\n");
335 exit(1);
336 }
315#endif 337#endif
316 338
317 /* Write .rdata$Z section. */ 339 /* Write .rdata$Z section. */
@@ -333,8 +355,10 @@ void emit_peobj(BuildCtx *ctx)
333#if LJ_TARGET_X64 355#if LJ_TARGET_X64
334 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA); 356 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA);
335 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA); 357 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA);
336 emit_peobj_sym(ctx, "lj_err_unwind_win64", 0, 358 emit_peobj_sym(ctx, "lj_err_unwind_win", 0,
337 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN); 359 PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
360#elif LJ_TARGET_X86
361 emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA);
338#endif 362#endif
339 363
340 emit_peobj_sym(ctx, ctx->beginsym, 0, 364 emit_peobj_sym(ctx, ctx->beginsym, 0,
diff --git a/src/lj_err.c b/src/lj_err.c
index a847ca07..1314c8db 100644
--- a/src/lj_err.c
+++ b/src/lj_err.c
@@ -46,7 +46,8 @@
46** the wrapper function feature. Lua errors thrown through C++ frames 46** the wrapper function feature. Lua errors thrown through C++ frames
47** cannot be caught by C++ code and C++ destructors are not run. 47** cannot be caught by C++ code and C++ destructors are not run.
48** 48**
49** EXT is the default on x64 systems, INT is the default on all other systems. 49** EXT is the default on x64 systems and on Windows, INT is the default on all
50** other systems.
50** 51**
51** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack 52** EXT can be manually enabled on POSIX systems using GCC and DWARF2 stack
52** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled 53** unwinding with -DLUAJIT_UNWIND_EXTERNAL. *All* C code must be compiled
@@ -55,7 +56,6 @@
55** and all C libraries that have callbacks which may be used to call back 56** and all C libraries that have callbacks which may be used to call back
56** into Lua. C++ code must *not* be compiled with -fno-exceptions. 57** into Lua. C++ code must *not* be compiled with -fno-exceptions.
57** 58**
58** EXT cannot be enabled on WIN32 since system exceptions use code-driven SEH.
59** EXT is mandatory on WIN64 since the calling convention has an abundance 59** EXT is mandatory on WIN64 since the calling convention has an abundance
60** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15). 60** of callee-saved registers (rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15).
61** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4). 61** The POSIX/x64 interpreter only saves r12/r13 for INT (e.g. PS4).
@@ -63,7 +63,7 @@
63 63
64#if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND 64#if defined(__GNUC__) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND
65#define LJ_UNWIND_EXT 1 65#define LJ_UNWIND_EXT 1
66#elif LJ_TARGET_X64 && LJ_TARGET_WINDOWS 66#elif LJ_TARGET_WINDOWS
67#define LJ_UNWIND_EXT 1 67#define LJ_UNWIND_EXT 1
68#endif 68#endif
69 69
@@ -384,7 +384,7 @@ static void err_raise_ext(int errcode)
384 384
385#endif /* LJ_TARGET_ARM */ 385#endif /* LJ_TARGET_ARM */
386 386
387#elif LJ_TARGET_X64 && LJ_ABI_WIN 387#elif LJ_ABI_WIN
388 388
389/* 389/*
390** Someone in Redmond owes me several days of my life. A lot of this is 390** Someone in Redmond owes me several days of my life. A lot of this is
@@ -402,6 +402,7 @@ static void err_raise_ext(int errcode)
402#define WIN32_LEAN_AND_MEAN 402#define WIN32_LEAN_AND_MEAN
403#include <windows.h> 403#include <windows.h>
404 404
405#if LJ_TARGET_X64
405/* Taken from: http://www.nynaeve.net/?p=99 */ 406/* Taken from: http://www.nynaeve.net/?p=99 */
406typedef struct UndocumentedDispatcherContext { 407typedef struct UndocumentedDispatcherContext {
407 ULONG64 ControlPc; 408 ULONG64 ControlPc;
@@ -416,11 +417,14 @@ typedef struct UndocumentedDispatcherContext {
416 ULONG ScopeIndex; 417 ULONG ScopeIndex;
417 ULONG Fill0; 418 ULONG Fill0;
418} UndocumentedDispatcherContext; 419} UndocumentedDispatcherContext;
420#else
421typedef void *UndocumentedDispatcherContext;
422#endif
419 423
420/* Another wild guess. */ 424/* Another wild guess. */
421extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow); 425extern void __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
422 426
423#ifdef MINGW_SDK_INIT 427#if LJ_TARGET_X64 && defined(MINGW_SDK_INIT)
424/* Workaround for broken MinGW64 declaration. */ 428/* Workaround for broken MinGW64 declaration. */
425VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx"); 429VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");
426#define RtlUnwindEx RtlUnwindEx_FIXED 430#define RtlUnwindEx RtlUnwindEx_FIXED
@@ -434,10 +438,15 @@ VOID RtlUnwindEx_FIXED(PVOID,PVOID,PVOID,PVOID,PVOID,PVOID) asm("RtlUnwindEx");
434#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff) 438#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff)
435#define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff)) 439#define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff))
436 440
437/* Win64 exception handler for interpreter frame. */ 441/* Windows exception handler for interpreter frame. */
438LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec, 442LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win(EXCEPTION_RECORD *rec,
439 void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch) 443 void *f, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
440{ 444{
445#if LJ_TARGET_X64
446 void *cf = f;
447#else
448 void *cf = (char *)f - CFRAME_OFS_SEH;
449#endif
441 lua_State *L = cframe_L(cf); 450 lua_State *L = cframe_L(cf);
442 int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ? 451 int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?
443 LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN; 452 LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;
@@ -457,6 +466,7 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
457 /* Don't catch access violations etc. */ 466 /* Don't catch access violations etc. */
458 return ExceptionContinueSearch; 467 return ExceptionContinueSearch;
459 } 468 }
469#if LJ_TARGET_X64
460 /* Unwind the stack and call all handlers for all lower C frames 470 /* Unwind the stack and call all handlers for all lower C frames
461 ** (including ourselves) again with EH_UNWINDING set. Then set 471 ** (including ourselves) again with EH_UNWINDING set. Then set
462 ** rsp = cf, rax = errcode and jump to the specified target. 472 ** rsp = cf, rax = errcode and jump to the specified target.
@@ -466,6 +476,18 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
466 lj_vm_unwind_c_eh), 476 lj_vm_unwind_c_eh),
467 rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable); 477 rec, (void *)(uintptr_t)errcode, ctx, dispatch->HistoryTable);
468 /* RtlUnwindEx should never return. */ 478 /* RtlUnwindEx should never return. */
479#else
480 UNUSED(ctx);
481 UNUSED(dispatch);
482 /* Call all handlers for all lower C frames (including ourselves) again
483 ** with EH_UNWINDING set. Then call the specified function, passing cf
484 ** and errcode.
485 */
486 lj_vm_rtlunwind(cf, (void *)rec,
487 (cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
488 (void *)lj_vm_unwind_ff : (void *)lj_vm_unwind_c, errcode);
489 /* lj_vm_rtlunwind does not return. */
490#endif
469 } 491 }
470 } 492 }
471 return ExceptionContinueSearch; 493 return ExceptionContinueSearch;
diff --git a/src/lj_frame.h b/src/lj_frame.h
index fc0e281c..db2e4da1 100644
--- a/src/lj_frame.h
+++ b/src/lj_frame.h
@@ -116,6 +116,17 @@ enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */
116 116
117/* These definitions must match with the arch-specific *.dasc files. */ 117/* These definitions must match with the arch-specific *.dasc files. */
118#if LJ_TARGET_X86 118#if LJ_TARGET_X86
119#if LJ_ABI_WIN
120#define CFRAME_OFS_ERRF (19*4)
121#define CFRAME_OFS_NRES (18*4)
122#define CFRAME_OFS_PREV (17*4)
123#define CFRAME_OFS_L (16*4)
124#define CFRAME_OFS_SEH (9*4)
125#define CFRAME_OFS_PC (6*4)
126#define CFRAME_OFS_MULTRES (5*4)
127#define CFRAME_SIZE (16*4)
128#define CFRAME_SHIFT_MULTRES 0
129#else
119#define CFRAME_OFS_ERRF (15*4) 130#define CFRAME_OFS_ERRF (15*4)
120#define CFRAME_OFS_NRES (14*4) 131#define CFRAME_OFS_NRES (14*4)
121#define CFRAME_OFS_PREV (13*4) 132#define CFRAME_OFS_PREV (13*4)
@@ -124,6 +135,7 @@ enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */
124#define CFRAME_OFS_MULTRES (5*4) 135#define CFRAME_OFS_MULTRES (5*4)
125#define CFRAME_SIZE (12*4) 136#define CFRAME_SIZE (12*4)
126#define CFRAME_SHIFT_MULTRES 0 137#define CFRAME_SHIFT_MULTRES 0
138#endif
127#elif LJ_TARGET_X64 139#elif LJ_TARGET_X64
128#if LJ_ABI_WIN 140#if LJ_ABI_WIN
129#define CFRAME_OFS_PREV (13*8) 141#define CFRAME_OFS_PREV (13*8)
diff --git a/src/lj_vm.h b/src/lj_vm.h
index be35295d..d605b143 100644
--- a/src/lj_vm.h
+++ b/src/lj_vm.h
@@ -17,6 +17,10 @@ LJ_ASMF int lj_vm_cpcall(lua_State *L, lua_CFunction func, void *ud,
17LJ_ASMF int lj_vm_resume(lua_State *L, TValue *base, int nres1, ptrdiff_t ef); 17LJ_ASMF int lj_vm_resume(lua_State *L, TValue *base, int nres1, ptrdiff_t ef);
18LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_c(void *cframe, int errcode); 18LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_c(void *cframe, int errcode);
19LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_ff(void *cframe); 19LJ_ASMF_NORET void LJ_FASTCALL lj_vm_unwind_ff(void *cframe);
20#if LJ_ABI_WIN && LJ_TARGET_X86
21LJ_ASMF_NORET void LJ_FASTCALL lj_vm_rtlunwind(void *cframe, void *excptrec,
22 void *unwinder, int errcode);
23#endif
20LJ_ASMF void lj_vm_unwind_c_eh(void); 24LJ_ASMF void lj_vm_unwind_c_eh(void);
21LJ_ASMF void lj_vm_unwind_ff_eh(void); 25LJ_ASMF void lj_vm_unwind_ff_eh(void);
22#if LJ_TARGET_X86ORX64 26#if LJ_TARGET_X86ORX64
diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc
index f108c0b5..39ccaa2e 100644
--- a/src/vm_x86.dasc
+++ b/src/vm_x86.dasc
@@ -121,19 +121,68 @@
121|//----------------------------------------------------------------------- 121|//-----------------------------------------------------------------------
122|.if not X64 // x86 stack layout. 122|.if not X64 // x86 stack layout.
123| 123|
124|.define CFRAME_SPACE, aword*7 // Delta for esp (see <--). 124|.if WIN
125|
126|.define CFRAME_SPACE, aword*9 // Delta for esp (see <--).
125|.macro saveregs_ 127|.macro saveregs_
126| push edi; push esi; push ebx 128| push edi; push esi; push ebx
129| push extern lj_err_unwind_win
130| fs; push dword [0]
131| fs; mov [0], esp
127| sub esp, CFRAME_SPACE 132| sub esp, CFRAME_SPACE
128|.endmacro 133|.endmacro
129|.macro saveregs 134|.macro restoreregs
130| push ebp; saveregs_ 135| add esp, CFRAME_SPACE
136| fs; pop dword [0]
137| pop edi // Short for esp += 4.
138| pop ebx; pop esi; pop edi; pop ebp
139|.endmacro
140|
141|.else
142|
143|.define CFRAME_SPACE, aword*7 // Delta for esp (see <--).
144|.macro saveregs_
145| push edi; push esi; push ebx
146| sub esp, CFRAME_SPACE
131|.endmacro 147|.endmacro
132|.macro restoreregs 148|.macro restoreregs
133| add esp, CFRAME_SPACE 149| add esp, CFRAME_SPACE
134| pop ebx; pop esi; pop edi; pop ebp 150| pop ebx; pop esi; pop edi; pop ebp
135|.endmacro 151|.endmacro
136| 152|
153|.endif
154|
155|.macro saveregs
156| push ebp; saveregs_
157|.endmacro
158|
159|.if WIN
160|.define SAVE_ERRF, aword [esp+aword*19] // vm_pcall/vm_cpcall only.
161|.define SAVE_NRES, aword [esp+aword*18]
162|.define SAVE_CFRAME, aword [esp+aword*17]
163|.define SAVE_L, aword [esp+aword*16]
164|//----- 16 byte aligned, ^^^ arguments from C caller
165|.define SAVE_RET, aword [esp+aword*15] //<-- esp entering interpreter.
166|.define SAVE_R4, aword [esp+aword*14]
167|.define SAVE_R3, aword [esp+aword*13]
168|.define SAVE_R2, aword [esp+aword*12]
169|//----- 16 byte aligned
170|.define SAVE_R1, aword [esp+aword*11]
171|.define SEH_FUNC, aword [esp+aword*10]
172|.define SEH_NEXT, aword [esp+aword*9] //<-- esp after register saves.
173|.define UNUSED2, aword [esp+aword*8]
174|//----- 16 byte aligned
175|.define UNUSED1, aword [esp+aword*7]
176|.define SAVE_PC, aword [esp+aword*6]
177|.define TMP2, aword [esp+aword*5]
178|.define TMP1, aword [esp+aword*4]
179|//----- 16 byte aligned
180|.define ARG4, aword [esp+aword*3]
181|.define ARG3, aword [esp+aword*2]
182|.define ARG2, aword [esp+aword*1]
183|.define ARG1, aword [esp] //<-- esp while in interpreter.
184|//----- 16 byte aligned, ^^^ arguments for C callee
185|.else
137|.define SAVE_ERRF, aword [esp+aword*15] // vm_pcall/vm_cpcall only. 186|.define SAVE_ERRF, aword [esp+aword*15] // vm_pcall/vm_cpcall only.
138|.define SAVE_NRES, aword [esp+aword*14] 187|.define SAVE_NRES, aword [esp+aword*14]
139|.define SAVE_CFRAME, aword [esp+aword*13] 188|.define SAVE_CFRAME, aword [esp+aword*13]
@@ -154,6 +203,7 @@
154|.define ARG2, aword [esp+aword*1] 203|.define ARG2, aword [esp+aword*1]
155|.define ARG1, aword [esp] //<-- esp while in interpreter. 204|.define ARG1, aword [esp] //<-- esp while in interpreter.
156|//----- 16 byte aligned, ^^^ arguments for C callee 205|//----- 16 byte aligned, ^^^ arguments for C callee
206|.endif
157| 207|
158|// FPARGx overlaps ARGx and ARG(x+1) on x86. 208|// FPARGx overlaps ARGx and ARG(x+1) on x86.
159|.define FPARG3, qword [esp+qword*1] 209|.define FPARG3, qword [esp+qword*1]
@@ -554,6 +604,10 @@ static void build_subroutines(BuildCtx *ctx)
554 |.else 604 |.else
555 | mov eax, FCARG2 // Error return status for vm_pcall. 605 | mov eax, FCARG2 // Error return status for vm_pcall.
556 | mov esp, FCARG1 606 | mov esp, FCARG1
607 |.if WIN
608 | lea FCARG1, SEH_NEXT
609 | fs; mov [0], FCARG1
610 |.endif
557 |.endif 611 |.endif
558 |->vm_unwind_c_eh: // Landing pad for external unwinder. 612 |->vm_unwind_c_eh: // Landing pad for external unwinder.
559 | mov L:RB, SAVE_L 613 | mov L:RB, SAVE_L
@@ -577,6 +631,10 @@ static void build_subroutines(BuildCtx *ctx)
577 |.else 631 |.else
578 | and FCARG1, CFRAME_RAWMASK 632 | and FCARG1, CFRAME_RAWMASK
579 | mov esp, FCARG1 633 | mov esp, FCARG1
634 |.if WIN
635 | lea FCARG1, SEH_NEXT
636 | fs; mov [0], FCARG1
637 |.endif
580 |.endif 638 |.endif
581 |->vm_unwind_ff_eh: // Landing pad for external unwinder. 639 |->vm_unwind_ff_eh: // Landing pad for external unwinder.
582 | mov L:RB, SAVE_L 640 | mov L:RB, SAVE_L
@@ -590,6 +648,19 @@ static void build_subroutines(BuildCtx *ctx)
590 | set_vmstate INTERP 648 | set_vmstate INTERP
591 | jmp ->vm_returnc // Increments RD/MULTRES and returns. 649 | jmp ->vm_returnc // Increments RD/MULTRES and returns.
592 | 650 |
651 |.if WIN and not X64
652 |->vm_rtlunwind@16: // Thin layer around RtlUnwind.
653 | // (void *cframe, void *excptrec, void *unwinder, int errcode)
654 | mov [esp], FCARG1 // Return value for RtlUnwind.
655 | push FCARG2 // Exception record for RtlUnwind.
656 | push 0 // Ignored by RtlUnwind.
657 | push dword [FCARG1+CFRAME_OFS_SEH]
658 | call extern RtlUnwind@16 // Violates ABI (clobbers too much).
659 | mov FCARG1, eax
660 | mov FCARG2, [esp+4] // errcode (for vm_unwind_c).
661 | ret // Jump to unwinder.
662 |.endif
663 |
593 |//----------------------------------------------------------------------- 664 |//-----------------------------------------------------------------------
594 |//-- Grow stack for calls ----------------------------------------------- 665 |//-- Grow stack for calls -----------------------------------------------
595 |//----------------------------------------------------------------------- 666 |//-----------------------------------------------------------------------