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