[PSEH3]
[reactos.git] / reactos / include / reactos / libs / pseh / pseh3.h
index ef255a9..457d7d9 100644 (file)
@@ -64,6 +64,9 @@ typedef struct _SEH3$_REGISTRATION_FRAME
     /* Except handler stores pointer to exception pointers here */
     PSEH3$_EXCEPTION_POINTERS volatile ExceptionPointers;
 
+    /* Except handle stores the exception code here */
+    unsigned long ExceptionCode;
+
     /* Registers that we need to save */
     unsigned long Esp;
     unsigned long Ebp;
@@ -113,15 +116,6 @@ void * __cdecl __attribute__((error("Can only be used inside an exception filter
 /* This attribute allows automatic cleanup of the registered frames */
 #define _SEH3$_AUTO_CLEANUP __attribute__((cleanup(_SEH3$_AutoCleanup)))
 
-/* CLANG specific definitions! */
-#ifdef __clang__
-
-/* CLANG thinks it is smart and optimizes the alloca away if it is 0 and with it the use of a frame register */
-#define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(4)) : "%esp", "memory")
-
-/* CLANG doesn't have asm goto! */
-#define _SEH3$_ASM_GOTO(_Label, ...)
-
 int
 __attribute__((regparm(3)))
 __attribute__((returns_twice))
@@ -130,6 +124,23 @@ _SEH3$_RegisterFrameWithNonVolatiles(
     const SEH3$_SCOPE_TABLE* ScopeTable,
     void* AllocaFrame);
 
+int
+__attribute__((regparm(3)))
+__attribute__((returns_twice))
+_SEH3$_RegisterTryLevelWithNonVolatiles(
+    volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame,
+    const SEH3$_SCOPE_TABLE* ScopeTable,
+    void* AllocaFrame);
+
+/* CLANG specific definitions! */
+#ifdef __clang__
+
+/* CLANG thinks it is smart and optimizes the alloca away if it is 0 and with it the use of a frame register */
+#define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(4)) : "%esp", "memory")
+
+/* CLANG doesn't have asm goto! */
+#define _SEH3$_ASM_GOTO(...)
+
 #define _SEH3$_RegisterFrame_(_TrylevelFrame, _DataTable) \
     do { \
         int result = _SEH3$_RegisterFrameWithNonVolatiles(_TrylevelFrame, _DataTable, __builtin_alloca(0)); \
@@ -141,14 +152,6 @@ _SEH3$_RegisterFrameWithNonVolatiles(
         } \
     } while(0)
 
-int
-__attribute__((regparm(3)))
-__attribute__((returns_twice))
-_SEH3$_RegisterTryLevelWithNonVolatiles(
-    volatile SEH3$_REGISTRATION_FRAME* RegistrationFrame,
-    const SEH3$_SCOPE_TABLE* ScopeTable,
-    void* AllocaFrame);
-
 #define _SEH3$_RegisterTryLevel_(_TrylevelFrame, _DataTable) \
     do { \
         int result = _SEH3$_RegisterTryLevelWithNonVolatiles(_TrylevelFrame, _DataTable, __builtin_alloca(0)); \
@@ -167,27 +170,27 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
 /* This will make GCC use ebp, even if it was disabled by -fomit-frame-pointer */
 #define _SEH3$_EnforceFramePointer() asm volatile ("#\n" : : "m"(*(char*)__builtin_alloca(0)) : "%esp", "memory")
 
-#define _SEH3$_ASM_GOTO(_Label, ...) asm goto ("#\n" : : : "memory", ## __VA_ARGS__ : _Label)
+#define _SEH3$_ASM_GOTO(...) asm goto ("#\n" : : : "memory" : __VA_ARGS__)
 
 #ifdef __cplusplus
 #define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \
-    asm goto ("leal %0, %%eax\n" \
-              "leal %1, %%edx\n" \
-              "call " #_Function "WithStackLayout\n" \
+    asm goto ("leal %0, %%eax\n\t" \
+              "leal %1, %%edx\n\t" \
+              "call " #_Function "WithStackLayout" \
               : \
-              : "m" (*(_TrylevelFrame)), "m" (*(_DataTable)), "c"(__builtin_alloca(0)) \
+              : "m" (*(_TrylevelFrame)), "m" (*(_DataTable)), "c" (__builtin_alloca(0)), "p" (_SEH3$_RegisterFrameWithNonVolatiles) \
               : "eax", "edx", "memory" \
-              : _SEH3$_l_HandlerTarget, _SEH3$_l_FilterOrFinally)
+              : _SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally)
 
 #else
 #define _SEH3$_CALL_WRAPPER(_Function, _TrylevelFrame, _DataTable) \
-    asm goto ("leal %0, %%eax\n" \
-              "leal %1, %%edx\n" \
-              "call " #_Function "\n" \
+    asm goto ("leal %0, %%eax\n\t" \
+              "leal %1, %%edx\n\t" \
+              "call " #_Function \
               : \
-              : "m" (*(_TrylevelFrame)), "m" (*(_DataTable)) \
+              : "m" (*(_TrylevelFrame)), "m" (*(_DataTable)), "p" (_SEH3$_RegisterFrameWithNonVolatiles) \
               : "eax", "edx", "ecx", "memory" \
-              : _SEH3$_l_HandlerTarget)
+              : _SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally)
 #endif
 
 /* This is an asm wrapper around _SEH3$_RegisterFrame */
@@ -202,10 +205,8 @@ _SEH3$_RegisterTryLevelWithNonVolatiles(
    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$_ASM_GOTO(_SEH3$_l_BeforeTry, _SEH3$_l_HandlerTarget, _SEH3$_l_OnException, _SEH3$_l_BeforeFilterOrFinally, _SEH3$_l_FilterOrFinally); \
+        asm volatile ("#" : "=a"(plabel) : "p"(&&_SEH3$_l_BeforeTry), "p"(&&_SEH3$_l_HandlerTarget), "p"(&&_SEH3$_l_OnException), "p"(&&_SEH3$_l_FilterOrFinally) \
                       : "ebx", "ecx", "edx", "esi", "edi", "flags", "memory" ); \
         goto _SEH3$_l_OnException;
 
@@ -229,8 +230,8 @@ _SEH3$_AutoCleanup(
 /* On invocation, the AllocaFrame field is loaded with the return esp value */
 #define _SEH3$_NESTED_FUNC_RETURN(_Result) \
         /* Restore esp and return to the caller */ \
-        asm volatile ("movl %[FixedEsp], %%esp\nret\n" \
-            : : "a"(_Result), [FixedEsp]"m"(_SEH3$_TrylevelFrame.AllocaFrame) : "ebx", "ecx", "edx", "esi", "edi", "flags", "memory")
+        asm volatile ("movl %[FixedEsp], %%esp\n\tret" \
+            : : "a" (_Result), [FixedEsp] "m" (_SEH3$_TrylevelFrame.AllocaFrame) : "ebx", "ecx", "edx", "esi", "edi", "flags", "memory")
 
 /* The filter "function" */
 #define _SEH3$_DEFINE_FILTER_FUNC(_Name, expression) \
@@ -254,14 +255,14 @@ _SEH3$_AutoCleanup(
 
 /* Since we cannot use nested functions, we declare these globally as macros */
 #define _abnormal_termination() (_SEH3$_TrylevelFrame.ExceptionPointers != 0)
-#define _exception_code() (_SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode)
+#define _exception_code() (_SEH3$_TrylevelFrame.ExceptionCode)
 #define _exception_info() (_SEH3$_TrylevelFrame.ExceptionPointers)
 
 #else /* __cplusplus || __clang__ */
 
 #define _SEH3$_DECLARE_EXCEPT_INTRINSICS() \
     inline __attribute__((always_inline, gnu_inline)) \
-    unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; }
+    unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionCode; }
 
 /* On GCC the filter function is a nested function with __fastcall calling
    convention. The eax register contains a base address the function uses
@@ -283,10 +284,13 @@ _SEH3$_AutoCleanup(
 #define _SEH3$_DEFINE_FILTER_FUNC(_Name, expression) \
     _SEH3$_NESTED_FUNC_OPEN(_Name) \
         /* Declare the intrinsics for exception filters */ \
+_Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wshadow\"") \
         inline __attribute__((always_inline, gnu_inline)) \
-        unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionPointers->ExceptionRecord->ExceptionCode; } \
+        unsigned long _exception_code() { return _SEH3$_TrylevelFrame.ExceptionCode; } \
         inline __attribute__((always_inline, gnu_inline)) \
         void * _exception_info() { return _SEH3$_TrylevelFrame.ExceptionPointers; } \
+_Pragma("GCC diagnostic pop") \
 \
         /* Now handle the actual filter expression */ \
         return (expression); \
@@ -346,8 +350,8 @@ _SEH3$_AutoCleanup(
         (void)&&_SEH3$_l_BeforeFilterOrFinally; \
         (void)&&_SEH3$_l_FilterOrFinally; \
 \
-_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
 _Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
 \
         /* Count the try level. Outside of any __try, _SEH3$_TryLevel is 0 */ \
         enum { \
@@ -379,16 +383,14 @@ _Pragma("GCC diagnostic pop") \
     _SEH3$_l_BeforeTry: (void)0; \
         _SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
 \
-_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
 _Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
 \
         /* Forward declaration of the filter function */ \
         _SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FilterFunction); \
 \
         /* Create a static data table that contains the jump target and filter function */ \
         static const SEH3$_SCOPE_TABLE _SEH3$_ScopeTable = { &&_SEH3$_l_HandlerTarget, _SEH3$_FILTER(&_SEH3$_FilterFunction, (__VA_ARGS__)), _SEH3$_TryLevel, _SEH3$_HANDLER_TYPE }; \
-\
-_Pragma("GCC diagnostic pop") \
 \
         /* Register the registration record. */ \
         if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \
@@ -396,14 +398,9 @@ _Pragma("GCC diagnostic pop") \
 \
         /* Define an empty inline finally function */ \
         _SEH3$_DEFINE_DUMMY_FINALLY(_SEH3$_FinallyFunction) \
-\
-_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
-_Pragma("GCC diagnostic push") \
 \
         /* Allow intrinsics for __except to be used */ \
         _SEH3$_DECLARE_EXCEPT_INTRINSICS(); \
-\
-_Pragma("GCC diagnostic pop") \
 \
         goto _SEH3$_l_DoTry; \
 \
@@ -437,16 +434,14 @@ _Pragma("GCC diagnostic pop") \
     _SEH3$_l_BeforeTry: (void)0; \
         _SEH3$_ASM_GOTO(_SEH3$_l_OnException); \
 \
-_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
 _Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
 \
         /* Forward declaration of the finally function */ \
         _SEH3$_DECLARE_FILTER_FUNC(_SEH3$_FinallyFunction); \
 \
         /* Create a static data table that contains the finally function */ \
         static const SEH3$_SCOPE_TABLE _SEH3$_ScopeTable = { 0, _SEH3$_FINALLY(&_SEH3$_FinallyFunction), _SEH3$_TryLevel, _SEH3$_HANDLER_TYPE }; \
-\
-_Pragma("GCC diagnostic pop") \
 \
         /* Register the registration record. */ \
         if (_SEH3$_TryLevel == 1) _SEH3$_RegisterFrame_(&_SEH3$_TrylevelFrame, &_SEH3$_ScopeTable); \
@@ -478,6 +473,8 @@ _Pragma("GCC diagnostic pop") \
 \
         /* Implementation of the auto cleanup function */ \
         _SEH3$_DEFINE_CLEANUP_FUNC(_SEH3$_AutoCleanup); \
+\
+_Pragma("GCC diagnostic pop") \
 \
     /* Close the outer scope */ \
     } while (0);