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