97f9fb81fc0571d609f23e456cf91f237999b26d
[reactos.git] / reactos / lib / sdk / crt / include / internal / wine / cppexcept.h
1 /*
2 * msvcrt C++ exception handling
3 *
4 * Copyright 2002 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #ifndef __MSVCRT_CPPEXCEPT_H
22 #define __MSVCRT_CPPEXCEPT_H
23
24 #include <pseh/pseh2.h>
25
26 /* Macros to define assembler functions somewhat portably */
27
28 #define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef"
29 #define __ASM_NAME(name) "_" name
30
31 #ifdef __GNUC__
32 # define __ASM_GLOBAL_FUNC(name,code) \
33 __asm__( ".align 4\n\t" \
34 ".globl " __ASM_NAME(#name) "\n\t" \
35 __ASM_FUNC(#name) "\n" \
36 __ASM_NAME(#name) ":\n\t" \
37 code );
38 #else /* __GNUC__ */
39 # define __ASM_GLOBAL_FUNC(name,code) \
40 void __asm_dummy_##name(void) { \
41 asm( ".align 4\n\t" \
42 ".globl " __ASM_NAME(#name) "\n\t" \
43 __ASM_FUNC(#name) "\n" \
44 __ASM_NAME(#name) ":\n\t" \
45 code ); \
46 }
47 #endif /* __GNUC__ */
48
49 #define EH_NONCONTINUABLE 0x01
50 #define EH_UNWINDING 0x02
51 #define EH_EXIT_UNWIND 0x04
52 #define EH_STACK_INVALID 0x08
53 #define EH_NESTED_CALL 0x10
54
55 #ifndef _M_ARM
56
57 #ifdef _MSC_VER
58 #pragma warning(push)
59 #pragma warning(disable:4733)
60 #endif
61
62 static inline EXCEPTION_REGISTRATION_RECORD *__wine_push_frame( EXCEPTION_REGISTRATION_RECORD *frame )
63 {
64 frame->Next = (struct _EXCEPTION_REGISTRATION_RECORD *)__readfsdword(0);
65 __writefsdword(0, (unsigned long)frame);
66 return frame->Next;
67 }
68
69 static inline EXCEPTION_REGISTRATION_RECORD *__wine_pop_frame( EXCEPTION_REGISTRATION_RECORD *frame )
70 {
71 __writefsdword(0, (unsigned long)frame->Next);
72 return frame->Next;
73 }
74
75 #ifdef _MSC_VER
76 #pragma warning(pop)
77 #endif
78
79 #endif
80
81 #define __TRY _SEH2_TRY
82 #define __EXCEPT(func) _SEH2_EXCEPT(func(_SEH2_GetExceptionInformation()))
83 #define __EXCEPT_PAGE_FAULT _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION)
84 #define __EXCEPT_ALL _SEH2_EXCEPT(_SEH_EXECUTE_HANDLER)
85 #define __ENDTRY _SEH2_END
86 #define __FINALLY(func) _SEH2_FINALLY { func(!_SEH2_AbnormalTermination()); }
87
88 #define CXX_FRAME_MAGIC 0x19930520
89 #define CXX_EXCEPTION 0xe06d7363
90
91 typedef void (*vtable_ptr)();
92
93 /* type_info object, see cpp.c for inplementation */
94 typedef struct __type_info
95 {
96 const vtable_ptr *vtable;
97 char *name; /* Unmangled name, allocated lazily */
98 char mangled[32]; /* Variable length, but we declare it large enough for static RTTI */
99 } type_info;
100
101 /* exception object */
102 typedef struct __exception
103 {
104 const vtable_ptr *vtable;
105 char *name; /* Name of this exception, always a new copy for each object */
106 int do_free; /* Whether to free 'name' in our dtor */
107 } exception;
108
109 /* the exception frame used by CxxFrameHandler */
110 typedef struct __cxx_exception_frame
111 {
112 EXCEPTION_REGISTRATION_RECORD frame; /* the standard exception frame */
113 int trylevel;
114 DWORD ebp;
115 } cxx_exception_frame;
116
117 /* info about a single catch {} block */
118 typedef struct __catchblock_info
119 {
120 UINT flags; /* flags (see below) */
121 type_info *type_info; /* C++ type caught by this block */
122 int offset; /* stack offset to copy exception object to */
123 void (*handler)(); /* catch block handler code */
124 } catchblock_info;
125 #define TYPE_FLAG_CONST 1
126 #define TYPE_FLAG_VOLATILE 2
127 #define TYPE_FLAG_REFERENCE 8
128
129 /* info about a single try {} block */
130 typedef struct __tryblock_info
131 {
132 int start_level; /* start trylevel of that block */
133 int end_level; /* end trylevel of that block */
134 int catch_level; /* initial trylevel of the catch block */
135 int catchblock_count; /* count of catch blocks in array */
136 catchblock_info *catchblock; /* array of catch blocks */
137 } tryblock_info;
138
139 /* info about the unwind handler for a given trylevel */
140 typedef struct __unwind_info
141 {
142 int prev; /* prev trylevel unwind handler, to run after this one */
143 void (*handler)(); /* unwind handler */
144 } unwind_info;
145
146 /* descriptor of all try blocks of a given function */
147 typedef struct __cxx_function_descr
148 {
149 UINT magic; /* must be CXX_FRAME_MAGIC */
150 UINT unwind_count; /* number of unwind handlers */
151 unwind_info *unwind_table; /* array of unwind handlers */
152 UINT tryblock_count; /* number of try blocks */
153 tryblock_info *tryblock; /* array of try blocks */
154 UINT unknown[3];
155 } cxx_function_descr;
156
157 typedef void (*cxx_copy_ctor)(void);
158
159 /* offsets for computing the this pointer */
160 typedef struct
161 {
162 int this_offset; /* offset of base class this pointer from start of object */
163 int vbase_descr; /* offset of virtual base class descriptor */
164 int vbase_offset; /* offset of this pointer offset in virtual base class descriptor */
165 } this_ptr_offsets;
166
167 /* complete information about a C++ type */
168 typedef struct __cxx_type_info
169 {
170 UINT flags; /* flags (see CLASS_* flags below) */
171 const type_info *type_info; /* C++ type info */
172 this_ptr_offsets offsets; /* offsets for computing the this pointer */
173 unsigned int size; /* object size */
174 cxx_copy_ctor copy_ctor; /* copy constructor */
175 } cxx_type_info;
176 #define CLASS_IS_SIMPLE_TYPE 1
177 #define CLASS_HAS_VIRTUAL_BASE_CLASS 4
178
179 /* table of C++ types that apply for a given object */
180 typedef struct __cxx_type_info_table
181 {
182 UINT count; /* number of types */
183 const cxx_type_info *info[3]; /* variable length, we declare it large enough for static RTTI */
184 } cxx_type_info_table;
185
186 typedef DWORD (*cxx_exc_custom_handler)( PEXCEPTION_RECORD, cxx_exception_frame*,
187 PCONTEXT, EXCEPTION_REGISTRATION_RECORD**,
188 const cxx_function_descr*, int nested_trylevel,
189 EXCEPTION_REGISTRATION_RECORD *nested_frame, DWORD unknown3 );
190
191 /* type information for an exception object */
192 typedef struct __cxx_exception_type
193 {
194 UINT flags; /* TYPE_FLAG flags */
195 void (*destructor)(); /* exception object destructor */
196 cxx_exc_custom_handler custom_handler; /* custom handler for this exception */
197 const cxx_type_info_table *type_info_table; /* list of types for this exception object */
198 } cxx_exception_type;
199
200 void _CxxThrowException(exception*,const cxx_exception_type*);
201
202 static inline const char *dbgstr_type_info( const type_info *info )
203 {
204 if (!info) return "{}";
205 return "{}";/*sprintf( "{vtable=%p name=%s (%s)}",
206 info->vtable, info->mangled, info->name ? info->name : "" );*/
207 }
208
209 /* compute the this pointer for a base class of a given type */
210 static inline void *get_this_pointer( const this_ptr_offsets *off, void *object )
211 {
212 void *this_ptr;
213 int *offset_ptr;
214
215 if (!object) return NULL;
216 this_ptr = (char *)object + off->this_offset;
217 if (off->vbase_descr >= 0)
218 {
219 /* move this ptr to vbase descriptor */
220 this_ptr = (char *)this_ptr + off->vbase_descr;
221 /* and fetch additional offset from vbase descriptor */
222 offset_ptr = (int *)(*(char **)this_ptr + off->vbase_offset);
223 this_ptr = (char *)this_ptr + *offset_ptr;
224 }
225 return this_ptr;
226 }
227
228 #endif /* __MSVCRT_CPPEXCEPT_H */