xref: /reactos/sdk/lib/crt/wine/cxx.h (revision 3a61dd7f)
1 /*
2  * Copyright 2012 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "cppexcept.h"
20 
21 #ifdef _MSC_VER
22 #define __ASM_VTABLE(name,funcs)
23 #else
24 #ifdef _WIN64
25 
26 #define VTABLE_ADD_FUNC(name) "\t.quad " THISCALL_NAME(name) "\n"
27 
28 #define __ASM_VTABLE(name,funcs) \
29     __asm__(".data\n" \
30             "\t.balign 8\n" \
31             "\t.quad " __ASM_NAME(#name "_rtti") "\n" \
32             "\t.globl " __ASM_NAME(#name "_vtable") "\n" \
33             __ASM_NAME(#name "_vtable") ":\n" \
34             funcs "\n\t.text")
35 
36 #else
37 
38 #define VTABLE_ADD_FUNC(name) "\t.long " THISCALL_NAME(name) "\n"
39 
40 #define __ASM_VTABLE(name,funcs) \
41     __asm__(".data\n" \
42             "\t.balign 4\n" \
43             "\t.long " __ASM_NAME(#name "_rtti") "\n" \
44             "\t.globl " __ASM_NAME(#name "_vtable") "\n" \
45             __ASM_NAME(#name "_vtable") ":\n" \
46             funcs "\n\t.text")
47 
48 #endif /* _WIN64 */
49 #endif // _MSC_VER
50 
51 #ifndef __x86_64__
52 
53 #define DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \
54     static type_info name ## _type_info = { \
55         &type_info_vtable, \
56         NULL, \
57         mangled_name \
58     }; \
59 \
60 static const rtti_base_descriptor name ## _rtti_base_descriptor = { \
61     &name ##_type_info, \
62     base_classes_no, \
63     { 0, -1, 0}, \
64     64 \
65 };
66 
67 #define DEFINE_RTTI_DATA(name, off, base_classes_no, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \
68     DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \
69 \
70 static const rtti_base_array name ## _rtti_base_array = { \
71     { \
72         &name ## _rtti_base_descriptor, \
73         cl1, \
74         cl2, \
75         cl3, \
76         cl4, \
77         cl5, \
78         cl6, \
79         cl7, \
80         cl8, \
81         cl9, \
82     } \
83 }; \
84 \
85 static const rtti_object_hierarchy name ## _hierarchy = { \
86     0, \
87     0, \
88     base_classes_no+1, \
89     &name ## _rtti_base_array \
90 }; \
91 \
92 const rtti_object_locator name ## _rtti = { \
93     0, \
94     off, \
95     0, \
96     &name ## _type_info, \
97     &name ## _hierarchy \
98 };
99 
100 #else
101 
102 #define __DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \
103     static type_info name ## _type_info = { \
104         &type_info_vtable, \
105         NULL, \
106         mangled_name \
107     }; \
108 \
109 static rtti_base_descriptor name ## _rtti_base_descriptor = { \
110     0xdeadbeef, \
111     base_classes_no, \
112     { 0, -1, 0}, \
113     64 \
114 };
115 
116 #define DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \
117     __DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \
118     \
119     static void init_ ## name ## _rtti(char *base) \
120     { \
121         name ## _rtti_base_descriptor.type_descriptor = (char*)&name ## _type_info - base; \
122     }
123 
124 #define DEFINE_RTTI_DATA(name, off, base_classes_no, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \
125     __DEFINE_RTTI_BASE(name, base_classes_no, mangled_name) \
126 \
127 static rtti_base_array name ## _rtti_base_array = { \
128     { \
129         0xdeadbeef, \
130         0xdeadbeef, \
131         0xdeadbeef, \
132         0xdeadbeef, \
133         0xdeadbeef, \
134         0xdeadbeef, \
135         0xdeadbeef, \
136         0xdeadbeef, \
137         0xdeadbeef, \
138         0xdeadbeef, \
139     } \
140 }; \
141 \
142 static rtti_object_hierarchy name ## _hierarchy = { \
143     0, \
144     0, \
145     base_classes_no+1, \
146     0xdeadbeef \
147 }; \
148 \
149 rtti_object_locator name ## _rtti = { \
150     1, \
151     off, \
152     0, \
153     0xdeadbeef, \
154     0xdeadbeef, \
155     0xdeadbeef \
156 };\
157 \
158 static void init_ ## name ## _rtti(char *base) \
159 { \
160     name ## _rtti_base_descriptor.type_descriptor = (char*)&name ## _type_info - base; \
161     name ## _rtti_base_array.bases[0] = (char*)&name ## _rtti_base_descriptor - base; \
162     name ## _rtti_base_array.bases[1] = (char*)cl1 - base; \
163     name ## _rtti_base_array.bases[2] = (char*)cl2 - base; \
164     name ## _rtti_base_array.bases[3] = (char*)cl3 - base; \
165     name ## _rtti_base_array.bases[4] = (char*)cl4 - base; \
166     name ## _rtti_base_array.bases[5] = (char*)cl5 - base; \
167     name ## _rtti_base_array.bases[6] = (char*)cl6 - base; \
168     name ## _rtti_base_array.bases[7] = (char*)cl7 - base; \
169     name ## _rtti_base_array.bases[8] = (char*)cl8 - base; \
170     name ## _rtti_base_array.bases[9] = (char*)cl9 - base; \
171     name ## _hierarchy.base_classes = (char*)&name ## _rtti_base_array - base; \
172     name ## _rtti.type_descriptor = (char*)&name ## _type_info - base; \
173     name ## _rtti.type_hierarchy = (char*)&name ## _hierarchy - base; \
174     name ## _rtti.object_locator = (char*)&name ## _rtti - base; \
175 }
176 
177 #endif
178 
179 #define DEFINE_RTTI_DATA0(name, off, mangled_name) \
180     DEFINE_RTTI_DATA(name, off, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name)
181 #define DEFINE_RTTI_DATA1(name, off, cl1, mangled_name) \
182     DEFINE_RTTI_DATA(name, off, 1, cl1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name)
183 #define DEFINE_RTTI_DATA2(name, off, cl1, cl2, mangled_name) \
184     DEFINE_RTTI_DATA(name, off, 2, cl1, cl2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name)
185 #define DEFINE_RTTI_DATA3(name, off, cl1, cl2, cl3, mangled_name) \
186     DEFINE_RTTI_DATA(name, off, 3, cl1, cl2, cl3, NULL, NULL, NULL, NULL, NULL, NULL, mangled_name)
187 #define DEFINE_RTTI_DATA4(name, off, cl1, cl2, cl3, cl4, mangled_name) \
188     DEFINE_RTTI_DATA(name, off, 4, cl1, cl2, cl3, cl4, NULL, NULL, NULL, NULL, NULL, mangled_name)
189 #define DEFINE_RTTI_DATA8(name, off, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, mangled_name) \
190     DEFINE_RTTI_DATA(name, off, 8, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, NULL, mangled_name)
191 #define DEFINE_RTTI_DATA9(name, off, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name) \
192     DEFINE_RTTI_DATA(name, off, 9, cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8, cl9, mangled_name)
193 
194 #ifndef __x86_64__
195 
196 typedef struct _rtti_base_descriptor
197 {
198     const type_info *type_descriptor;
199     int num_base_classes;
200     this_ptr_offsets offsets;    /* offsets for computing the this pointer */
201     unsigned int attributes;
202 } rtti_base_descriptor;
203 
204 typedef struct _rtti_base_array
205 {
206     const rtti_base_descriptor *bases[10]; /* First element is the class itself */
207 } rtti_base_array;
208 
209 typedef struct _rtti_object_hierarchy
210 {
211     unsigned int signature;
212     unsigned int attributes;
213     int array_len; /* Size of the array pointed to by 'base_classes' */
214     const rtti_base_array *base_classes;
215 } rtti_object_hierarchy;
216 
217 typedef struct _rtti_object_locator
218 {
219     unsigned int signature;
220     int base_class_offset;
221     unsigned int flags;
222     const type_info *type_descriptor;
223     const rtti_object_hierarchy *type_hierarchy;
224 } rtti_object_locator;
225 
226 #else
227 
228 typedef struct
229 {
230     unsigned int type_descriptor;
231     int num_base_classes;
232     this_ptr_offsets offsets;    /* offsets for computing the this pointer */
233     unsigned int attributes;
234 } rtti_base_descriptor;
235 
236 typedef struct
237 {
238     unsigned int bases[10]; /* First element is the class itself */
239 } rtti_base_array;
240 
241 typedef struct
242 {
243     unsigned int signature;
244     unsigned int attributes;
245     int array_len; /* Size of the array pointed to by 'base_classes' */
246     unsigned int base_classes;
247 } rtti_object_hierarchy;
248 
249 typedef struct
250 {
251     unsigned int signature;
252     int base_class_offset;
253     unsigned int flags;
254     unsigned int type_descriptor;
255     unsigned int type_hierarchy;
256     unsigned int object_locator;
257 } rtti_object_locator;
258 
259 #endif
260 
261 #ifdef __ASM_USE_THISCALL_WRAPPER
262 
263 #define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (WINAPI*)type)&vtbl_wrapper_##off)args
264 
265 extern void *vtbl_wrapper_0;
266 extern void *vtbl_wrapper_4;
267 extern void *vtbl_wrapper_8;
268 extern void *vtbl_wrapper_12;
269 extern void *vtbl_wrapper_16;
270 extern void *vtbl_wrapper_20;
271 extern void *vtbl_wrapper_24;
272 extern void *vtbl_wrapper_28;
273 extern void *vtbl_wrapper_32;
274 extern void *vtbl_wrapper_36;
275 extern void *vtbl_wrapper_40;
276 extern void *vtbl_wrapper_44;
277 extern void *vtbl_wrapper_48;
278 
279 #else
280 
281 #define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (__thiscall***)type)this)[0][off/4]args
282 
283 #endif
284 
285 exception* __thiscall exception_ctor(exception*, const char**);
286 
287 extern const vtable_ptr type_info_vtable;
288 
289 #ifdef __REACTOS__
290 void * __thiscall type_info_vector_dtor(type_info * _this, unsigned int flags);
291 #endif
292 
293 #define CREATE_TYPE_INFO_VTABLE \
294 DEFINE_THISCALL_WRAPPER(type_info_vector_dtor,8) \
295 void * __thiscall type_info_vector_dtor(type_info * _this, unsigned int flags) \
296 { \
297     if (flags & 2) \
298     { \
299         /* we have an array, with the number of elements stored before the first object */ \
300         INT_PTR i, *ptr = (INT_PTR *)_this - 1; \
301 \
302         for (i = *ptr - 1; i >= 0; i--) free(_this[i].name); \
303         free(ptr); \
304     } \
305     else \
306     { \
307         free(_this->name); \
308         if (flags & 1) free(_this); \
309     } \
310     return _this; \
311 } \
312 \
313 DEFINE_RTTI_DATA0( type_info, 0, ".?AVtype_info@@" ) \
314 \
315 __ASM_BLOCK_BEGIN(type_info_vtables) \
316     __ASM_VTABLE(type_info, \
317             VTABLE_ADD_FUNC(type_info_vector_dtor)); \
318 __ASM_BLOCK_END
319