mirror of
https://github.com/reactos/reactos.git
synced 2025-04-19 12:08:55 +00:00
[PSEH3]
Start factoring out compiler support for nested functions (neither CLANG not C++ support it, so we will add some other crazy hacks later ;-)) svn path=/trunk/; revision=62402
This commit is contained in:
parent
2948ed43c5
commit
a12d2d5e6c
2 changed files with 45 additions and 24 deletions
|
@ -89,7 +89,7 @@ unsigned long __cdecl __attribute__((error("Can only be used inside an exception
|
|||
void * __cdecl __attribute__((error("Can only be used inside an exception filter."))) _exception_info(void);
|
||||
|
||||
/* This attribute allows automatic cleanup of the registered frames */
|
||||
#define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_AutoCleanup)))
|
||||
#define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_Unregister)))
|
||||
|
||||
/* CLANG specific definitions! */
|
||||
#ifdef __clang__
|
||||
|
@ -133,6 +133,8 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
|||
} \
|
||||
} while(0)
|
||||
|
||||
#define _SEH3$_SCARE_GCC()
|
||||
|
||||
#else /* !__clang__ */
|
||||
|
||||
#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label)
|
||||
|
@ -155,14 +157,49 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
|||
: "ecx", "edx", "memory" \
|
||||
: _SEH3$_l_HandlerTarget)
|
||||
|
||||
/* Define the registers that get clobbered, when reaching the __except block.
|
||||
We specify ebp on optimized builds without frame pointer, since it will be
|
||||
used by GCC as a general purpose register then. */
|
||||
#if defined(__OPTIMIZE__) && defined(_ALLOW_OMIT_FRAME_POINTER)
|
||||
#define _SEH3$_CLOBBER_ON_EXCEPTION "ebp", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
|
||||
#else
|
||||
#define _SEH3$_CLOBBER_ON_EXCEPTION "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
|
||||
#endif
|
||||
|
||||
/* This construct scares GCC so much, that it will stop moving code
|
||||
around into places that are never executed. */
|
||||
#define _SEH3$_SCARE_GCC() \
|
||||
void *plabel; \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_BeforeTry); \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_HandlerTarget); \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
|
||||
asm volatile ("#" : "=a"(plabel) : "p"(&&_SEH3$_l_BeforeTry), "p"(&&_SEH3$_l_HandlerTarget), "p"(&&_SEH3$_l_OnException) \
|
||||
: _SEH3$_CLOBBER_ON_EXCEPTION ); \
|
||||
goto _SEH3$_l_OnException;
|
||||
|
||||
#endif /* __clang__ */
|
||||
|
||||
/* Neither CLANG nor C++ support nested functions */
|
||||
#if defined(__cplusplus) || defined(__clang__)
|
||||
|
||||
/* Use the global unregister function */
|
||||
void
|
||||
__attribute__((regparm(1)))
|
||||
_SEH3$_Unregister(
|
||||
volatile SEH3$_REGISTRATION_FRAME *Frame);
|
||||
|
||||
/* These are only dummies here */
|
||||
#define _SEH3$_DECLARE_CLEANUP_FUNC(_Name)
|
||||
#define _SEH3$_DEFINE_CLEANUP_FUNC(_Name)
|
||||
#define _SEH3$_DECLARE_FILTER_FUNC(_Name)
|
||||
#define _SEH3$_DEFINE_DUMMY_FINALLY(_Name)
|
||||
|
||||
#else /* __cplusplus || __clang__ */
|
||||
|
||||
#define _SEH3$_DECLARE_EXCEPT_INTRINSICS() \
|
||||
inline __attribute__((always_inline, gnu_inline)) \
|
||||
unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; }
|
||||
|
||||
|
||||
/* On GCC the filter function is a nested function with __fastcall calling
|
||||
convention. The eax register contains a base address the function uses
|
||||
to address the callers stack frame. __fastcall is chosen, because it gives
|
||||
|
@ -219,25 +256,8 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
|||
_SEH3$_FinallyFunction(1); \
|
||||
}
|
||||
|
||||
/* Define the registers that get clobbered, when reaching the __except block.
|
||||
We specify ebp on optimized builds without frame pointer, since it will be
|
||||
used by GCC as a general purpose register then. */
|
||||
#if defined(__OPTIMIZE__) && defined(_ALLOW_OMIT_FRAME_POINTER)
|
||||
#define _SEH3$_CLOBBER_ON_EXCEPTION "ebp", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
|
||||
#else
|
||||
#define _SEH3$_CLOBBER_ON_EXCEPTION "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
|
||||
#endif
|
||||
#endif /* __cplusplus || __clang__ */
|
||||
|
||||
/* This construct scares GCC so much, that it will stop moving code
|
||||
around into places that are never executed. */
|
||||
#define _SEH3$_SCARE_GCC() \
|
||||
void *plabel; \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_BeforeTry); \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_HandlerTarget); \
|
||||
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
|
||||
asm volatile ("#" : "=a"(plabel) : "p"(&&_SEH3$_l_BeforeTry), "p"(&&_SEH3$_l_HandlerTarget), "p"(&&_SEH3$_l_OnException) \
|
||||
: _SEH3$_CLOBBER_ON_EXCEPTION ); \
|
||||
goto _SEH3$_l_OnException;
|
||||
|
||||
|
||||
#define _SEH3_TRY \
|
||||
|
@ -259,7 +279,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
|||
}; \
|
||||
\
|
||||
/* Forward declaration of the auto cleanup function */ \
|
||||
_SEH3$_DECLARE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
|
||||
_SEH3$_DECLARE_CLEANUP_FUNC(_SEH3$_Unregister); \
|
||||
\
|
||||
/* Allocate a registration frame */ \
|
||||
volatile SEH3$_REGISTRATION_FRAME _SEH3$_AUTO_CLEANUP _SEH3$_TrylevelFrame; \
|
||||
|
@ -355,7 +375,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
|||
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
|
||||
\
|
||||
/* Implementation of the auto cleanup function */ \
|
||||
_SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
|
||||
_SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_Unregister); \
|
||||
\
|
||||
/* Close the outer scope */ \
|
||||
} while (0);
|
||||
|
|
|
@ -50,8 +50,9 @@ C_ASSERT(SEH3_REGISTRATION_FRAME_Ebp == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, E
|
|||
C_ASSERT(SEH3_SCOPE_TABLE_Filter == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Filter));
|
||||
C_ASSERT(SEH3_SCOPE_TABLE_Target == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Target));
|
||||
|
||||
static inline
|
||||
void _SEH3$_Unregister(
|
||||
void
|
||||
__attribute__((regparm(1)))
|
||||
_SEH3$_Unregister(
|
||||
volatile SEH3$_REGISTRATION_FRAME *Frame)
|
||||
{
|
||||
if (Frame->Handler)
|
||||
|
|
Loading…
Reference in a new issue