ReactOS 0.4.16-dev-455-g37b0646
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#define _SEH2_TRY __try
29#define _SEH2_FINALLY __finally
30#define _SEH2_EXCEPT(...) __except(__VA_ARGS__)
31#define _SEH2_END
32#define _SEH2_GetExceptionInformation() (GetExceptionInformation())
33#define _SEH2_GetExceptionCode() (GetExceptionCode())
34#define _SEH2_AbnormalTermination() (AbnormalTermination())
35#define _SEH2_YIELD(STMT_) STMT_
36#define _SEH2_LEAVE __leave
37#define _SEH2_VOLATILE
38
39#define __endtry
40
41#elif defined(__GNUC__) && !defined(__clang__) && defined(_M_AMD64)
42
43#include "pseh2_64.h"
44
45#elif defined(_USE_DUMMY_PSEH) || defined (__arm__) || defined(_M_AMD64)
46
47#ifdef __cplusplus
48extern"C"
49{
50#endif
51extern int _SEH2_Volatile0;
53#ifdef __cplusplus
54} // extern "C"
55#endif
56
57#define _SEH2_TRY \
58_Pragma("GCC diagnostic push") \
59_Pragma("GCC diagnostic ignored \"-Wunused-label\"")\
60{ \
61 __label__ __seh2_scope_end__;
62
63#define _SEH2_FINALLY \
64 __seh2_scope_end__:; \
65 } \
66 if (1) \
67 { \
68 __label__ __seh2_scope_end__;
69
70#define _SEH2_EXCEPT(...) \
71 __seh2_scope_end__:; \
72 } \
73 if (_SEH2_Volatile0 || (0 && (__VA_ARGS__))) \
74 { \
75 __label__ __seh2_scope_end__;
76
77#define _SEH2_END \
78 __seh2_scope_end__:; \
79 } \
80_Pragma("GCC diagnostic pop")
81
82#define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)0)
83#define _SEH2_GetExceptionCode() _SEH2_VolatileExceptionCode
84#define _SEH2_AbnormalTermination() (0)
85#define _SEH2_YIELD(STMT_) STMT_
86#define _SEH2_LEAVE goto __seh2_scope_end__;
87#define _SEH2_VOLATILE volatile
88
89#elif defined(_USE_PSEH3)
90
91#include "pseh3.h"
92
93/* Compatibility macros */
94#define _SEH2_TRY _SEH3_TRY
95#define _SEH2_EXCEPT _SEH3_EXCEPT
96#define _SEH2_FINALLY _SEH3_FINALLY
97#define _SEH2_END _SEH3_END
98#define _SEH2_GetExceptionInformation() ((struct _EXCEPTION_POINTERS*)_exception_info())
99#define _SEH2_GetExceptionCode _exception_code
100#define _SEH2_AbnormalTermination _abnormal_termination
101#define _SEH2_LEAVE _SEH3_LEAVE
102#define _SEH2_YIELD(x) x
103#define _SEH2_VOLATILE volatile
104
105#ifndef __try // Conflict with GCC's STL
106#define __try _SEH3_TRY
107#define __except _SEH3_EXCEPT
108#define __finally _SEH3_FINALLY
109#define __endtry _SEH3_END
110#define __leave _SEH3_LEAVE
111#endif
112
113#elif defined(__GNUC__)
114
115struct _EXCEPTION_RECORD;
117struct _CONTEXT;
118
119typedef int (__cdecl * _SEH2FrameHandler_t)
120(
121 struct _EXCEPTION_RECORD *,
122 void *,
123 struct _CONTEXT *,
124 void *
125);
126
127typedef struct __SEH2Registration
128{
129 struct __SEH2Registration * SER_Prev;
130 _SEH2FrameHandler_t SER_Handler;
131}
132_SEH2Registration_t;
133
134typedef struct __SEH2Frame
135{
136 _SEH2Registration_t SF_Registration;
137 volatile struct __SEH2TryLevel * volatile SF_TopTryLevel;
138 volatile unsigned long SF_Code;
139}
140_SEH2Frame_t;
141
142typedef struct __SEH2TryLevel
143{
144 volatile struct __SEH2TryLevel * ST_Next;
145 void * ST_Filter;
146 void * ST_Body;
147}
148_SEH2TryLevel_t;
149
150typedef struct __SEH2HandleTryLevel
151{
152 _SEH2TryLevel_t SHT_Common;
153 void * volatile SHT_Esp;
154 void * volatile SHT_Ebp;
155 void * volatile SHT_Ebx;
156 void * volatile SHT_Esi;
157 void * volatile SHT_Edi;
158}
159_SEH2HandleTryLevel_t;
160
161#ifdef __cplusplus
162extern "C" {
163#endif
164
165extern int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
166extern __attribute__((returns_twice)) int __cdecl _SEH2EnterFrameAndHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
167extern __attribute__((returns_twice)) int __cdecl _SEH2EnterHandleTrylevel(_SEH2Frame_t *, volatile _SEH2HandleTryLevel_t *, void *);
168extern void __cdecl _SEH2LeaveFrame(void);
169extern void __cdecl _SEH2Return(void);
170
171#ifdef __cplusplus
172}
173#endif
174
175/* Prevent gcc from inlining functions that use SEH. */
176#if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7))
177static inline __attribute__((always_inline)) __attribute__((returns_twice)) void _SEH_DontInline() {}
178#define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() _SEH_DontInline();
179#else
180#define __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS()
181#endif
182
183/* A no-op side effect that scares GCC */
184#define __SEH_SIDE_EFFECT __asm__ __volatile__("#")
185
186/* A no-op without any real side effects, but silences warnings */
187#define __SEH_PRETEND_SIDE_EFFECT (void)0
188
189/* Forces GCC to consider the specified label reachable */
190#define __SEH_USE_LABEL(L_) if(__SEH_VOLATILE_FALSE) goto L_;
191
192/* Makes GCC pretend the specified label is reachable, to silence warnings */
193#define __SEH_PRETEND_USE_LABEL(L_) (void)(&&L_)
194
195/* Soft memory barrier */
196#define __SEH_BARRIER __asm__ __volatile__("#":::"memory")
197
198/* GCC doesn't know that this equals zero */
199#define __SEH_VOLATILE_ZERO ({ int zero = 0; __asm__ __volatile__("#" : "+g" (zero)); zero; })
200
201#define __SEH_VOLATILE_FALSE __builtin_expect(__SEH_VOLATILE_ZERO, 0)
202#define __SEH_VOLATILE_TRUE __builtin_expect(!__SEH_VOLATILE_ZERO, 1)
203
204#define ___SEH_STRINGIFY(X_) # X_
205#define __SEH_STRINGIFY(X_) ___SEH_STRINGIFY(X_)
206
207#define __SEH_EXCEPT_RET long
208#define __SEH_EXCEPT_ARGS __attribute__((unused)) _SEH2Frame_t * _SEH2FrameP, __attribute__((unused)) struct _EXCEPTION_POINTERS * _SEHExceptionInformation
209#define __SEH_EXCEPT_ARGS_ , __SEH_EXCEPT_ARGS
210#define __SEH_EXCEPT_PFN __SEH_DECLARE_EXCEPT_PFN
211#define __SEH_DECLARE_EXCEPT_PFN(NAME_) __SEH_EXCEPT_RET (__cdecl * NAME_)(__SEH_EXCEPT_ARGS)
212#define __SEH_DECLARE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
213#define __SEH_DEFINE_EXCEPT(NAME_) __SEH_EXCEPT_RET __cdecl NAME_(__SEH_EXCEPT_ARGS)
214
215#define __SEH_FINALLY_RET void
216#define __SEH_FINALLY_ARGS void
217#define __SEH_FINALLY_ARGS_
218#define __SEH_FINALLY_PFN __SEH_DECLARE_FINALLY_PFN
219#define __SEH_DECLARE_FINALLY_PFN(NAME_) __SEH_FINALLY_RET (__cdecl * NAME_)(__SEH_FINALLY_ARGS)
220#define __SEH_DECLARE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
221#define __SEH_DEFINE_FINALLY(NAME_) __SEH_FINALLY_RET __cdecl NAME_(__SEH_FINALLY_ARGS)
222
223#define __SEH_RETURN_EXCEPT(R_) return (long)(R_)
224#define __SEH_RETURN_FINALLY() return
225
226#define __SEH_BEGIN_TRY \
227 { \
228 __label__ _SEHEndTry; \
229 \
230 __SEH_PRETEND_USE_LABEL(_SEHEndTry); \
231 \
232 { \
233 __SEH_BARRIER;
234
235#define __SEH_END_TRY \
236 __SEH_BARRIER; \
237 } \
238 _SEHEndTry:; \
239 }
240
241#define __SEH_SET_TRYLEVEL(TRYLEVEL_) \
242 { \
243 __SEH_BARRIER; _SEH2FrameP->SF_TopTryLevel = (TRYLEVEL_); __SEH_BARRIER; \
244 }
245
246#define __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) (_SEH2EnterFrameAndTrylevel(_SEH2FrameP, (TRYLEVEL_)))
247#define __SEH_ENTER_TRYLEVEL(TRYLEVEL_) ((__SEH_SET_TRYLEVEL((TRYLEVEL_))), 0)
248
249#define __SEH_ENTER_FRAME_AND_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterFrameAndHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
250#define __SEH_ENTER_HANDLE_TRYLEVEL(TRYLEVEL_, HANDLE_) _SEH2EnterHandleTrylevel(_SEH2FrameP, (TRYLEVEL_), (HANDLE_))
251
252#define __SEH_ENTER_SCOPE(TRYLEVEL_) (_SEHTopTryLevel ? __SEH_ENTER_FRAME_AND_TRYLEVEL(TRYLEVEL_) : __SEH_ENTER_TRYLEVEL(TRYLEVEL_))
253#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_))))
254
255#define __SEH_LEAVE_TRYLEVEL() \
256 if(!_SEHTopTryLevel) \
257 { \
258 __SEH_SET_TRYLEVEL(_SEHPrevTryLevelP); \
259 } \
260
261#define __SEH_LEAVE_FRAME() \
262 if(_SEHTopTryLevel) \
263 { \
264 _SEH2LeaveFrame(); \
265 }
266
267#define __SEH_END_SCOPE_CHAIN \
268 static __attribute__((unused)) const int _SEH2ScopeKind = 1; \
269 static __attribute__((unused)) _SEH2Frame_t * const _SEH2FrameP = 0; \
270 static __attribute__((unused)) _SEH2TryLevel_t * const _SEH2TryLevelP = 0;
271
272#define __SEH_BEGIN_SCOPE \
273 for(;;) \
274 { \
275 const int _SEHTopTryLevel = (_SEH2ScopeKind != 0); \
276 _SEH2Frame_t * const _SEHCurFrameP = _SEH2FrameP; \
277 volatile _SEH2TryLevel_t * const _SEHPrevTryLevelP = _SEH2TryLevelP; \
278 __attribute__((unused)) int _SEHAbnormalTermination; \
279 \
280 (void)_SEHTopTryLevel; \
281 (void)_SEHCurFrameP; \
282 (void)_SEHPrevTryLevelP; \
283 \
284 { \
285 __label__ _SEHBeforeTry; \
286 __label__ _SEHDoTry; \
287 __label__ _SEHAfterTry; \
288 static const int _SEH2ScopeKind = 0; \
289 volatile _SEH2TryLevel_t _SEHTryLevel; \
290 volatile _SEH2HandleTryLevel_t _SEHHandleTryLevel; \
291 _SEH2Frame_t _SEH2Frame[_SEHTopTryLevel ? 1 : 0]; \
292 volatile _SEH2TryLevel_t * _SEH2TryLevelP; \
293 _SEH2Frame_t * const _SEH2FrameP = _SEHTopTryLevel ? \
294 _SEH2Frame : _SEHCurFrameP; \
295 \
296 (void)_SEH2ScopeKind; \
297 (void)_SEHTryLevel; \
298 (void)_SEHHandleTryLevel; \
299 (void)_SEH2FrameP; \
300 (void)_SEH2TryLevelP; \
301 \
302 goto _SEHBeforeTry; \
303 \
304 _SEHDoTry:;
305
306#define __SEH_END_SCOPE \
307 } \
308 \
309 break; \
310 }
311
312#define __SEH_SCOPE_LOCALS \
313 __label__ _SEHBeginExcept; \
314 __label__ _SEHEndExcept; \
315 \
316 auto __SEH_DECLARE_FINALLY(_SEHFinally);
317
318#define _SEH2_TRY \
319 __PREVENT_GCC_FROM_INLINING_SEH_FUNCTIONS() \
320 __SEH_BEGIN_SCOPE \
321 { \
322 __SEH_SCOPE_LOCALS; \
323 \
324 __SEH_BEGIN_TRY \
325 {
326
327#define _SEH2_FINALLY \
328 } \
329 __SEH_END_TRY; \
330 \
331 goto _SEHAfterTry; \
332 _SEHBeforeTry:; \
333 \
334 __SEH_PRETEND_USE_LABEL(_SEHBeginExcept); \
335 __SEH_PRETEND_USE_LABEL(_SEHEndExcept); \
336 \
337 _SEHTryLevel.ST_Filter = 0; \
338 _SEHTryLevel.ST_Body = &_SEHFinally; \
339 _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
340 __SEH_ENTER_SCOPE(&_SEHTryLevel); \
341 _SEH2TryLevelP = &_SEHTryLevel; \
342 \
343 _SEHAbnormalTermination = 1; \
344 \
345 goto _SEHDoTry; \
346 _SEHAfterTry:; \
347 \
348 _SEHAbnormalTermination = 0; \
349 \
350 __SEH_LEAVE_TRYLEVEL(); \
351 \
352 _SEHFinally(); \
353 goto _SEHEndExcept; \
354 \
355 _SEHBeginExcept:; \
356 \
357 __attribute__((noinline)) __SEH_DEFINE_FINALLY(_SEHFinally) \
358 { \
359 __SEH_END_SCOPE_CHAIN; \
360 \
361 (void)_SEH2ScopeKind; \
362 (void)_SEH2FrameP; \
363 (void)_SEH2TryLevelP; \
364 \
365 for(;; ({ __SEH_RETURN_FINALLY(); })) \
366 {
367
368#define _SEH2_EXCEPT(...) \
369 } \
370 __SEH_END_TRY; \
371 \
372 goto _SEHAfterTry; \
373 \
374 _SEHBeforeTry:; \
375 \
376 { \
377 __attribute__((unused)) struct _EXCEPTION_POINTERS * volatile _SEHExceptionInformation; \
378 \
379 if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) <= 0) \
380 { \
381 if((__VA_ARGS__) < 0) \
382 { \
383 _SEHTryLevel.ST_Filter = (void *)-1; \
384 _SEHTryLevel.ST_Body = 0; \
385 } \
386 else \
387 { \
388 _SEHTryLevel.ST_Filter = (void *)0; \
389 _SEHTryLevel.ST_Body = 0; \
390 } \
391 \
392 _SEHTryLevel.ST_Next = _SEHPrevTryLevelP; \
393 __SEH_ENTER_SCOPE(&_SEHTryLevel); \
394 _SEH2TryLevelP = &_SEHTryLevel; \
395 } \
396 else \
397 { \
398 if(__builtin_constant_p((__VA_ARGS__)) && (__VA_ARGS__) > 0) \
399 _SEHHandleTryLevel.SHT_Common.ST_Filter = (void *)1; \
400 else \
401 { \
402 __SEH_DEFINE_EXCEPT(_SEHExcept) \
403 { \
404 __SEH_RETURN_EXCEPT((__VA_ARGS__)); \
405 } \
406 \
407 _SEHHandleTryLevel.SHT_Common.ST_Filter = &_SEHExcept; \
408 } \
409 \
410 _SEHHandleTryLevel.SHT_Common.ST_Next = _SEHPrevTryLevelP; \
411 _SEH2TryLevelP = &_SEHHandleTryLevel.SHT_Common; \
412 \
413 if(__builtin_expect(__SEH_ENTER_HANDLE_SCOPE(&_SEHHandleTryLevel, &&_SEHBeginExcept), 0)) \
414 goto _SEHBeginExcept; \
415 } \
416 } \
417 \
418 goto _SEHDoTry; \
419 \
420 __attribute__((unused)) __SEH_DEFINE_FINALLY(_SEHFinally) { __SEH_RETURN_FINALLY(); } \
421 \
422 _SEHAfterTry:; \
423 __SEH_LEAVE_TRYLEVEL(); \
424 \
425 goto _SEHEndExcept; \
426 \
427 _SEHBeginExcept:; \
428 { \
429 { \
430 __SEH_BARRIER;
431
432#define _SEH2_END \
433 __SEH_BARRIER; \
434 } \
435 } \
436 \
437 _SEHEndExcept:; \
438 \
439 __SEH_LEAVE_FRAME(); \
440 } \
441 __SEH_END_SCOPE;
442
443#define _SEH2_GetExceptionInformation() (_SEHExceptionInformation)
444#define _SEH2_GetExceptionCode() ((_SEH2FrameP)->SF_Code)
445#define _SEH2_AbnormalTermination() (_SEHAbnormalTermination)
446
447#define _SEH2_YIELD(STMT_) \
448 for(;;) \
449 { \
450 if(!_SEH2ScopeKind) \
451 _SEH2Return(); \
452 \
453 STMT_; \
454 }
455
456#define _SEH2_LEAVE goto _SEHEndTry
457
458__SEH_END_SCOPE_CHAIN;
459
460#define _SEH2_VOLATILE volatile
461
462#else
463#error no PSEH support
464#endif
465
466#endif /* !KJK_PSEH2_H_ */
467
468/* 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)