ReactOS 0.4.16-dev-290-g89a3b8f
pseh2.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2008 KJK::Hyperion
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 DEALINGS IN THE SOFTWARE.
21*/
22
23#ifndef KJK_PSEH2_H_
24#define KJK_PSEH2_H_
25
26#if defined(_USE_NATIVE_SEH) || (defined(_MSC_VER) && !(defined(__clang__) && defined(_M_AMD64)))
27
28#include <excpt.h>
29#define _SEH2_TRY __try
30#define _SEH2_FINALLY __finally
31#define _SEH2_EXCEPT(...) __except(__VA_ARGS__)
32#define _SEH2_END
33#define _SEH2_GetExceptionInformation() (GetExceptionInformation())
34#define _SEH2_GetExceptionCode() (GetExceptionCode())
35#define _SEH2_AbnormalTermination() (AbnormalTermination())
36#define _SEH2_YIELD(STMT_) STMT_
37#define _SEH2_LEAVE __leave
38#define _SEH2_VOLATILE
39
40#elif defined(__GNUC__) && !defined(__clang__) && defined(_M_AMD64)
41
42#include "pseh2_64.h"
43
44#elif defined(_USE_DUMMY_PSEH) || defined (__arm__) || defined(_M_AMD64)
45
46#ifdef __cplusplus
47extern"C"
48{
49#endif
50extern int _SEH2_Volatile0;
52#ifdef __cplusplus
53} // extern "C"
54#endif
55
56#define _SEH2_TRY \
57_Pragma("GCC diagnostic push") \
58_Pragma("GCC diagnostic ignored \"-Wunused-label\"")\
59{ \
60 __label__ __seh2_scope_end__;
61
62#define _SEH2_FINALLY \
63 __seh2_scope_end__:; \
64 } \
65 if (1) \
66 { \
67 __label__ __seh2_scope_end__;
68
69#define _SEH2_EXCEPT(...) \
70 __seh2_scope_end__:; \
71 } \
72 if (_SEH2_Volatile0 || (0 && (__VA_ARGS__))) \
73 { \
74 __label__ __seh2_scope_end__;
75
76#define _SEH2_END \
77 __seh2_scope_end__:; \
78 } \
79_Pragma("GCC diagnostic pop")
80
81#define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)0)
82#define _SEH2_GetExceptionCode() _SEH2_VolatileExceptionCode
83#define _SEH2_AbnormalTermination() (0)
84#define _SEH2_YIELD(STMT_) STMT_
85#define _SEH2_LEAVE goto __seh2_scope_end__;
86#define _SEH2_VOLATILE volatile
87
88#elif defined(_USE_PSEH3)
89
90#include "pseh3.h"
91
92/* Compatibility macros */
93#define _SEH2_TRY _SEH3_TRY
94#define _SEH2_EXCEPT _SEH3_EXCEPT
95#define _SEH2_FINALLY _SEH3_FINALLY
96#define _SEH2_END _SEH3_END
97#define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)_exception_info())
98#define _SEH2_GetExceptionCode _exception_code
99#define _SEH2_AbnormalTermination _abnormal_termination
100#define _SEH2_LEAVE _SEH3_LEAVE
101#define _SEH2_YIELD(x) x
102#define _SEH2_VOLATILE volatile
103
104#elif defined(__GNUC__)
105
106struct _EXCEPTION_RECORD;
108struct _CONTEXT;
109
110typedef int (__cdecl * _SEH2FrameHandler_t)
111(
112 struct _EXCEPTION_RECORD *,
113 void *,
114 struct _CONTEXT *,
115 void *
116);
117
118typedef struct __SEH2Registration
119{
120 struct __SEH2Registration * SER_Prev;
121 _SEH2FrameHandler_t SER_Handler;
122}
123_SEH2Registration_t;
124
125typedef struct __SEH2Frame
126{
127 _SEH2Registration_t SF_Registration;
128 volatile struct __SEH2TryLevel * volatile SF_TopTryLevel;
129 volatile unsigned long SF_Code;
130}
131_SEH2Frame_t;
132
133typedef struct __SEH2TryLevel
134{
135 volatile struct __SEH2TryLevel * ST_Next;
136 void * ST_Filter;
137 void * ST_Body;
138}
139_SEH2TryLevel_t;
140
141typedef struct __SEH2HandleTryLevel
142{
143 _SEH2TryLevel_t SHT_Common;
144 void * volatile SHT_Esp;
145 void * volatile SHT_Ebp;
146 void * volatile SHT_Ebx;
147 void * volatile SHT_Esi;
148 void * volatile SHT_Edi;
149}
150_SEH2HandleTryLevel_t;
151
152#ifdef __cplusplus
153extern "C" {
154#endif
155
156extern int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
157extern __attribute__((returns_twice)) int __cdecl _SEH2EnterFrameAndHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
158extern __attribute__((returns_twice)) int __cdecl _SEH2EnterHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
159extern void __cdecl _SEH2LeaveFrame(void);
160extern void __cdecl _SEH2Return(void);
161
162#ifdef __cplusplus
163}
164#endif
165
166/* Prevent gcc from inlining functions that use SEH. */
167#if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7))
168static inline __attribute__((always_inline)) __attribute__((returns_twice)) void _SEH_DontInline() {}
169#define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() _SEH_DontInline();
170#else
171#define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS()
172#endif
173
174/* A no-op side effect that scares GCC */
175#define __SEH_SIDE_EFFECT __asm__ __volatile__("#")
176
177/* A no-op without any real side effects, but silences warnings */
178#define __SEH_PRETEND_SIDE_EFFECT (void)0
179
180/* Forces GCC to consider the specified label reachable */
181#define __SEH_USE_LABEL(L_) if(__SEH_VOLATILE_FALSE) goto L_;
182
183/* Makes GCC pretend the specified label is reachable, to silence warnings */
184#define __SEH_PRETEND_USE_LABEL(L_) (void)(&&L_)
185
186/* Soft memory barrier */
187#define __SEH_BARRIER __asm__ __volatile__("#":::"memory")
188
189/* GCC doesn't know that this equals zero */
190#define __SEH_VOLATILE_ZERO ({ int zero = 0; __asm__ __volatile__("#" : "+g" (zero)); zero; })
191
192#define __SEH_VOLATILE_FALSE __builtin_expect(__SEH_VOLATILE_ZERO, 0)
193#define __SEH_VOLATILE_TRUE __builtin_expect(!__SEH_VOLATILE_ZERO, 1)
194
195#define ___SEH_STRINGIFY(X_) # X_
196#define __SEH_STRINGIFY(X_) ___SEH_STRINGIFY(X_)
197
198#define __SEH_EXCEPT_RET long
199#define __SEH_EXCEPT_ARGS __attribute__((unused)) _SEH2Frame_t * _SEH2FrameP, __attribute__((unused)) struct _EXCEPTION_POINTERS * _SEHExceptionInformation
200#define __SEH_EXCEPT_ARGS_ , __SEH_EXCEPT_ARGS
201#define __SEH_EXCEPT_PFN __SEH_DECLARE_EXCEPT_PFN
202#define __SEH_DECLARE_EXCEPT_PFN(NAME_) __SEH_EXCEPT_RET (__cdecl * NAME_)(__SEH_EXCEPT_ARGS)
203#define __SEH_DECLARE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
204#define __SEH_DEFINE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
205
206#define __SEH_FINALLY_RET void
207#define __SEH_FINALLY_ARGS void
208#define __SEH_FINALLY_ARGS_
209#define __SEH_FINALLY_PFN __SEH_DECLARE_FINALLY_PFN
210#define __SEH_DECLARE_FINALLY_PFN(NAME_) __SEH_FINALLY_RET (__cdecl * NAME_)(__SEH_FINALLY_ARGS)
211#define __SEH_DECLARE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
212#define __SEH_DEFINE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
213
214#define __SEH_RETURN_EXCEPT(R_) return (long)(R_)
215#define __SEH_RETURN_FINALLY() return
216
217#define __SEH_BEGIN_TRY \
218 { \
219 __label__ _SEHEndTry; \
220 \
221 __SEH_PRETEND_USE_LABEL(_SEHEndTry); \
222 \
223 { \
224 __SEH_BARRIER;
225
226#define __SEH_END_TRY \
227 __SEH_BARRIER; \
228 } \
229 _SEHEndTry:; \
230 }
231
232#define __SEH_SET_TRYLEVEL(TRYLEVEL_) \
233 { \
234 __SEH_BARRIER; _SEH2FrameP->SF_TopTryLevel = (TRYLEVEL_); __SEH_BARRIER; \
235 }
236
237#define __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) (_SEH2EnterFrameAndTrylevel(_SEH2FrameP, (TRYLEVEL_)))
238#define __SEH_ENTER_TRYLEVEL(TRYLEVEL_) ((__SEH_SET_TRYLEVEL((TRYLEVEL_))), 0)
239
240#define __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterFrameAndHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
241#define __SEH_ENTER_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
242
243#define __SEH_ENTER_SCOPE(TRYLEVEL_) (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) : __SEH_ENTER_TRYLEVEL(TRYLEVEL_))
244#define __SEH_ENTER_HANDLE_SCOPE(TRYLEVEL_, HANDLE_) (({ __SEH_BARRIER; __asm__ __volatile__("mov %%esp, %0" : "=m" ((TRYLEVEL_)->SHT_Esp)); __SEH_BARRIER; }), (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL((TRYLEVEL_), (HANDLE_)) : __SEH_ENTER_HANDLE_TRYLEVEL((TRYLEVEL_), (HANDLE_))))
245
246#define __SEH_LEAVE_TRYLEVEL() \
247 if(!_SEHTopTryLevel) \
248 { \
249 __SEH_SET_TRYLEVEL(_SEHPrevTryLevelP); \
250 } \
251
252#define __SEH_LEAVE_FRAME() \
253 if(_SEHTopTryLevel) \
254 { \
255 _SEH2LeaveFrame(); \
256 }
257
258#define __SEH_END_SCOPE_CHAIN \
259 static __attribute__((unused)) const int _SEH2ScopeKind = 1; \
260 static __attribute__((unused)) _SEH2Frame_t * const _SEH2FrameP = 0; \
261 static __attribute__((unused)) _SEH2TryLevel_t * const _SEH2TryLevelP = 0;
262
263#define __SEH_BEGIN_SCOPE \
264 for(;;) \
265 { \
266 const int _SEHTopTryLevel = (_SEH2ScopeKind != 0); \
267 _SEH2Frame_t * const _SEHCurFrameP = _SEH2FrameP; \
268 volatile _SEH2TryLevel_t * const _SEHPrevTryLevelP = _SEH2TryLevelP; \
269 __attribute__((unused)) int _SEHAbnormalTermination; \
270 \
271 (void)_SEHTopTryLevel; \
272 (void)_SEHCurFrameP; \
273 (void)_SEHPrevTryLevelP; \
274 \
275 { \
276 __label__ _SEHBeforeTry; \
277 __label__ _SEHDoTry; \
278 __label__ _SEHAfterTry; \
279 static const int _SEH2ScopeKind = 0; \
280 volatile _SEH2TryLevel_t _SEHTryLevel; \
281 volatile _SEH2HandleTryLevel_t _SEHHandleTryLevel; \
282 _SEH2Frame_t _SEH2Frame[_SEHTopTryLevel ? 1 : 0]; \
283 volatile _SEH2TryLevel_t * _SEH2TryLevelP; \
284 _SEH2Frame_t * const _SEH2FrameP = _SEHTopTryLevel ? \
285 _SEH2Frame : _SEHCurFrameP; \
286 \
287 (void)_SEH2ScopeKind; \
288 (void)_SEHTryLevel; \
289 (void)_SEHHandleTryLevel; \
290 (void)_SEH2FrameP; \
291 (void)_SEH2TryLevelP; \
292 \
293 goto _SEHBeforeTry; \
294 \
295 _SEHDoTry:;
296
297#define __SEH_END_SCOPE \
298 } \
299 \
300 break; \
301 }
302
303#define __SEH_SCOPE_LOCALS \
304 __label__ _SEHBeginExcept; \
305 __label__ _SEHEndExcept; \
306 \
307 auto __SEH_DECLARE_FINALLY(_SEHFinally);
308
309#define _SEH2_TRY \
310 __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() \
311 __SEH_BEGIN_SCOPE \
312 { \
313 __SEH_SCOPE_LOCALS; \
314 \
315 __SEH_BEGIN_TRY \
316 {
317
318#define _SEH2_FINALLY \
319 } \
320 __SEH_END_TRY; \
321 \
322 goto _SEHAfterTry; \
323 _SEHBeforeTry:; \
324 \
325 __SEH_PRETEND_USE_LABEL(_SEHBeginExcept); \
326 __SEH_PRETEND_USE_LABEL(_SEHEndExcept); \
327 \
328 _SEHTryLevel.ST_Filter = 0; \
329 _SEHTryLevel.ST_Body = &_SEHFinally; \
330 _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
331 __SEH_ENTER_SCOPE(&_SEHTryLevel); \
332 _SEH2TryLevelP = &_SEHTryLevel; \
333 \
334 _SEHAbnormalTermination = 1; \
335 \
336 goto _SEHDoTry; \
337 _SEHAfterTry:; \
338 \
339 _SEHAbnormalTermination = 0; \
340 \
341 __SEH_LEAVE_TRYLEVEL(); \
342 \
343 _SEHFinally(); \
344 goto _SEHEndExcept; \
345 \
346 _SEHBeginExcept:; \
347 \
348 __attribute__((noinline)) __SEH_DEFINE_FINALLY(_SEHFinally) \
349 { \
350 __SEH_END_SCOPE_CHAIN; \
351 \
352 (void)_SEH2ScopeKind; \
353 (void)_SEH2FrameP; \
354 (void)_SEH2TryLevelP; \
355 \
356 for(;; ({ __SEH_RETURN_FINALLY(); })) \
357 {
358
359#define _SEH2_EXCEPT(...) \
360 } \
361 __SEH_END_TRY; \
362 \
363 goto _SEHAfterTry; \
364 \
365 _SEHBeforeTry:; \
366 \
367 { \
368 __attribute__((unused)) struct _EXCEPTION_POINTERS * volatile _SEHExceptionInformation; \
369 \
370 if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) <= 0) \
371 { \
372 if((__VA_ARGS__) < 0) \
373 { \
374 _SEHTryLevel.ST_Filter = (void *)-1; \
375 _SEHTryLevel.ST_Body = 0; \
376 } \
377 else \
378 { \
379 _SEHTryLevel.ST_Filter = (void *)0; \
380 _SEHTryLevel.ST_Body = 0; \
381 } \
382 \
383 _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
384 __SEH_ENTER_SCOPE(&_SEHTryLevel); \
385 _SEH2TryLevelP = &_SEHTryLevel; \
386 } \
387 else \
388 { \
389 if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) > 0) \
390 _SEHHandleTryLevel.SHT_Common.ST_Filter = (void *)1; \
391 else \
392 { \
393 __SEH_DEFINE_EXCEPT(_SEHExcept) \
394 { \
395 __SEH_RETURN_EXCEPT((__VA_ARGS__)); \
396 } \
397 \
398 _SEHHandleTryLevel.SHT_Common.ST_Filter = &_SEHExcept; \
399 } \
400 \
401 _SEHHandleTryLevel.SHT_Common.ST_Next = _SEHPrevTryLevelP; \
402 _SEH2TryLevelP = &_SEHHandleTryLevel.SHT_Common; \
403 \
404 if(__builtin_expect(__SEH_ENTER_HANDLE_SCOPE(&_SEHHandleTryLevel, &&_SEHBeginExcept), 0)) \
405 goto _SEHBeginExcept; \
406 } \
407 } \
408 \
409 goto _SEHDoTry; \
410 \
411 __attribute__((unused)) __SEH_DEFINE_FINALLY(_SEHFinally) { __SEH_RETURN_FINALLY(); } \
412 \
413 _SEHAfterTry:; \
414 __SEH_LEAVE_TRYLEVEL(); \
415 \
416 goto _SEHEndExcept; \
417 \
418 _SEHBeginExcept:; \
419 { \
420 { \
421 __SEH_BARRIER;
422
423#define _SEH2_END \
424 __SEH_BARRIER; \
425 } \
426 } \
427 \
428 _SEHEndExcept:; \
429 \
430 __SEH_LEAVE_FRAME(); \
431 } \
432 __SEH_END_SCOPE;
433
434#define _SEH2_GetExceptionInformation() (_SEHExceptionInformation)
435#define _SEH2_GetExceptionCode() ((_SEH2FrameP)->SF_Code)
436#define _SEH2_AbnormalTermination() (_SEHAbnormalTermination)
437
438#define _SEH2_YIELD(STMT_) \
439 for(;;) \
440 { \
441 if(!_SEH2ScopeKind) \
442 _SEH2Return(); \
443 \
444 STMT_; \
445 }
446
447#define _SEH2_LEAVE goto _SEHEndTry
448
449__SEH_END_SCOPE_CHAIN;
450
451#define _SEH2_VOLATILE volatile
452
453#else
454#error no PSEH support
455#endif
456
457#endif /* !KJK_PSEH2_H_ */
458
459/* EOF */
#define __cdecl
Definition: accygwin.h:79
#define __attribute__(x)
Definition: wpp_private.h:207
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
int _SEH2_VolatileExceptionCode
Definition: dummy.c:4
int _SEH2_Volatile0
Definition: dummy.c:3
int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *frame, volatile _SEH2TryLevel_t *trylevel)
void __cdecl _SEH2Return(void)
void __cdecl _SEH2LeaveFrame(void)