Author: tkreuzer Date: Sun Mar 2 20:54:04 2014 New Revision: 62393
URL: http://svn.reactos.org/svn/reactos?rev=62393&view=rev Log: [PSEH3] - Switch parameters in _SEH3$_RegisterFrame and _SEH3$_RegisterTryLevel (just for consistency) - rename _SEH3$_RegisterTryLevel macro to _SEH3$_RegisterTryLevel_ - Add TryLevel and HandlerType fields to the scope table, since we'll need these later - Start factoring out some Clang specific macros
Modified: trunk/reactos/include/reactos/libs/pseh/pseh3.h trunk/reactos/lib/pseh/i386/pseh3_i386.S
Modified: trunk/reactos/include/reactos/libs/pseh/pseh3.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/pseh/p... ============================================================================== --- trunk/reactos/include/reactos/libs/pseh/pseh3.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/libs/pseh/pseh3.h [iso-8859-1] Sun Mar 2 20:54:04 2014 @@ -21,6 +21,8 @@ { void *Target; void *Filter; + unsigned char TryLevel; + unsigned char HandlerType; } SEH3$_SCOPE_TABLE, *PSEH3$_SCOPE_TABLE;
typedef struct _SEH3$_EXCEPTION_POINTERS @@ -57,6 +59,7 @@ /* Prevent gcc from inlining functions that use SEH. */ static inline __attribute__((always_inline)) __attribute__((returns_twice)) void _SEH3$_PreventInlining() {}
+/* Unregister the root frame */ extern inline __attribute__((always_inline,gnu_inline)) void _SEH3$_UnregisterFrame(volatile SEH3$_REGISTRATION_FRAME *RegistrationFrame) { @@ -64,6 +67,7 @@ : : [NewHead] "ir" (RegistrationFrame->Next) : "memory"); }
+/* Unregister a trylevel frame */ extern inline __attribute__((always_inline,gnu_inline)) void _SEH3$_UnregisterTryLevel( volatile SEH3$_REGISTRATION_FRAME *TrylevelFrame) @@ -84,41 +88,80 @@ unsigned long __cdecl __attribute__((error("Can only be used inside an exception filter or __except block."))) _exception_code(void); void * __cdecl __attribute__((error("Can only be used inside an exception filter."))) _exception_info(void);
-/* 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 attribute allows automatic cleanup of the registered frames */ #define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_AutoCleanup)))
-#define _SEH3$_ASM_GOTO(_Asm, _Label, ...) asm goto (_Asm : : : "memory", ## __VA_ARGS__ : _Label) +/* CLANG specific definitions! */ +#ifdef __clang__ + +/* CLANG doesn't have asm goto! */ +#define _SEH3$_ASM_GOTO(_Label, ...) + +int +__attribute__((regparm(2))) +__attribute__((returns_twice)) +_SEH3$_RegisterFrameWithNonVolatiles( + volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame, + const SEH3$_SCOPE_TABLE* ScopeTable); + +#define _SEH3$_RegisterFrame_(_TrylevelFrame, _DataTable) \ + do { \ + int result = _SEH3$_RegisterFrameWithNonVolatiles(_TrylevelFrame, _DataTable); \ + if (__builtin_expect(result != 0, 0)) \ + { \ + if (result == 1) goto _SEH3$_l_FilterOrFinally; \ + if (result == 2) goto _SEH3$_l_HandlerTarget; \ + goto _SEH3$_l_BeforeFilterOrFinally; \ + } \ + } while(0) + +int +__attribute__((regparm(2))) +__attribute__((returns_twice)) +_SEH3$_RegisterTryLevelWithNonVolatiles( + volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame, + const SEH3$_SCOPE_TABLE* ScopeTable); + +#define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \ + do { \ + int result = _SEH3$_RegisterTryLevelWithNonVolatiles(_TrylevelFrame, _DataTable); \ + if (__builtin_expect(result != 0, 0)) \ + { \ + if (result == 1) goto _SEH3$_l_FilterOrFinally; \ + if (result == 2) goto _SEH3$_l_HandlerTarget; \ + goto _SEH3$_l_BeforeFilterOrFinally; \ + } \ + } while(0) + +#else /* !__clang__ */ + +#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label) + +/* This is an asm wrapper around _SEH3$_RegisterFrame */ +#define _SEH3$_RegisterFrame_(_TrylevelFrame, _DataTable) \ + asm goto ("leal %1, %%edx\n" \ + "call __SEH3$_RegisterFrame\n" \ + : \ + : "a" (_TrylevelFrame), "m" (*(_DataTable)) \ + : "ecx", "edx", "memory" \ + : _SEH3$_l_HandlerTarget) + +/* This is an asm wrapper around _SEH3$_RegisterTryLevel */ +#define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \ + asm goto ("leal %1, %%edx\n" \ + "call __SEH3$_RegisterTryLevel\n" \ + : \ + : "a" (_TrylevelFrame), "m" (*(_DataTable)) \ + : "ecx", "edx", "memory" \ + : _SEH3$_l_HandlerTarget) + +#endif /* __clang__ */ +
#define _SEH3$_DECLARE_EXCEPT_INTRINSICS() \ inline __attribute__((always_inline, gnu_inline)) \ unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; }
-/* This is an asm wrapper around _SEH3$_RegisterFrame */ -#define _SEH3$_RegisterFrame(_TrylevelFrame, _DataTable, _Target) \ - asm goto ("leal %0, %%edx\n" \ - "call __SEH3$_RegisterFrame\n" \ - : \ - : "m" (*(_TrylevelFrame)), "a" (_DataTable) \ - : "ecx", "edx", "memory" \ - : _Target) - -/* This is an asm wrapper around _SEH3$_EnterTryLevel */ -#define _SEH3$_RegisterTryLevel(_TrylevelFrame, _DataTable, _Target) \ - asm goto ("leal %0, %%edx\n" \ - "call __SEH3$_RegisterTryLevel\n" \ - : \ - : "m" (*(_TrylevelFrame)), "a" (_DataTable) \ - : "ecx", "edx", "memory" \ - : _Target)
/* On GCC the filter function is a nested function with __fastcall calling convention. The eax register contains a base address the function uses @@ -176,13 +219,22 @@ _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 + /* 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("#\n", _SEH3$_l_BeforeTry); \ - _SEH3$_ASM_GOTO("#\n", _SEH3$_l_HandlerTarget); \ - _SEH3$_ASM_GOTO("#\n", _SEH3$_l_OnException); \ + _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; @@ -226,7 +278,7 @@ goto _SEH3$_l_EndTry; \ \ _SEH3$_l_BeforeTry: (void)0; \ - _SEH3$_ASM_GOTO("#\n", _SEH3$_l_OnException); \ + _SEH3$_ASM_GOTO(_SEH3$_l_OnException); \ \ /* Forward declaration of the filter function */ \ _SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FilterFunction); \ @@ -235,8 +287,8 @@ static const SEH3$_SCOPE_TABLE _SEH3$_ScopeTable = { &&_SEH3$_l_HandlerTarget, _SEH3$_FILTER(&_SEH3$_FilterFunction, (__VA_ARGS__)) }; \ \ /* Register the registration record. */ \ - if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable, _SEH3$_l_HandlerTarget); \ - else _SEH3$_RegisterTryLevel(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable, _SEH3$_l_HandlerTarget); \ + if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \ + else _SEH3$_RegisterTryLevel_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \ \ /* Emit the filter function */ \ _SEH3$_DEFINE_FILTER_FUNC(_SEH3$_FilterFunction, (__VA_ARGS__)) \ @@ -268,7 +320,7 @@ goto _SEH3$_l_EndTry; \ \ _SEH3$_l_BeforeTry: (void)0; \ - _SEH3$_ASM_GOTO("#\n", _SEH3$_l_OnException); \ + _SEH3$_ASM_GOTO(_SEH3$_l_OnException); \ \ /* Forward declaration of the finally function */ \ _SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FinallyFunction); \ @@ -277,8 +329,8 @@ static const SEH3$_SCOPE_TABLE _SEH3$_ScopeTable = { 0, &_SEH3$_FinallyFunction }; \ \ /* Register the registration record. */ \ - if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable, _SEH3$_l_HandlerTarget); \ - else _SEH3$_RegisterTryLevel(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable, _SEH3$_l_HandlerTarget); \ + if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \ + else _SEH3$_RegisterTryLevel_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \ \ goto _SEH3$_l_DoTry; \ \ @@ -300,7 +352,7 @@ _SEH3$_SCARE_GCC() \ \ _SEH3$_l_EndTry:(void)0; \ - _SEH3$_ASM_GOTO("#\n", _SEH3$_l_OnException); \ + _SEH3$_ASM_GOTO(_SEH3$_l_OnException); \ \ /* Implementation of the auto cleanup function */ \ _SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
Modified: trunk/reactos/lib/pseh/i386/pseh3_i386.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/pseh/i386/pseh3_i386.S?... ============================================================================== --- trunk/reactos/lib/pseh/i386/pseh3_i386.S [iso-8859-1] (original) +++ trunk/reactos/lib/pseh/i386/pseh3_i386.S [iso-8859-1] Sun Mar 2 20:54:04 2014 @@ -18,37 +18,37 @@ * __attribute__((regparm(2))) * __attribute__((returns_twice)) * _SEH3$_RegisterFrame[WithNonVolatiles]( - * PSEH_DATA_TABLE DataTable<eax>, - * PSEH_REGISTRATION_FRAME RegistrationRecord<edx>); + * PSEH3$_REGISTRATION_FRAME RegistrationFrame<eax>, + * PSEH3$_SCOPE_TABLE ScopeTable<edx>); */ .global __SEH3$_RegisterFrameWithNonVolatiles __SEH3$_RegisterFrameWithNonVolatiles:
/* Save non-volatiles in the registration frame */ - mov [edx + SEH3_REGISTRATION_FRAME_Ebx], ebx - mov [edx + SEH3_REGISTRATION_FRAME_Esi], esi - mov [edx + SEH3_REGISTRATION_FRAME_Edi], edi + mov [eax + SEH3_REGISTRATION_FRAME_Ebx], ebx + mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi + mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
.global __SEH3$_RegisterFrame __SEH3$_RegisterFrame:
/* Save the address of the static data table */ - mov [edx + SEH3_REGISTRATION_FRAME_ScopeTable], eax + mov [eax + SEH3_REGISTRATION_FRAME_ScopeTable], edx
/* Set the handler address */ - mov dword ptr [edx + SEH3_REGISTRATION_FRAME_Handler], offset __SEH3$_except_handler + mov dword ptr [eax + SEH3_REGISTRATION_FRAME_Handler], offset __SEH3$_except_handler
/* Set this as the end of the internal chain */ - mov dword ptr [edx + SEH3_REGISTRATION_FRAME_EndOfChain], edx + mov dword ptr [eax + SEH3_REGISTRATION_FRAME_EndOfChain], eax
/* Register the frame in the TEB */ - mov eax, dword ptr fs:[0] - mov [edx + SEH3_REGISTRATION_FRAME_Next], eax - mov dword ptr fs:[0], edx + mov edx, dword ptr fs:[0] + mov [eax + SEH3_REGISTRATION_FRAME_Next], edx + mov dword ptr fs:[0], eax
/* Save the stack registers */ - mov [edx + SEH3_REGISTRATION_FRAME_Esp], esp - mov [edx + SEH3_REGISTRATION_FRAME_Ebp], ebp + mov [eax + SEH3_REGISTRATION_FRAME_Esp], esp + mov [eax + SEH3_REGISTRATION_FRAME_Ebp], ebp
/* Set eax to 0 to indicate 1st return */ xor eax, eax @@ -60,39 +60,39 @@ * __attribute__((regparm(2))) * __attribute__((returns_twice)) * _SEH3$_RegisterTryLevel[WithNonVolatiles]( - * PSEH_DATA_TABLE DataTable<eax>, - * PSEH_REGISTRATION_FRAME RegistrationRecord<edx>); + * PSEH3$_REGISTRATION_FRAME RegistrationFrame<edx>, + * PSEH3$_SCOPE_TABLE ScopeTable<eax>); */ .global __SEH3$_RegisterTryLevelWithNonVolatiles __SEH3$_RegisterTryLevelWithNonVolatiles:
/* Save non-volatiles in the registration frame */ - mov [edx + SEH3_REGISTRATION_FRAME_Ebx], ebx - mov [edx + SEH3_REGISTRATION_FRAME_Esi], esi - mov [edx + SEH3_REGISTRATION_FRAME_Edi], edi + mov [eax + SEH3_REGISTRATION_FRAME_Ebx], ebx + mov [eax + SEH3_REGISTRATION_FRAME_Esi], esi + mov [eax + SEH3_REGISTRATION_FRAME_Edi], edi
.global __SEH3$_RegisterTryLevel __SEH3$_RegisterTryLevel:
/* Save the address of the static data table */ - mov [edx + SEH3_REGISTRATION_FRAME_ScopeTable], eax + mov [eax + SEH3_REGISTRATION_FRAME_ScopeTable], edx
/* Set the handler address to NULL as identification */ - and dword ptr [edx + SEH3_REGISTRATION_FRAME_Handler], 0 + and dword ptr [eax + SEH3_REGISTRATION_FRAME_Handler], 0
/* Get the current registered frame */ - mov eax, dword ptr fs:[0] + mov edx, dword ptr fs:[0]
/* Get the current end of the chain and set this as Next */ - mov ecx, [eax + SEH3_REGISTRATION_FRAME_EndOfChain] - mov [edx + SEH3_REGISTRATION_FRAME_Next], ecx + mov ecx, [edx + SEH3_REGISTRATION_FRAME_EndOfChain] + mov [eax + SEH3_REGISTRATION_FRAME_Next], ecx
/* Set this as the end of the internal chain */ - mov dword ptr [eax + SEH3_REGISTRATION_FRAME_EndOfChain], edx + mov dword ptr [edx + SEH3_REGISTRATION_FRAME_EndOfChain], eax
/* Save the stack registers */ - mov [edx + SEH3_REGISTRATION_FRAME_Esp], esp - mov [edx + SEH3_REGISTRATION_FRAME_Ebp], ebp + mov [eax + SEH3_REGISTRATION_FRAME_Esp], esp + mov [eax + SEH3_REGISTRATION_FRAME_Ebp], ebp
/* Set eax to 0 to indicate 1st return */ xor eax, eax