mirror of
https://github.com/reactos/reactos.git
synced 2025-06-27 18:00:49 +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);
|
void * __cdecl __attribute__((error("Can only be used inside an exception filter."))) _exception_info(void);
|
||||||
|
|
||||||
/* This attribute allows automatic cleanup of the registered frames */
|
/* 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! */
|
/* CLANG specific definitions! */
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
|
@ -133,6 +133,8 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
#define _SEH3$_SCARE_GCC()
|
||||||
|
|
||||||
#else /* !__clang__ */
|
#else /* !__clang__ */
|
||||||
|
|
||||||
#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label)
|
#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label)
|
||||||
|
@ -155,14 +157,49 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
||||||
: "ecx", "edx", "memory" \
|
: "ecx", "edx", "memory" \
|
||||||
: _SEH3$_l_HandlerTarget)
|
: _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__ */
|
#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() \
|
#define _SEH3$_DECLARE_EXCEPT_INTRINSICS() \
|
||||||
inline __attribute__((always_inline, gnu_inline)) \
|
inline __attribute__((always_inline, gnu_inline)) \
|
||||||
unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; }
|
unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; }
|
||||||
|
|
||||||
|
|
||||||
/* On GCC the filter function is a nested function with __fastcall calling
|
/* On GCC the filter function is a nested function with __fastcall calling
|
||||||
convention. The eax register contains a base address the function uses
|
convention. The eax register contains a base address the function uses
|
||||||
to address the callers stack frame. __fastcall is chosen, because it gives
|
to address the callers stack frame. __fastcall is chosen, because it gives
|
||||||
|
@ -219,25 +256,8 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
||||||
_SEH3$_FinallyFunction(1); \
|
_SEH3$_FinallyFunction(1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define the registers that get clobbered, when reaching the __except block.
|
#endif /* __cplusplus || __clang__ */
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
#define _SEH3_TRY \
|
#define _SEH3_TRY \
|
||||||
|
@ -259,7 +279,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
/* Forward declaration of the auto cleanup function */ \
|
/* Forward declaration of the auto cleanup function */ \
|
||||||
_SEH3$_DECLARE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
|
_SEH3$_DECLARE_CLEANUP_FUNC(_SEH3$_Unregister); \
|
||||||
\
|
\
|
||||||
/* Allocate a registration frame */ \
|
/* Allocate a registration frame */ \
|
||||||
volatile SEH3$_REGISTRATION_FRAME _SEH3$_AUTO_CLEANUP _SEH3$_TrylevelFrame; \
|
volatile SEH3$_REGISTRATION_FRAME _SEH3$_AUTO_CLEANUP _SEH3$_TrylevelFrame; \
|
||||||
|
@ -355,7 +375,7 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
|
||||||
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
|
_SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
|
||||||
\
|
\
|
||||||
/* Implementation of the auto cleanup function */ \
|
/* Implementation of the auto cleanup function */ \
|
||||||
_SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
|
_SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_Unregister); \
|
||||||
\
|
\
|
||||||
/* Close the outer scope */ \
|
/* Close the outer scope */ \
|
||||||
} while (0);
|
} 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_Filter == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Filter));
|
||||||
C_ASSERT(SEH3_SCOPE_TABLE_Target == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Target));
|
C_ASSERT(SEH3_SCOPE_TABLE_Target == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Target));
|
||||||
|
|
||||||
static inline
|
void
|
||||||
void _SEH3$_Unregister(
|
__attribute__((regparm(1)))
|
||||||
|
_SEH3$_Unregister(
|
||||||
volatile SEH3$_REGISTRATION_FRAME *Frame)
|
volatile SEH3$_REGISTRATION_FRAME *Frame)
|
||||||
{
|
{
|
||||||
if (Frame->Handler)
|
if (Frame->Handler)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue