diff options
-rw-r--r-- | src/host/buildvm_asm.c | 9 | ||||
-rw-r--r-- | src/lj_err.c | 92 | ||||
-rw-r--r-- | src/vm_arm.dasc | 11 |
3 files changed, 84 insertions, 28 deletions
diff --git a/src/host/buildvm_asm.c b/src/host/buildvm_asm.c index 9b7ae53a..9b119425 100644 --- a/src/host/buildvm_asm.c +++ b/src/host/buildvm_asm.c | |||
@@ -261,11 +261,20 @@ void emit_asm(BuildCtx *ctx) | |||
261 | 261 | ||
262 | #if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND | 262 | #if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND |
263 | /* This should really be moved into buildvm_arm.dasc. */ | 263 | /* This should really be moved into buildvm_arm.dasc. */ |
264 | #if LJ_ARCH_HASFPU | ||
265 | fprintf(ctx->fp, | ||
266 | ".fnstart\n" | ||
267 | ".save {r5, r6, r7, r8, r9, r10, r11, lr}\n" | ||
268 | ".vsave {d8-d15}\n" | ||
269 | ".save {r4}\n" | ||
270 | ".pad #28\n"); | ||
271 | #else | ||
264 | fprintf(ctx->fp, | 272 | fprintf(ctx->fp, |
265 | ".fnstart\n" | 273 | ".fnstart\n" |
266 | ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" | 274 | ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" |
267 | ".pad #28\n"); | 275 | ".pad #28\n"); |
268 | #endif | 276 | #endif |
277 | #endif | ||
269 | #if LJ_TARGET_MIPS | 278 | #if LJ_TARGET_MIPS |
270 | fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n"); | 279 | fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n"); |
271 | #endif | 280 | #endif |
diff --git a/src/lj_err.c b/src/lj_err.c index 9ac0c988..d641735e 100644 --- a/src/lj_err.c +++ b/src/lj_err.c | |||
@@ -190,13 +190,6 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode) | |||
190 | ** since various OS, distros and compilers mess up the header installation. | 190 | ** since various OS, distros and compilers mess up the header installation. |
191 | */ | 191 | */ |
192 | 192 | ||
193 | typedef struct _Unwind_Exception | ||
194 | { | ||
195 | uint64_t exclass; | ||
196 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
197 | uintptr_t p1, p2; | ||
198 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
199 | |||
200 | typedef struct _Unwind_Context _Unwind_Context; | 193 | typedef struct _Unwind_Context _Unwind_Context; |
201 | 194 | ||
202 | #define _URC_OK 0 | 195 | #define _URC_OK 0 |
@@ -206,8 +199,20 @@ typedef struct _Unwind_Context _Unwind_Context; | |||
206 | #define _URC_CONTINUE_UNWIND 8 | 199 | #define _URC_CONTINUE_UNWIND 8 |
207 | #define _URC_FAILURE 9 | 200 | #define _URC_FAILURE 9 |
208 | 201 | ||
202 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
203 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
204 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
205 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
206 | |||
209 | #if !LJ_TARGET_ARM | 207 | #if !LJ_TARGET_ARM |
210 | 208 | ||
209 | typedef struct _Unwind_Exception | ||
210 | { | ||
211 | uint64_t exclass; | ||
212 | void (*excleanup)(int, struct _Unwind_Exception *); | ||
213 | uintptr_t p1, p2; | ||
214 | } __attribute__((__aligned__)) _Unwind_Exception; | ||
215 | |||
211 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); | 216 | extern uintptr_t _Unwind_GetCFA(_Unwind_Context *); |
212 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); | 217 | extern void _Unwind_SetGR(_Unwind_Context *, int, uintptr_t); |
213 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); | 218 | extern void _Unwind_SetIP(_Unwind_Context *, uintptr_t); |
@@ -219,11 +224,6 @@ extern int _Unwind_RaiseException(_Unwind_Exception *); | |||
219 | #define _UA_HANDLER_FRAME 4 | 224 | #define _UA_HANDLER_FRAME 4 |
220 | #define _UA_FORCE_UNWIND 8 | 225 | #define _UA_FORCE_UNWIND 8 |
221 | 226 | ||
222 | #define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */ | ||
223 | #define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (uint64_t)(c)) | ||
224 | #define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff) | ||
225 | #define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff)) | ||
226 | |||
227 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ | 227 | /* DWARF2 personality handler referenced from interpreter .eh_frame. */ |
228 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, | 228 | LJ_FUNCA int lj_err_unwind_dwarf(int version, int actions, |
229 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) | 229 | uint64_t uexclass, _Unwind_Exception *uex, _Unwind_Context *ctx) |
@@ -302,10 +302,23 @@ static void err_raise_ext(int errcode) | |||
302 | } | 302 | } |
303 | #endif | 303 | #endif |
304 | 304 | ||
305 | #else | 305 | #else /* LJ_TARGET_ARM */ |
306 | |||
307 | #define _US_VIRTUAL_UNWIND_FRAME 0 | ||
308 | #define _US_UNWIND_FRAME_STARTING 1 | ||
309 | #define _US_ACTION_MASK 3 | ||
310 | #define _US_FORCE_UNWIND 8 | ||
311 | |||
312 | typedef struct _Unwind_Control_Block _Unwind_Control_Block; | ||
313 | typedef struct _Unwind_Context _Unwind_Context; | ||
314 | |||
315 | struct _Unwind_Control_Block { | ||
316 | uint64_t exclass; | ||
317 | uint32_t misc[20]; | ||
318 | }; | ||
306 | 319 | ||
307 | extern void _Unwind_DeleteException(void *); | 320 | extern int _Unwind_RaiseException(_Unwind_Control_Block *); |
308 | extern int __gnu_unwind_frame (void *, _Unwind_Context *); | 321 | extern int __gnu_unwind_frame(_Unwind_Control_Block *, _Unwind_Context *); |
309 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); | 322 | extern int _Unwind_VRS_Set(_Unwind_Context *, int, uint32_t, int, void *); |
310 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); | 323 | extern int _Unwind_VRS_Get(_Unwind_Context *, int, uint32_t, int, void *); |
311 | 324 | ||
@@ -321,34 +334,57 @@ static inline void _Unwind_SetGR(_Unwind_Context *ctx, int r, uint32_t v) | |||
321 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); | 334 | _Unwind_VRS_Set(ctx, 0, r, 0, &v); |
322 | } | 335 | } |
323 | 336 | ||
324 | #define _US_VIRTUAL_UNWIND_FRAME 0 | 337 | extern void lj_vm_unwind_ext(void); |
325 | #define _US_UNWIND_FRAME_STARTING 1 | ||
326 | #define _US_ACTION_MASK 3 | ||
327 | #define _US_FORCE_UNWIND 8 | ||
328 | 338 | ||
329 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ | 339 | /* ARM unwinder personality handler referenced from interpreter .ARM.extab. */ |
330 | LJ_FUNCA int lj_err_unwind_arm(int state, void *ucb, _Unwind_Context *ctx) | 340 | LJ_FUNCA int lj_err_unwind_arm(int state, _Unwind_Control_Block *ucb, |
341 | _Unwind_Context *ctx) | ||
331 | { | 342 | { |
332 | void *cf = (void *)_Unwind_GetGR(ctx, 13); | 343 | void *cf = (void *)_Unwind_GetGR(ctx, 13); |
333 | lua_State *L = cframe_L(cf); | 344 | lua_State *L = cframe_L(cf); |
334 | if ((state & _US_ACTION_MASK) == _US_VIRTUAL_UNWIND_FRAME) { | 345 | int errcode; |
335 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); | 346 | |
347 | switch ((state & _US_ACTION_MASK)) { | ||
348 | case _US_VIRTUAL_UNWIND_FRAME: | ||
349 | if ((state & _US_FORCE_UNWIND)) break; | ||
336 | return _URC_HANDLER_FOUND; | 350 | return _URC_HANDLER_FOUND; |
337 | } | 351 | case _US_UNWIND_FRAME_STARTING: |
338 | if ((state&(_US_ACTION_MASK|_US_FORCE_UNWIND)) == _US_UNWIND_FRAME_STARTING) { | 352 | if (LJ_UEXCLASS_CHECK(ucb->exclass)) { |
339 | _Unwind_DeleteException(ucb); | 353 | errcode = LJ_UEXCLASS_ERRCODE(ucb->exclass); |
340 | _Unwind_SetGR(ctx, 15, (uint32_t)(void *)lj_err_throw); | 354 | } else { |
341 | _Unwind_SetGR(ctx, 0, (uint32_t)L); | 355 | errcode = LUA_ERRRUN; |
342 | _Unwind_SetGR(ctx, 1, (uint32_t)LUA_ERRRUN); | 356 | setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP)); |
357 | } | ||
358 | cf = err_unwind(L, cf, errcode); | ||
359 | if ((state & _US_FORCE_UNWIND) || cf == NULL) break; | ||
360 | _Unwind_SetGR(ctx, 15, (uint32_t)lj_vm_unwind_ext); | ||
361 | _Unwind_SetGR(ctx, 0, (uint32_t)ucb); | ||
362 | _Unwind_SetGR(ctx, 1, (uint32_t)errcode); | ||
363 | _Unwind_SetGR(ctx, 2, cframe_unwind_ff(cf) ? | ||
364 | (uint32_t)lj_vm_unwind_ff_eh : | ||
365 | (uint32_t)lj_vm_unwind_c_eh); | ||
343 | return _URC_INSTALL_CONTEXT; | 366 | return _URC_INSTALL_CONTEXT; |
367 | default: | ||
368 | return _URC_FAILURE; | ||
344 | } | 369 | } |
345 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) | 370 | if (__gnu_unwind_frame(ucb, ctx) != _URC_OK) |
346 | return _URC_FAILURE; | 371 | return _URC_FAILURE; |
347 | return _URC_CONTINUE_UNWIND; | 372 | return _URC_CONTINUE_UNWIND; |
348 | } | 373 | } |
349 | 374 | ||
375 | #if LJ_UNWIND_EXT | ||
376 | static __thread _Unwind_Control_Block static_uex; | ||
377 | |||
378 | static void err_raise_ext(int errcode) | ||
379 | { | ||
380 | memset(&static_uex, 0, sizeof(static_uex)); | ||
381 | static_uex.exclass = LJ_UEXCLASS_MAKE(errcode); | ||
382 | _Unwind_RaiseException(&static_uex); | ||
383 | } | ||
350 | #endif | 384 | #endif |
351 | 385 | ||
386 | #endif /* LJ_TARGET_ARM */ | ||
387 | |||
352 | #elif LJ_TARGET_X64 && LJ_ABI_WIN | 388 | #elif LJ_TARGET_X64 && LJ_ABI_WIN |
353 | 389 | ||
354 | /* | 390 | /* |
diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc index af722f9e..acc0853b 100644 --- a/src/vm_arm.dasc +++ b/src/vm_arm.dasc | |||
@@ -373,6 +373,17 @@ static void build_subroutines(BuildCtx *ctx) | |||
373 | | st_vmstate CARG2 | 373 | | st_vmstate CARG2 |
374 | | b ->vm_returnc | 374 | | b ->vm_returnc |
375 | | | 375 | | |
376 | |->vm_unwind_ext: // Complete external unwind. | ||
377 | #if !LJ_NO_UNWIND | ||
378 | | push {r0, r1, r2, lr} | ||
379 | | bl extern _Unwind_Complete | ||
380 | | ldr r0, [sp] | ||
381 | | bl extern _Unwind_DeleteException | ||
382 | | pop {r0, r1, r2, lr} | ||
383 | | mov r0, r1 | ||
384 | | bx r2 | ||
385 | #endif | ||
386 | | | ||
376 | |//----------------------------------------------------------------------- | 387 | |//----------------------------------------------------------------------- |
377 | |//-- Grow stack for calls ----------------------------------------------- | 388 | |//-- Grow stack for calls ----------------------------------------------- |
378 | |//----------------------------------------------------------------------- | 389 | |//----------------------------------------------------------------------- |