]>
Commit | Line | Data |
---|---|---|
b4c522fa | 1 | /* typeinfo.cc -- D runtime type identification. |
8d9254fc | 2 | Copyright (C) 2013-2020 Free Software Foundation, Inc. |
b4c522fa IB |
3 | |
4 | GCC is free software; you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation; either version 3, or (at your option) | |
7 | any later version. | |
8 | ||
9 | GCC 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 | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with GCC; see the file COPYING3. If not see | |
16 | <http://www.gnu.org/licenses/>. */ | |
17 | ||
18 | #include "config.h" | |
19 | #include "system.h" | |
20 | #include "coretypes.h" | |
21 | ||
22 | #include "dmd/aggregate.h" | |
23 | #include "dmd/enum.h" | |
24 | #include "dmd/errors.h" | |
25 | #include "dmd/expression.h" | |
26 | #include "dmd/globals.h" | |
27 | #include "dmd/identifier.h" | |
28 | #include "dmd/module.h" | |
29 | #include "dmd/mtype.h" | |
30 | #include "dmd/template.h" | |
31 | #include "dmd/target.h" | |
32 | ||
33 | #include "tree.h" | |
34 | #include "fold-const.h" | |
35 | #include "diagnostic.h" | |
36 | #include "stringpool.h" | |
37 | #include "toplev.h" | |
38 | #include "stor-layout.h" | |
39 | ||
40 | #include "d-tree.h" | |
41 | #include "d-target.h" | |
42 | ||
43 | ||
44 | /* D returns type information to the user as TypeInfo class objects, and can | |
45 | be retrieved for any type using `typeid()'. We also use type information | |
46 | to implement many runtime library helpers, including `new', `delete', most | |
47 | dynamic array operations, and all associative array operations. | |
48 | ||
49 | Type information for a particular type is indicated with an ABI defined | |
50 | structure derived from TypeInfo. This would all be very straight forward, | |
51 | but for the fact that the runtime library provides the definitions of the | |
52 | TypeInfo structure and the ABI defined derived classes in `object.d', as | |
53 | well as having specific implementations of TypeInfo for built-in types | |
54 | in `rt/typeinfo`. We cannot build declarations of these directly in the | |
55 | compiler, but we need to layout objects of their type. | |
56 | ||
57 | To get around this, we define layout compatible POD-structs and generate the | |
58 | appropriate initializations for them. When we have to provide a TypeInfo to | |
59 | the user, we cast the internal compiler type to TypeInfo. | |
60 | ||
61 | It is only required that TypeInfo has a definition in `object.d'. It could | |
62 | happen that we are generating a type information for a TypeInfo object that | |
63 | has no declaration. We however only need the addresses of such incomplete | |
64 | TypeInfo objects for static initialization. */ | |
65 | ||
66 | enum tinfo_kind | |
67 | { | |
68 | TK_TYPEINFO_TYPE, /* object.TypeInfo */ | |
69 | TK_CLASSINFO_TYPE, /* object.TypeInfo_Class */ | |
70 | TK_INTERFACE_TYPE, /* object.TypeInfo_Interface */ | |
71 | TK_STRUCT_TYPE, /* object.TypeInfo_Struct */ | |
72 | TK_POINTER_TYPE, /* object.TypeInfo_Pointer */ | |
73 | TK_ARRAY_TYPE, /* object.TypeInfo_Array */ | |
74 | TK_STATICARRAY_TYPE, /* object.TypeInfo_StaticArray */ | |
75 | TK_ASSOCIATIVEARRAY_TYPE, /* object.TypeInfo_AssociativeArray */ | |
76 | TK_VECTOR_TYPE, /* object.TypeInfo_Vector */ | |
77 | TK_ENUMERAL_TYPE, /* object.TypeInfo_Enum */ | |
78 | TK_FUNCTION_TYPE, /* object.TypeInfo_Function */ | |
79 | TK_DELEGATE_TYPE, /* object.TypeInfo_Delegate */ | |
80 | TK_TYPELIST_TYPE, /* object.TypeInfo_Tuple */ | |
81 | TK_CONST_TYPE, /* object.TypeInfo_Const */ | |
82 | TK_IMMUTABLE_TYPE, /* object.TypeInfo_Invariant */ | |
83 | TK_SHARED_TYPE, /* object.TypeInfo_Shared */ | |
84 | TK_INOUT_TYPE, /* object.TypeInfo_Inout */ | |
85 | TK_CPPTI_TYPE, /* object.__cpp_type_info_ptr */ | |
86 | TK_END | |
87 | }; | |
88 | ||
89 | /* An array of all internal TypeInfo derived types we need. | |
90 | The TypeInfo and ClassInfo types are created early, the | |
91 | remainder are generated as needed. */ | |
92 | ||
93 | static GTY(()) tree tinfo_types[TK_END]; | |
94 | ||
95 | /* Return the kind of TypeInfo used to describe TYPE. */ | |
96 | ||
97 | static tinfo_kind | |
98 | get_typeinfo_kind (Type *type) | |
99 | { | |
100 | /* Check head shared/const modifiers first. */ | |
101 | if (type->isShared ()) | |
102 | return TK_SHARED_TYPE; | |
103 | else if (type->isConst ()) | |
104 | return TK_CONST_TYPE; | |
105 | else if (type->isImmutable ()) | |
106 | return TK_IMMUTABLE_TYPE; | |
107 | else if (type->isWild ()) | |
108 | return TK_INOUT_TYPE; | |
109 | ||
110 | switch (type->ty) | |
111 | { | |
112 | case Tpointer: | |
113 | return TK_POINTER_TYPE; | |
114 | ||
115 | case Tarray: | |
116 | return TK_ARRAY_TYPE; | |
117 | ||
118 | case Tsarray: | |
119 | return TK_STATICARRAY_TYPE; | |
120 | ||
121 | case Taarray: | |
122 | return TK_ASSOCIATIVEARRAY_TYPE; | |
123 | ||
124 | case Tstruct: | |
125 | return TK_STRUCT_TYPE; | |
126 | ||
127 | case Tvector: | |
128 | return TK_VECTOR_TYPE; | |
129 | ||
130 | case Tenum: | |
131 | return TK_ENUMERAL_TYPE; | |
132 | ||
133 | case Tfunction: | |
134 | return TK_FUNCTION_TYPE; | |
135 | ||
136 | case Tdelegate: | |
137 | return TK_DELEGATE_TYPE; | |
138 | ||
139 | case Ttuple: | |
140 | return TK_TYPELIST_TYPE; | |
141 | ||
142 | case Tclass: | |
89fdaf5a | 143 | if (type->isTypeClass ()->sym->isInterfaceDeclaration ()) |
b4c522fa IB |
144 | return TK_INTERFACE_TYPE; |
145 | else | |
146 | return TK_CLASSINFO_TYPE; | |
147 | ||
148 | default: | |
149 | return TK_TYPEINFO_TYPE; | |
150 | } | |
151 | } | |
152 | ||
153 | /* Generate the RECORD_TYPE containing the data layout of a TypeInfo derivative | |
154 | as used by the runtime. This layout must be consistent with that defined in | |
155 | the `object.d' module. */ | |
156 | ||
157 | static void | |
158 | make_internal_typeinfo (tinfo_kind tk, Identifier *ident, ...) | |
159 | { | |
160 | va_list ap; | |
161 | ||
162 | va_start (ap, ident); | |
163 | ||
164 | /* First two fields are from the TypeInfo base class. | |
165 | Note, finish_builtin_struct() expects these fields in reverse order. */ | |
166 | tree fields = create_field_decl (ptr_type_node, NULL, 1, 1); | |
167 | DECL_CHAIN (fields) = create_field_decl (vtbl_ptr_type_node, NULL, 1, 1); | |
168 | ||
169 | /* Now add the derived fields. */ | |
170 | tree field_type = va_arg (ap, tree); | |
171 | while (field_type != NULL_TREE) | |
172 | { | |
173 | tree field = create_field_decl (field_type, NULL, 1, 1); | |
174 | DECL_CHAIN (field) = fields; | |
175 | fields = field; | |
176 | field_type = va_arg (ap, tree); | |
177 | } | |
178 | ||
179 | /* Create the TypeInfo type. */ | |
180 | tree type = make_node (RECORD_TYPE); | |
181 | finish_builtin_struct (type, ident->toChars (), fields, NULL_TREE); | |
182 | ||
183 | tinfo_types[tk] = type; | |
184 | ||
185 | va_end (ap); | |
186 | } | |
187 | ||
88ad43b1 IB |
188 | /* Reference to the `object` module, where all TypeInfo is defined. */ |
189 | ||
190 | static Module *object_module; | |
191 | ||
192 | /* Helper for create_frontend_tinfo_types. Creates a typeinfo class | |
193 | declaration incase one wasn't supplied by reading `object.d'. */ | |
b4c522fa IB |
194 | |
195 | static void | |
88ad43b1 | 196 | make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL) |
b4c522fa IB |
197 | { |
198 | if (!base) | |
199 | base = Type::dtypeinfo; | |
200 | ||
88ad43b1 IB |
201 | gcc_assert (object_module); |
202 | ||
b4c522fa | 203 | /* Create object module in order to complete the semantic. */ |
88ad43b1 IB |
204 | if (!object_module->_scope) |
205 | object_module->importAll (NULL); | |
b4c522fa IB |
206 | |
207 | /* Assignment of global typeinfo variables is managed by the ClassDeclaration | |
208 | constructor, so only need to new the declaration here. */ | |
88ad43b1 | 209 | Loc loc = (object_module->md) ? object_module->md->loc : object_module->loc; |
b4c522fa IB |
210 | ClassDeclaration *tinfo = ClassDeclaration::create (loc, ident, NULL, NULL, |
211 | true); | |
88ad43b1 IB |
212 | tinfo->parent = object_module; |
213 | tinfo->semantic (object_module->_scope); | |
b4c522fa | 214 | tinfo->baseClass = base; |
88ad43b1 IB |
215 | /* This is a compiler generated class, and shouldn't be mistaken for being |
216 | the type declared in the runtime library. */ | |
217 | tinfo->storage_class |= STCtemp; | |
b4c522fa IB |
218 | } |
219 | ||
220 | /* Make sure the required builtin types exist for generating the TypeInfo | |
221 | variable definitions. */ | |
222 | ||
223 | void | |
224 | create_tinfo_types (Module *mod) | |
225 | { | |
226 | /* Build the internal TypeInfo and ClassInfo types. | |
227 | See TypeInfoVisitor for documentation of field layout. */ | |
228 | make_internal_typeinfo (TK_TYPEINFO_TYPE, Identifier::idPool ("TypeInfo"), | |
229 | NULL); | |
230 | ||
231 | make_internal_typeinfo (TK_CLASSINFO_TYPE, | |
232 | Identifier::idPool ("TypeInfo_Class"), | |
233 | array_type_node, array_type_node, array_type_node, | |
234 | array_type_node, ptr_type_node, ptr_type_node, | |
235 | ptr_type_node, d_uint_type, ptr_type_node, | |
236 | array_type_node, ptr_type_node, ptr_type_node, NULL); | |
237 | ||
88ad43b1 IB |
238 | object_module = mod; |
239 | } | |
240 | ||
241 | /* Same as create_tinfo_types, but builds all front-end TypeInfo variable | |
242 | definitions. */ | |
243 | ||
244 | static void | |
245 | create_frontend_tinfo_types (void) | |
246 | { | |
c0aebc60 | 247 | /* If there's no Object class defined, then neither can TypeInfo be. */ |
88ad43b1 | 248 | if (object_module == NULL || ClassDeclaration::object == NULL) |
c0aebc60 IB |
249 | return; |
250 | ||
b4c522fa IB |
251 | /* Create all frontend TypeInfo classes declarations. We rely on all |
252 | existing, even if only just as stubs. */ | |
253 | if (!Type::dtypeinfo) | |
88ad43b1 | 254 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo"), |
b4c522fa IB |
255 | ClassDeclaration::object); |
256 | ||
257 | if (!Type::typeinfoclass) | |
88ad43b1 | 258 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Class")); |
b4c522fa IB |
259 | |
260 | if (!Type::typeinfointerface) | |
88ad43b1 | 261 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Interface")); |
b4c522fa IB |
262 | |
263 | if (!Type::typeinfostruct) | |
88ad43b1 | 264 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Struct")); |
b4c522fa IB |
265 | |
266 | if (!Type::typeinfopointer) | |
88ad43b1 | 267 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Pointer")); |
b4c522fa IB |
268 | |
269 | if (!Type::typeinfoarray) | |
88ad43b1 | 270 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Array")); |
b4c522fa IB |
271 | |
272 | if (!Type::typeinfostaticarray) | |
88ad43b1 | 273 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_StaticArray")); |
b4c522fa IB |
274 | |
275 | if (!Type::typeinfoassociativearray) | |
88ad43b1 | 276 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_AssociativeArray")); |
b4c522fa IB |
277 | |
278 | if (!Type::typeinfoenum) | |
88ad43b1 | 279 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Enum")); |
b4c522fa IB |
280 | |
281 | if (!Type::typeinfofunction) | |
88ad43b1 | 282 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Function")); |
b4c522fa IB |
283 | |
284 | if (!Type::typeinfodelegate) | |
88ad43b1 | 285 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Delegate")); |
b4c522fa IB |
286 | |
287 | if (!Type::typeinfotypelist) | |
88ad43b1 | 288 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Tuple")); |
b4c522fa IB |
289 | |
290 | if (!Type::typeinfoconst) | |
88ad43b1 | 291 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Const")); |
b4c522fa IB |
292 | |
293 | if (!Type::typeinfoinvariant) | |
88ad43b1 | 294 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Invariant"), |
b4c522fa IB |
295 | Type::typeinfoconst); |
296 | ||
297 | if (!Type::typeinfoshared) | |
88ad43b1 | 298 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Shared"), |
b4c522fa IB |
299 | Type::typeinfoconst); |
300 | ||
301 | if (!Type::typeinfowild) | |
88ad43b1 | 302 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Wild"), |
b4c522fa IB |
303 | Type::typeinfoconst); |
304 | ||
305 | if (!Type::typeinfovector) | |
88ad43b1 | 306 | make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Vector")); |
b4c522fa IB |
307 | |
308 | if (!ClassDeclaration::cpp_type_info_ptr) | |
88ad43b1 | 309 | make_frontend_typeinfo (Identifier::idPool ("__cpp_type_info_ptr"), |
b4c522fa IB |
310 | ClassDeclaration::object); |
311 | } | |
312 | ||
c0aebc60 IB |
313 | /* Return true if TypeInfo class TINFO is available in the runtime library. */ |
314 | ||
315 | bool | |
316 | have_typeinfo_p (ClassDeclaration *tinfo) | |
317 | { | |
318 | /* Run-time typeinfo disabled on command line. */ | |
319 | if (!global.params.useTypeInfo) | |
320 | return false; | |
321 | ||
322 | /* Can't layout TypeInfo if type is not declared, or is an opaque | |
323 | declaration in the object module. */ | |
324 | if (!tinfo || !tinfo->members) | |
325 | return false; | |
326 | ||
327 | /* Typeinfo is compiler-generated. */ | |
328 | if (tinfo->storage_class & STCtemp) | |
329 | return false; | |
330 | ||
331 | return true; | |
332 | } | |
333 | ||
b4c522fa IB |
334 | /* Implements the visitor interface to build the TypeInfo layout of all |
335 | TypeInfoDeclaration AST classes emitted from the D Front-end. | |
336 | All visit methods accept one parameter D, which holds the frontend AST | |
337 | of the TypeInfo class. They also don't return any value, instead the | |
338 | generated symbol is cached internally and returned from the caller. */ | |
339 | ||
340 | class TypeInfoVisitor : public Visitor | |
341 | { | |
342 | using Visitor::visit; | |
343 | ||
98eb7b2e | 344 | tree decl_; |
b4c522fa IB |
345 | vec<constructor_elt, va_gc> *init_; |
346 | ||
98eb7b2e IB |
347 | /* Build an internal comdat symbol for the manifest constant VALUE, so that |
348 | its address can be taken. */ | |
349 | ||
350 | tree internal_reference (tree value) | |
351 | { | |
352 | /* Use the typeinfo decl name as a prefix for the internal symbol. */ | |
353 | const char *prefix = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (this->decl_)); | |
354 | tree decl = build_artificial_decl (TREE_TYPE (value), value, prefix); | |
355 | ||
356 | /* The internal pointer reference should be public, but not visible outside | |
357 | the compilation unit. */ | |
358 | DECL_EXTERNAL (decl) = 0; | |
359 | TREE_PUBLIC (decl) = 1; | |
360 | DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL; | |
48742e02 | 361 | d_comdat_linkage (decl); |
98eb7b2e IB |
362 | d_pushdecl (decl); |
363 | ||
364 | return decl; | |
365 | } | |
366 | ||
b4c522fa IB |
367 | /* Add VALUE to the constructor values list. */ |
368 | ||
369 | void layout_field (tree value) | |
370 | { | |
371 | CONSTRUCTOR_APPEND_ELT (this->init_, NULL_TREE, value); | |
372 | } | |
373 | ||
374 | /* Write out STR as a static D string literal. */ | |
375 | ||
376 | void layout_string (const char *str) | |
377 | { | |
378 | unsigned len = strlen (str); | |
379 | tree value = build_string (len, str); | |
380 | ||
381 | TREE_TYPE (value) = make_array_type (Type::tchar, len); | |
382 | TREE_CONSTANT (value) = 1; | |
383 | TREE_READONLY (value) = 1; | |
384 | TREE_STATIC (value) = 1; | |
385 | ||
386 | /* Taking the address, so assign the literal to a static var. */ | |
98eb7b2e | 387 | tree decl = this->internal_reference (value); |
b4c522fa | 388 | TREE_READONLY (decl) = 1; |
b4c522fa IB |
389 | |
390 | value = d_array_value (build_ctype (Type::tchar->arrayOf ()), | |
391 | size_int (len), build_address (decl)); | |
392 | this->layout_field (value); | |
393 | } | |
394 | ||
395 | ||
396 | /* Write out the __vptr and __monitor fields of class CD. */ | |
397 | ||
398 | void layout_base (ClassDeclaration *cd) | |
399 | { | |
400 | gcc_assert (cd != NULL); | |
c0aebc60 IB |
401 | |
402 | if (have_typeinfo_p (cd)) | |
403 | this->layout_field (build_address (get_vtable_decl (cd))); | |
404 | else | |
405 | this->layout_field (null_pointer_node); | |
406 | ||
b4c522fa IB |
407 | this->layout_field (null_pointer_node); |
408 | } | |
409 | ||
410 | /* Write out the interfaces field of class CD. | |
411 | Returns the array of interfaces that the field is pointing to. */ | |
412 | ||
413 | tree layout_interfaces (ClassDeclaration *cd) | |
414 | { | |
415 | size_t offset = int_size_in_bytes (tinfo_types[TK_CLASSINFO_TYPE]); | |
416 | tree csym = build_address (get_classinfo_decl (cd)); | |
417 | ||
418 | /* Put out the offset to where vtblInterfaces are written. */ | |
419 | tree value = d_array_value (array_type_node, | |
2cbc99d1 | 420 | size_int (cd->vtblInterfaces->length), |
b4c522fa IB |
421 | build_offset (csym, size_int (offset))); |
422 | this->layout_field (value); | |
423 | ||
424 | /* Internally, the compiler sees Interface as: | |
425 | void*[4] interface; | |
426 | ||
427 | The run-time layout of Interface is: | |
428 | TypeInfo_Class classinfo; | |
429 | void*[] vtbl; | |
430 | size_t offset; */ | |
431 | vec<constructor_elt, va_gc> *elms = NULL; | |
432 | ||
2cbc99d1 | 433 | for (size_t i = 0; i < cd->vtblInterfaces->length; i++) |
b4c522fa IB |
434 | { |
435 | BaseClass *b = (*cd->vtblInterfaces)[i]; | |
436 | ClassDeclaration *id = b->sym; | |
437 | vec<constructor_elt, va_gc> *v = NULL; | |
438 | ||
439 | /* Fill in the vtbl[]. */ | |
440 | if (!cd->isInterfaceDeclaration ()) | |
441 | b->fillVtbl (cd, &b->vtbl, 1); | |
442 | ||
443 | /* ClassInfo for the interface. */ | |
444 | value = build_address (get_classinfo_decl (id)); | |
445 | CONSTRUCTOR_APPEND_ELT (v, size_int (0), value); | |
446 | ||
447 | if (!cd->isInterfaceDeclaration ()) | |
448 | { | |
449 | /* The vtable of the interface length and ptr. */ | |
450 | unsigned voffset = base_vtable_offset (cd, b); | |
451 | gcc_assert (voffset != 0u); | |
452 | value = build_offset (csym, size_int (voffset)); | |
453 | ||
275bef5f IB |
454 | CONSTRUCTOR_APPEND_ELT (v, size_int (1), |
455 | size_int (id->vtbl.length)); | |
b4c522fa IB |
456 | CONSTRUCTOR_APPEND_ELT (v, size_int (2), value); |
457 | } | |
458 | ||
459 | /* The 'this' offset. */ | |
460 | CONSTRUCTOR_APPEND_ELT (v, size_int (3), size_int (b->offset)); | |
461 | ||
462 | /* Add to the array of interfaces. */ | |
463 | value = build_constructor (vtbl_interface_type_node, v); | |
464 | CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value); | |
465 | } | |
466 | ||
2cbc99d1 | 467 | tree domain = size_int (cd->vtblInterfaces->length - 1); |
b4c522fa IB |
468 | tree arrtype = build_array_type (vtbl_interface_type_node, |
469 | build_index_type (domain)); | |
470 | return build_constructor (arrtype, elms); | |
471 | } | |
472 | ||
473 | /* Write out the interfacing vtable[] of base class BCD that will be accessed | |
474 | from the overriding class CD. If both are the same class, then this will | |
475 | be its own vtable. INDEX is the offset in the interfaces array of the | |
476 | base class where the Interface reference can be found. | |
477 | This must be mirrored with base_vtable_offset(). */ | |
478 | ||
479 | void layout_base_vtable (ClassDeclaration *cd, ClassDeclaration *bcd, | |
480 | size_t index) | |
481 | { | |
482 | BaseClass *bs = (*bcd->vtblInterfaces)[index]; | |
483 | ClassDeclaration *id = bs->sym; | |
484 | vec<constructor_elt, va_gc> *elms = NULL; | |
485 | FuncDeclarations bvtbl; | |
486 | ||
2cbc99d1 | 487 | if (id->vtbl.length == 0 || base_vtable_offset (cd, bs) == ~0u) |
b4c522fa IB |
488 | return; |
489 | ||
490 | /* Fill bvtbl with the functions we want to put out. */ | |
491 | if (cd != bcd && !bs->fillVtbl (cd, &bvtbl, 0)) | |
492 | return; | |
493 | ||
494 | /* First entry is struct Interface reference. */ | |
495 | if (id->vtblOffset ()) | |
496 | { | |
497 | size_t offset = int_size_in_bytes (tinfo_types[TK_CLASSINFO_TYPE]); | |
498 | offset += (index * int_size_in_bytes (vtbl_interface_type_node)); | |
499 | tree value = build_offset (build_address (get_classinfo_decl (bcd)), | |
500 | size_int (offset)); | |
501 | CONSTRUCTOR_APPEND_ELT (elms, size_zero_node, value); | |
502 | } | |
503 | ||
2cbc99d1 | 504 | for (size_t i = id->vtblOffset () ? 1 : 0; i < id->vtbl.length; i++) |
b4c522fa IB |
505 | { |
506 | FuncDeclaration *fd = (cd == bcd) ? bs->vtbl[i] : bvtbl[i]; | |
507 | if (fd != NULL) | |
508 | { | |
509 | tree value = build_address (make_thunk (fd, bs->offset)); | |
510 | CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value); | |
511 | } | |
512 | } | |
513 | ||
2cbc99d1 | 514 | tree vtbldomain = build_index_type (size_int (id->vtbl.length - 1)); |
b4c522fa IB |
515 | tree vtbltype = build_array_type (vtable_entry_type, vtbldomain); |
516 | tree value = build_constructor (vtbltype, elms); | |
517 | this->layout_field (value); | |
518 | } | |
519 | ||
520 | ||
521 | public: | |
98eb7b2e | 522 | TypeInfoVisitor (tree decl) |
b4c522fa | 523 | { |
98eb7b2e | 524 | this->decl_ = decl; |
b4c522fa IB |
525 | this->init_ = NULL; |
526 | } | |
527 | ||
528 | /* Return the completed constructor for the TypeInfo record. */ | |
529 | ||
530 | tree result (void) | |
531 | { | |
98eb7b2e | 532 | return build_struct_literal (TREE_TYPE (this->decl_), this->init_); |
b4c522fa IB |
533 | } |
534 | ||
535 | /* Layout of TypeInfo is: | |
536 | void **__vptr; | |
537 | void *__monitor; */ | |
538 | ||
539 | void visit (TypeInfoDeclaration *) | |
540 | { | |
541 | /* The vtable for TypeInfo. */ | |
542 | this->layout_base (Type::dtypeinfo); | |
543 | } | |
544 | ||
545 | /* Layout of TypeInfo_Const is: | |
546 | void **__vptr; | |
547 | void *__monitor; | |
548 | TypeInfo base; */ | |
549 | ||
550 | void visit (TypeInfoConstDeclaration *d) | |
551 | { | |
552 | Type *tm = d->tinfo->mutableOf (); | |
553 | tm = tm->merge2 (); | |
554 | ||
555 | /* The vtable for TypeInfo_Const. */ | |
556 | this->layout_base (Type::typeinfoconst); | |
557 | ||
558 | /* TypeInfo for the mutable type. */ | |
c0aebc60 | 559 | this->layout_field (build_typeinfo (d->loc, tm)); |
b4c522fa IB |
560 | } |
561 | ||
562 | /* Layout of TypeInfo_Immutable is: | |
563 | void **__vptr; | |
564 | void *__monitor; | |
565 | TypeInfo base; */ | |
566 | ||
567 | void visit (TypeInfoInvariantDeclaration *d) | |
568 | { | |
569 | Type *tm = d->tinfo->mutableOf (); | |
570 | tm = tm->merge2 (); | |
571 | ||
572 | /* The vtable for TypeInfo_Invariant. */ | |
573 | this->layout_base (Type::typeinfoinvariant); | |
574 | ||
575 | /* TypeInfo for the mutable type. */ | |
c0aebc60 | 576 | this->layout_field (build_typeinfo (d->loc, tm)); |
b4c522fa IB |
577 | } |
578 | ||
579 | /* Layout of TypeInfo_Shared is: | |
580 | void **__vptr; | |
581 | void *__monitor; | |
582 | TypeInfo base; */ | |
583 | ||
584 | void visit (TypeInfoSharedDeclaration *d) | |
585 | { | |
586 | Type *tm = d->tinfo->unSharedOf (); | |
587 | tm = tm->merge2 (); | |
588 | ||
589 | /* The vtable for TypeInfo_Shared. */ | |
590 | this->layout_base (Type::typeinfoshared); | |
591 | ||
592 | /* TypeInfo for the unshared type. */ | |
c0aebc60 | 593 | this->layout_field (build_typeinfo (d->loc, tm)); |
b4c522fa IB |
594 | } |
595 | ||
596 | /* Layout of TypeInfo_Inout is: | |
597 | void **__vptr; | |
598 | void *__monitor; | |
599 | TypeInfo base; */ | |
600 | ||
601 | void visit (TypeInfoWildDeclaration *d) | |
602 | { | |
603 | Type *tm = d->tinfo->mutableOf (); | |
604 | tm = tm->merge2 (); | |
605 | ||
606 | /* The vtable for TypeInfo_Inout. */ | |
607 | this->layout_base (Type::typeinfowild); | |
608 | ||
609 | /* TypeInfo for the mutable type. */ | |
c0aebc60 | 610 | this->layout_field (build_typeinfo (d->loc, tm)); |
b4c522fa IB |
611 | } |
612 | ||
613 | /* Layout of TypeInfo_Enum is: | |
614 | void **__vptr; | |
615 | void *__monitor; | |
616 | TypeInfo base; | |
617 | string name; | |
618 | void[] m_init; */ | |
619 | ||
620 | void visit (TypeInfoEnumDeclaration *d) | |
621 | { | |
89fdaf5a | 622 | TypeEnum *ti = d->tinfo->isTypeEnum (); |
b4c522fa IB |
623 | EnumDeclaration *ed = ti->sym; |
624 | ||
625 | /* The vtable for TypeInfo_Enum. */ | |
626 | this->layout_base (Type::typeinfoenum); | |
627 | ||
628 | /* TypeInfo for enum members. */ | |
c0aebc60 | 629 | tree memtype = (ed->memtype) ? build_typeinfo (d->loc, ed->memtype) |
b4c522fa IB |
630 | : null_pointer_node; |
631 | this->layout_field (memtype); | |
632 | ||
633 | /* Name of the enum declaration. */ | |
634 | this->layout_string (ed->toPrettyChars ()); | |
635 | ||
636 | /* Default initializer for enum. */ | |
637 | if (ed->members && !d->tinfo->isZeroInit ()) | |
638 | { | |
639 | tree length = size_int (ed->type->size ()); | |
640 | tree ptr = build_address (enum_initializer_decl (ed)); | |
641 | this->layout_field (d_array_value (array_type_node, length, ptr)); | |
642 | } | |
643 | else | |
644 | this->layout_field (null_array_node); | |
645 | } | |
646 | ||
647 | /* Layout of TypeInfo_Pointer is: | |
648 | void **__vptr; | |
649 | void *__monitor; | |
650 | TypeInfo m_next; */ | |
651 | ||
652 | void visit (TypeInfoPointerDeclaration *d) | |
653 | { | |
89fdaf5a | 654 | TypePointer *ti = d->tinfo->isTypePointer (); |
b4c522fa IB |
655 | |
656 | /* The vtable for TypeInfo_Pointer. */ | |
657 | this->layout_base (Type::typeinfopointer); | |
658 | ||
659 | /* TypeInfo for pointer-to type. */ | |
c0aebc60 | 660 | this->layout_field (build_typeinfo (d->loc, ti->next)); |
b4c522fa IB |
661 | } |
662 | ||
663 | /* Layout of TypeInfo_Array is: | |
664 | void **__vptr; | |
665 | void *__monitor; | |
666 | TypeInfo value; */ | |
667 | ||
668 | void visit (TypeInfoArrayDeclaration *d) | |
669 | { | |
89fdaf5a | 670 | TypeDArray *ti = d->tinfo->isTypeDArray (); |
b4c522fa IB |
671 | |
672 | /* The vtable for TypeInfo_Array. */ | |
673 | this->layout_base (Type::typeinfoarray); | |
674 | ||
675 | /* TypeInfo for array of type. */ | |
c0aebc60 | 676 | this->layout_field (build_typeinfo (d->loc, ti->next)); |
b4c522fa IB |
677 | } |
678 | ||
679 | /* Layout of TypeInfo_StaticArray is: | |
680 | void **__vptr; | |
681 | void *__monitor; | |
682 | TypeInfo value; | |
683 | size_t len; */ | |
684 | ||
685 | void visit (TypeInfoStaticArrayDeclaration *d) | |
686 | { | |
89fdaf5a | 687 | TypeSArray *ti = d->tinfo->isTypeSArray (); |
b4c522fa IB |
688 | |
689 | /* The vtable for TypeInfo_StaticArray. */ | |
690 | this->layout_base (Type::typeinfostaticarray); | |
691 | ||
692 | /* TypeInfo for array of type. */ | |
c0aebc60 | 693 | this->layout_field (build_typeinfo (d->loc, ti->next)); |
b4c522fa IB |
694 | |
695 | /* Static array length. */ | |
696 | this->layout_field (size_int (ti->dim->toInteger ())); | |
697 | } | |
698 | ||
699 | /* Layout of TypeInfo_AssociativeArray is: | |
700 | void **__vptr; | |
701 | void *__monitor; | |
702 | TypeInfo value; | |
703 | TypeInfo key; */ | |
704 | ||
705 | void visit (TypeInfoAssociativeArrayDeclaration *d) | |
706 | { | |
89fdaf5a | 707 | TypeAArray *ti = d->tinfo->isTypeAArray (); |
b4c522fa IB |
708 | |
709 | /* The vtable for TypeInfo_AssociativeArray. */ | |
710 | this->layout_base (Type::typeinfoassociativearray); | |
711 | ||
712 | /* TypeInfo for value of type. */ | |
c0aebc60 | 713 | this->layout_field (build_typeinfo (d->loc, ti->next)); |
b4c522fa IB |
714 | |
715 | /* TypeInfo for index of type. */ | |
c0aebc60 | 716 | this->layout_field (build_typeinfo (d->loc, ti->index)); |
b4c522fa IB |
717 | } |
718 | ||
719 | /* Layout of TypeInfo_Vector is: | |
720 | void **__vptr; | |
721 | void *__monitor; | |
722 | TypeInfo base; */ | |
723 | ||
724 | void visit (TypeInfoVectorDeclaration *d) | |
725 | { | |
89fdaf5a | 726 | TypeVector *ti = d->tinfo->isTypeVector (); |
b4c522fa IB |
727 | |
728 | /* The vtable for TypeInfo_Vector. */ | |
729 | this->layout_base (Type::typeinfovector); | |
730 | ||
731 | /* TypeInfo for equivalent static array. */ | |
c0aebc60 | 732 | this->layout_field (build_typeinfo (d->loc, ti->basetype)); |
b4c522fa IB |
733 | } |
734 | ||
735 | /* Layout of TypeInfo_Function is: | |
736 | void **__vptr; | |
737 | void *__monitor; | |
738 | TypeInfo next; | |
739 | string deco; */ | |
740 | ||
741 | void visit (TypeInfoFunctionDeclaration *d) | |
742 | { | |
89fdaf5a IB |
743 | TypeFunction *ti = d->tinfo->isTypeFunction (); |
744 | gcc_assert (ti->deco != NULL); | |
b4c522fa IB |
745 | |
746 | /* The vtable for TypeInfo_Function. */ | |
747 | this->layout_base (Type::typeinfofunction); | |
748 | ||
749 | /* TypeInfo for function return value. */ | |
c0aebc60 | 750 | this->layout_field (build_typeinfo (d->loc, ti->next)); |
b4c522fa IB |
751 | |
752 | /* Mangled name of function declaration. */ | |
753 | this->layout_string (d->tinfo->deco); | |
754 | } | |
755 | ||
756 | /* Layout of TypeInfo_Delegate is: | |
757 | void **__vptr; | |
758 | void *__monitor; | |
759 | TypeInfo next; | |
760 | string deco; */ | |
761 | ||
762 | void visit (TypeInfoDelegateDeclaration *d) | |
763 | { | |
89fdaf5a IB |
764 | TypeDelegate *ti = d->tinfo->isTypeDelegate (); |
765 | gcc_assert (ti->deco != NULL); | |
b4c522fa IB |
766 | |
767 | /* The vtable for TypeInfo_Delegate. */ | |
768 | this->layout_base (Type::typeinfodelegate); | |
769 | ||
770 | /* TypeInfo for delegate return value. */ | |
c0aebc60 | 771 | this->layout_field (build_typeinfo (d->loc, ti->next)); |
b4c522fa IB |
772 | |
773 | /* Mangled name of delegate declaration. */ | |
774 | this->layout_string (d->tinfo->deco); | |
775 | } | |
776 | ||
777 | /* Layout of ClassInfo/TypeInfo_Class is: | |
778 | void **__vptr; | |
779 | void *__monitor; | |
780 | byte[] m_init; | |
781 | string name; | |
782 | void*[] vtbl; | |
783 | Interface[] interfaces; | |
784 | TypeInfo_Class base; | |
785 | void *destructor; | |
786 | void function(Object) classInvariant; | |
787 | ClassFlags m_flags; | |
788 | void *deallocator; | |
789 | OffsetTypeInfo[] m_offTi; | |
790 | void function(Object) defaultConstructor; | |
791 | immutable(void)* m_RTInfo; | |
792 | ||
793 | Information relating to interfaces, and their vtables are laid out | |
794 | immediately after the named fields, if there is anything to write. */ | |
795 | ||
796 | void visit (TypeInfoClassDeclaration *d) | |
797 | { | |
89fdaf5a | 798 | TypeClass *ti = d->tinfo->isTypeClass (); |
b4c522fa IB |
799 | ClassDeclaration *cd = ti->sym; |
800 | ||
801 | /* The vtable for ClassInfo. */ | |
802 | this->layout_base (Type::typeinfoclass); | |
803 | ||
804 | if (!cd->members) | |
805 | return; | |
806 | ||
807 | tree interfaces = NULL_TREE; | |
808 | ||
809 | if (!cd->isInterfaceDeclaration ()) | |
810 | { | |
811 | /* Default initializer for class. */ | |
812 | tree init = aggregate_initializer_decl (cd); | |
813 | tree value = d_array_value (array_type_node, size_int (cd->structsize), | |
814 | build_address (init)); | |
815 | this->layout_field (value); | |
816 | ||
817 | /* Name of the class declaration. */ | |
818 | const char *name = cd->ident->toChars (); | |
819 | if (!(strlen (name) > 9 && memcmp (name, "TypeInfo_", 9) == 0)) | |
820 | name = cd->toPrettyChars (); | |
821 | this->layout_string (name); | |
822 | ||
823 | /* The vtable of the class declaration. */ | |
2cbc99d1 | 824 | value = d_array_value (array_type_node, size_int (cd->vtbl.length), |
b4c522fa IB |
825 | build_address (get_vtable_decl (cd))); |
826 | this->layout_field (value); | |
827 | ||
828 | /* Array of base interfaces that have their own vtable. */ | |
2cbc99d1 | 829 | if (cd->vtblInterfaces->length) |
b4c522fa IB |
830 | interfaces = this->layout_interfaces (cd); |
831 | else | |
832 | this->layout_field (null_array_node); | |
833 | ||
834 | /* TypeInfo_Class base; */ | |
835 | tree base = (cd->baseClass) | |
836 | ? build_address (get_classinfo_decl (cd->baseClass)) | |
837 | : null_pointer_node; | |
838 | this->layout_field (base); | |
839 | ||
840 | /* void *destructor; */ | |
841 | tree dtor = (cd->dtor) ? build_address (get_symbol_decl (cd->dtor)) | |
842 | : null_pointer_node; | |
843 | this->layout_field (dtor); | |
844 | ||
845 | /* void function(Object) classInvariant; */ | |
846 | tree inv = (cd->inv) ? build_address (get_symbol_decl (cd->inv)) | |
847 | : null_pointer_node; | |
848 | this->layout_field (inv); | |
849 | ||
850 | /* ClassFlags m_flags; */ | |
851 | ClassFlags::Type flags = ClassFlags::hasOffTi; | |
852 | if (cd->isCOMclass ()) | |
853 | flags |= ClassFlags::isCOMclass; | |
854 | ||
855 | if (cd->isCPPclass ()) | |
856 | flags |= ClassFlags::isCPPclass; | |
857 | ||
858 | flags |= ClassFlags::hasGetMembers; | |
859 | flags |= ClassFlags::hasTypeInfo; | |
860 | ||
861 | if (cd->ctor) | |
862 | flags |= ClassFlags::hasCtor; | |
863 | ||
864 | for (ClassDeclaration *bcd = cd; bcd; bcd = bcd->baseClass) | |
865 | { | |
866 | if (bcd->dtor) | |
867 | { | |
868 | flags |= ClassFlags::hasDtor; | |
869 | break; | |
870 | } | |
871 | } | |
872 | ||
873 | if (cd->isAbstract ()) | |
874 | flags |= ClassFlags::isAbstract; | |
875 | ||
876 | for (ClassDeclaration *bcd = cd; bcd; bcd = bcd->baseClass) | |
877 | { | |
878 | if (!bcd->members) | |
879 | continue; | |
880 | ||
2cbc99d1 | 881 | for (size_t i = 0; i < bcd->members->length; i++) |
b4c522fa IB |
882 | { |
883 | Dsymbol *sm = (*bcd->members)[i]; | |
884 | if (sm->hasPointers ()) | |
885 | goto Lhaspointers; | |
886 | } | |
887 | } | |
888 | ||
889 | flags |= ClassFlags::noPointers; | |
890 | ||
891 | Lhaspointers: | |
130cc10e | 892 | this->layout_field (build_integer_cst (flags, d_uint_type)); |
b4c522fa IB |
893 | |
894 | /* void *deallocator; */ | |
895 | tree ddtor = (cd->aggDelete) | |
896 | ? build_address (get_symbol_decl (cd->aggDelete)) | |
897 | : null_pointer_node; | |
898 | this->layout_field (ddtor); | |
899 | ||
900 | /* OffsetTypeInfo[] m_offTi; (not implemented) */ | |
901 | this->layout_field (null_array_node); | |
902 | ||
903 | /* void function(Object) defaultConstructor; */ | |
904 | if (cd->defaultCtor && !(cd->defaultCtor->storage_class & STCdisable)) | |
905 | { | |
906 | tree dctor = get_symbol_decl (cd->defaultCtor); | |
907 | this->layout_field (build_address (dctor)); | |
908 | } | |
909 | else | |
910 | this->layout_field (null_pointer_node); | |
911 | ||
912 | /* immutable(void)* m_RTInfo; */ | |
913 | if (cd->getRTInfo) | |
914 | this->layout_field (build_expr (cd->getRTInfo, true)); | |
915 | else if (!(flags & ClassFlags::noPointers)) | |
916 | this->layout_field (size_one_node); | |
917 | } | |
918 | else | |
919 | { | |
920 | /* No initializer for interface. */ | |
921 | this->layout_field (null_array_node); | |
922 | ||
923 | /* Name of the interface declaration. */ | |
924 | this->layout_string (cd->toPrettyChars ()); | |
925 | ||
926 | /* No vtable for interface declaration. */ | |
927 | this->layout_field (null_array_node); | |
928 | ||
929 | /* Array of base interfaces that have their own vtable. */ | |
2cbc99d1 | 930 | if (cd->vtblInterfaces->length) |
b4c522fa IB |
931 | interfaces = this->layout_interfaces (cd); |
932 | else | |
933 | this->layout_field (null_array_node); | |
934 | ||
935 | /* TypeInfo_Class base; | |
936 | void *destructor; | |
937 | void function(Object) classInvariant; */ | |
938 | this->layout_field (null_pointer_node); | |
939 | this->layout_field (null_pointer_node); | |
940 | this->layout_field (null_pointer_node); | |
941 | ||
942 | /* ClassFlags m_flags; */ | |
943 | ClassFlags::Type flags = ClassFlags::hasOffTi; | |
944 | flags |= ClassFlags::hasTypeInfo; | |
945 | if (cd->isCOMinterface ()) | |
946 | flags |= ClassFlags::isCOMclass; | |
947 | ||
130cc10e | 948 | this->layout_field (build_integer_cst (flags, d_uint_type)); |
b4c522fa IB |
949 | |
950 | /* void *deallocator; | |
951 | OffsetTypeInfo[] m_offTi; (not implemented) | |
952 | void function(Object) defaultConstructor; */ | |
953 | this->layout_field (null_pointer_node); | |
954 | this->layout_field (null_array_node); | |
955 | this->layout_field (null_pointer_node); | |
956 | ||
957 | /* immutable(void)* m_RTInfo; */ | |
958 | if (cd->getRTInfo) | |
959 | this->layout_field (build_expr (cd->getRTInfo, true)); | |
960 | else | |
961 | this->layout_field (null_pointer_node); | |
962 | } | |
963 | ||
964 | /* Put out array of Interfaces. */ | |
965 | if (interfaces != NULL_TREE) | |
966 | this->layout_field (interfaces); | |
967 | ||
968 | if (!cd->isInterfaceDeclaration ()) | |
969 | { | |
970 | /* Put out this class' interface vtables[]. */ | |
2cbc99d1 | 971 | for (size_t i = 0; i < cd->vtblInterfaces->length; i++) |
b4c522fa IB |
972 | this->layout_base_vtable (cd, cd, i); |
973 | ||
974 | /* Put out the overriding interface vtables[]. */ | |
975 | for (ClassDeclaration *bcd = cd->baseClass; bcd; bcd = bcd->baseClass) | |
976 | { | |
2cbc99d1 | 977 | for (size_t i = 0; i < bcd->vtblInterfaces->length; i++) |
b4c522fa IB |
978 | this->layout_base_vtable (cd, bcd, i); |
979 | } | |
980 | } | |
981 | } | |
982 | ||
983 | /* Layout of TypeInfo_Interface is: | |
984 | void **__vptr; | |
985 | void *__monitor; | |
986 | TypeInfo_Class info; */ | |
987 | ||
988 | void visit (TypeInfoInterfaceDeclaration *d) | |
989 | { | |
89fdaf5a | 990 | TypeClass *ti = d->tinfo->isTypeClass (); |
b4c522fa IB |
991 | |
992 | if (!ti->sym->vclassinfo) | |
993 | ti->sym->vclassinfo = TypeInfoClassDeclaration::create (ti); | |
994 | ||
995 | /* The vtable for TypeInfo_Interface. */ | |
996 | this->layout_base (Type::typeinfointerface); | |
997 | ||
998 | /* TypeInfo for class inheriting the interface. */ | |
999 | tree tidecl = get_typeinfo_decl (ti->sym->vclassinfo); | |
1000 | this->layout_field (build_address (tidecl)); | |
1001 | } | |
1002 | ||
1003 | /* Layout of TypeInfo_Struct is: | |
1004 | void **__vptr; | |
1005 | void *__monitor; | |
1006 | string name; | |
1007 | void[] m_init; | |
1008 | hash_t function(in void*) xtoHash; | |
1009 | bool function(in void*, in void*) xopEquals; | |
1010 | int function(in void*, in void*) xopCmp; | |
1011 | string function(const(void)*) xtoString; | |
1012 | StructFlags m_flags; | |
1013 | void function(void*) xdtor; | |
1014 | void function(void*) xpostblit; | |
1015 | uint m_align; | |
1016 | version (X86_64) | |
1017 | TypeInfo m_arg1; | |
1018 | TypeInfo m_arg2; | |
1019 | immutable(void)* xgetRTInfo; */ | |
1020 | ||
1021 | void visit (TypeInfoStructDeclaration *d) | |
1022 | { | |
89fdaf5a | 1023 | TypeStruct *ti = d->tinfo->isTypeStruct (); |
b4c522fa IB |
1024 | StructDeclaration *sd = ti->sym; |
1025 | ||
1026 | /* The vtable for TypeInfo_Struct. */ | |
1027 | this->layout_base (Type::typeinfostruct); | |
1028 | ||
1029 | if (!sd->members) | |
1030 | return; | |
1031 | ||
1032 | /* Name of the struct declaration. */ | |
1033 | this->layout_string (sd->toPrettyChars ()); | |
1034 | ||
1035 | /* Default initializer for struct. */ | |
1036 | tree ptr = (sd->zeroInit) ? null_pointer_node | |
1037 | : build_address (aggregate_initializer_decl (sd)); | |
1038 | this->layout_field (d_array_value (array_type_node, | |
1039 | size_int (sd->structsize), ptr)); | |
1040 | ||
1041 | /* hash_t function (in void*) xtoHash; */ | |
1042 | tree xhash = (sd->xhash) ? build_address (get_symbol_decl (sd->xhash)) | |
1043 | : null_pointer_node; | |
1044 | this->layout_field (xhash); | |
1045 | ||
1046 | if (sd->xhash) | |
1047 | { | |
1048 | TypeFunction *tf = (TypeFunction *) sd->xhash->type; | |
1049 | gcc_assert (tf->ty == Tfunction); | |
1050 | if (!tf->isnothrow || tf->trust == TRUSTsystem) | |
1051 | { | |
1052 | warning (sd->xhash->loc, "toHash() must be declared as " | |
1053 | "extern (D) size_t toHash() const nothrow @safe, " | |
1054 | "not %s", tf->toChars ()); | |
1055 | } | |
1056 | } | |
1057 | ||
1058 | /* bool function(in void*, in void*) xopEquals; */ | |
1059 | tree xeq = (sd->xeq) ? build_address (get_symbol_decl (sd->xeq)) | |
1060 | : null_pointer_node; | |
1061 | this->layout_field (xeq); | |
1062 | ||
1063 | /* int function(in void*, in void*) xopCmp; */ | |
1064 | tree xcmp = (sd->xcmp) ? build_address (get_symbol_decl (sd->xcmp)) | |
1065 | : null_pointer_node; | |
1066 | this->layout_field (xcmp); | |
1067 | ||
1068 | /* string function(const(void)*) xtoString; */ | |
1069 | FuncDeclaration *fdx = search_toString (sd); | |
1070 | if (fdx) | |
1071 | this->layout_field (build_address (get_symbol_decl (fdx))); | |
1072 | else | |
1073 | this->layout_field (null_pointer_node); | |
1074 | ||
1075 | /* StructFlags m_flags; */ | |
1076 | StructFlags::Type m_flags = 0; | |
1077 | if (ti->hasPointers ()) | |
1078 | m_flags |= StructFlags::hasPointers; | |
130cc10e | 1079 | this->layout_field (build_integer_cst (m_flags, d_uint_type)); |
b4c522fa IB |
1080 | |
1081 | /* void function(void*) xdtor; */ | |
1082 | tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor)) | |
1083 | : null_pointer_node; | |
1084 | this->layout_field (dtor); | |
1085 | ||
1086 | /* void function(void*) xpostblit; */ | |
1087 | if (sd->postblit && !(sd->postblit->storage_class & STCdisable)) | |
1088 | this->layout_field (build_address (get_symbol_decl (sd->postblit))); | |
1089 | else | |
1090 | this->layout_field (null_pointer_node); | |
1091 | ||
1092 | /* uint m_align; */ | |
130cc10e | 1093 | this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type)); |
b4c522fa IB |
1094 | |
1095 | if (global.params.is64bit) | |
1096 | { | |
1097 | /* TypeInfo m_arg1; */ | |
c0aebc60 | 1098 | tree arg1type = (sd->arg1type) ? build_typeinfo (d->loc, sd->arg1type) |
b4c522fa IB |
1099 | : null_pointer_node; |
1100 | this->layout_field (arg1type); | |
1101 | ||
1102 | /* TypeInfo m_arg2; */ | |
c0aebc60 | 1103 | tree arg2type = (sd->arg2type) ? build_typeinfo (d->loc, sd->arg2type) |
b4c522fa IB |
1104 | : null_pointer_node; |
1105 | this->layout_field (arg2type); | |
1106 | } | |
1107 | ||
1108 | /* immutable(void)* xgetRTInfo; */ | |
1109 | if (sd->getRTInfo) | |
1110 | this->layout_field (build_expr (sd->getRTInfo, true)); | |
1111 | else if (m_flags & StructFlags::hasPointers) | |
1112 | this->layout_field (size_one_node); | |
1113 | } | |
1114 | ||
1115 | /* Layout of TypeInfo_Tuple is: | |
1116 | void **__vptr; | |
1117 | void *__monitor; | |
1118 | TypeInfo[] elements; */ | |
1119 | ||
1120 | void visit (TypeInfoTupleDeclaration *d) | |
1121 | { | |
89fdaf5a | 1122 | TypeTuple *ti = d->tinfo->isTypeTuple (); |
b4c522fa IB |
1123 | |
1124 | /* The vtable for TypeInfo_Tuple. */ | |
1125 | this->layout_base (Type::typeinfotypelist); | |
1126 | ||
1127 | /* TypeInfo[] elements; */ | |
2cbc99d1 | 1128 | Type *satype = Type::tvoidptr->sarrayOf (ti->arguments->length); |
b4c522fa | 1129 | vec<constructor_elt, va_gc> *elms = NULL; |
2cbc99d1 | 1130 | for (size_t i = 0; i < ti->arguments->length; i++) |
b4c522fa IB |
1131 | { |
1132 | Parameter *arg = (*ti->arguments)[i]; | |
1133 | CONSTRUCTOR_APPEND_ELT (elms, size_int (i), | |
c0aebc60 | 1134 | build_typeinfo (d->loc, arg->type)); |
b4c522fa IB |
1135 | } |
1136 | tree ctor = build_constructor (build_ctype (satype), elms); | |
98eb7b2e | 1137 | tree decl = this->internal_reference (ctor); |
b4c522fa | 1138 | |
2cbc99d1 | 1139 | tree length = size_int (ti->arguments->length); |
b4c522fa IB |
1140 | tree ptr = build_address (decl); |
1141 | this->layout_field (d_array_value (array_type_node, length, ptr)); | |
1142 | ||
b4c522fa IB |
1143 | rest_of_decl_compilation (decl, 1, 0); |
1144 | } | |
1145 | }; | |
1146 | ||
1147 | ||
1148 | /* Main entry point for TypeInfoVisitor interface to generate | |
1149 | TypeInfo constructor for the TypeInfoDeclaration AST class D. */ | |
1150 | ||
1151 | tree | |
1152 | layout_typeinfo (TypeInfoDeclaration *d) | |
1153 | { | |
88ad43b1 IB |
1154 | if (!Type::dtypeinfo) |
1155 | create_frontend_tinfo_types (); | |
1156 | ||
98eb7b2e | 1157 | TypeInfoVisitor v = TypeInfoVisitor (get_typeinfo_decl (d)); |
b4c522fa IB |
1158 | d->accept (&v); |
1159 | return v.result (); | |
1160 | } | |
1161 | ||
1162 | /* Like layout_typeinfo, but generates the TypeInfo_Class for | |
1163 | the class or interface declaration CD. */ | |
1164 | ||
1165 | tree | |
1166 | layout_classinfo (ClassDeclaration *cd) | |
1167 | { | |
88ad43b1 IB |
1168 | if (!Type::dtypeinfo) |
1169 | create_frontend_tinfo_types (); | |
1170 | ||
b4c522fa | 1171 | TypeInfoClassDeclaration *d = TypeInfoClassDeclaration::create (cd->type); |
98eb7b2e | 1172 | TypeInfoVisitor v = TypeInfoVisitor (get_classinfo_decl (cd)); |
b4c522fa IB |
1173 | d->accept (&v); |
1174 | return v.result (); | |
1175 | } | |
1176 | ||
1177 | /* Layout fields that immediately come after the classinfo type for DECL if | |
1178 | there's any interfaces or interface vtables to be added. | |
1179 | This must be mirrored with base_vtable_offset(). */ | |
1180 | ||
1181 | static tree | |
1182 | layout_classinfo_interfaces (ClassDeclaration *decl) | |
1183 | { | |
1184 | tree type = tinfo_types[TK_CLASSINFO_TYPE]; | |
1185 | size_t structsize = int_size_in_bytes (type); | |
1186 | ||
2cbc99d1 | 1187 | if (decl->vtblInterfaces->length) |
b4c522fa IB |
1188 | { |
1189 | size_t interfacesize = int_size_in_bytes (vtbl_interface_type_node); | |
1190 | tree field; | |
1191 | ||
1192 | type = copy_aggregate_type (type); | |
1193 | ||
1194 | /* First layout the static array of Interface, which provides information | |
1195 | about the vtables that follow. */ | |
2cbc99d1 | 1196 | tree domain = size_int (decl->vtblInterfaces->length - 1); |
b4c522fa IB |
1197 | tree arrtype = build_array_type (vtbl_interface_type_node, |
1198 | build_index_type (domain)); | |
1199 | field = create_field_decl (arrtype, NULL, 1, 1); | |
1200 | insert_aggregate_field (type, field, structsize); | |
2cbc99d1 | 1201 | structsize += decl->vtblInterfaces->length * interfacesize; |
b4c522fa IB |
1202 | |
1203 | /* For each interface, layout each vtable. */ | |
2cbc99d1 | 1204 | for (size_t i = 0; i < decl->vtblInterfaces->length; i++) |
b4c522fa IB |
1205 | { |
1206 | BaseClass *b = (*decl->vtblInterfaces)[i]; | |
1207 | ClassDeclaration *id = b->sym; | |
1208 | unsigned offset = base_vtable_offset (decl, b); | |
1209 | ||
2cbc99d1 | 1210 | if (id->vtbl.length && offset != ~0u) |
b4c522fa | 1211 | { |
275bef5f IB |
1212 | tree vtbldomain |
1213 | = build_index_type (size_int (id->vtbl.length - 1)); | |
b4c522fa IB |
1214 | tree vtbltype = build_array_type (vtable_entry_type, vtbldomain); |
1215 | ||
1216 | field = create_field_decl (vtbltype, NULL, 1, 1); | |
1217 | insert_aggregate_field (type, field, offset); | |
5905cbdb | 1218 | structsize += id->vtbl.length * target.ptrsize; |
b4c522fa IB |
1219 | } |
1220 | } | |
1221 | } | |
1222 | ||
1223 | /* Layout the arrays of overriding interface vtables. */ | |
1224 | for (ClassDeclaration *bcd = decl->baseClass; bcd; bcd = bcd->baseClass) | |
1225 | { | |
2cbc99d1 | 1226 | for (size_t i = 0; i < bcd->vtblInterfaces->length; i++) |
b4c522fa IB |
1227 | { |
1228 | BaseClass *b = (*bcd->vtblInterfaces)[i]; | |
1229 | ClassDeclaration *id = b->sym; | |
1230 | unsigned offset = base_vtable_offset (decl, b); | |
1231 | ||
2cbc99d1 | 1232 | if (id->vtbl.length && offset != ~0u) |
b4c522fa IB |
1233 | { |
1234 | if (type == tinfo_types[TK_CLASSINFO_TYPE]) | |
1235 | type = copy_aggregate_type (type); | |
1236 | ||
275bef5f IB |
1237 | tree vtbldomain |
1238 | = build_index_type (size_int (id->vtbl.length - 1)); | |
b4c522fa IB |
1239 | tree vtbltype = build_array_type (vtable_entry_type, vtbldomain); |
1240 | ||
1241 | tree field = create_field_decl (vtbltype, NULL, 1, 1); | |
1242 | insert_aggregate_field (type, field, offset); | |
5905cbdb | 1243 | structsize += id->vtbl.length * target.ptrsize; |
b4c522fa IB |
1244 | } |
1245 | } | |
1246 | } | |
1247 | ||
1248 | /* Update the type size and record mode for the classinfo type. */ | |
1249 | if (type != tinfo_types[TK_CLASSINFO_TYPE]) | |
013fca64 | 1250 | finish_aggregate_type (structsize, TYPE_ALIGN_UNIT (type), type); |
b4c522fa IB |
1251 | |
1252 | return type; | |
1253 | } | |
1254 | ||
1255 | /* Returns true if the TypeInfo for TYPE should be placed in | |
1256 | the runtime library. */ | |
1257 | ||
1258 | static bool | |
1259 | builtin_typeinfo_p (Type *type) | |
1260 | { | |
1261 | if (type->isTypeBasic () || type->ty == Tclass || type->ty == Tnull) | |
1262 | return !type->mod; | |
1263 | ||
1264 | if (type->ty == Tarray) | |
1265 | { | |
1266 | /* Strings are so common, make them builtin. */ | |
1267 | Type *next = type->nextOf (); | |
1268 | return !type->mod | |
1269 | && ((next->isTypeBasic () != NULL && !next->mod) | |
1270 | || (next->ty == Tchar && next->mod == MODimmutable) | |
1271 | || (next->ty == Tchar && next->mod == MODconst)); | |
1272 | } | |
1273 | ||
1274 | return false; | |
1275 | } | |
1276 | ||
1277 | /* Implements a visitor interface to create the decl tree for TypeInfo decls. | |
1278 | TypeInfo_Class objects differ in that they also have information about | |
1279 | the class type packed immediately after the TypeInfo symbol. | |
1280 | ||
1281 | If the frontend had an interface to allow distinguishing being these two | |
1282 | AST types, then that would be better for us. */ | |
1283 | ||
1284 | class TypeInfoDeclVisitor : public Visitor | |
1285 | { | |
1286 | using Visitor::visit; | |
1287 | ||
1288 | public: | |
1289 | TypeInfoDeclVisitor (void) | |
1290 | { | |
1291 | } | |
1292 | ||
1293 | void visit (TypeInfoDeclaration *tid) | |
1294 | { | |
1295 | tree ident = get_identifier (tid->ident->toChars ()); | |
1296 | tree type = tinfo_types[get_typeinfo_kind (tid->tinfo)]; | |
1297 | gcc_assert (type != NULL_TREE); | |
1298 | ||
1299 | tid->csym = declare_extern_var (ident, type); | |
1300 | DECL_LANG_SPECIFIC (tid->csym) = build_lang_decl (tid); | |
1301 | ||
1302 | DECL_CONTEXT (tid->csym) = d_decl_context (tid); | |
1303 | TREE_READONLY (tid->csym) = 1; | |
1304 | ||
1305 | /* Built-in typeinfo will be referenced as one-only. */ | |
1306 | gcc_assert (!tid->isInstantiated ()); | |
1307 | ||
1308 | if (builtin_typeinfo_p (tid->tinfo)) | |
1309 | d_linkonce_linkage (tid->csym); | |
1310 | else | |
1311 | d_comdat_linkage (tid->csym); | |
1312 | } | |
1313 | ||
1314 | void visit (TypeInfoClassDeclaration *tid) | |
1315 | { | |
89fdaf5a | 1316 | TypeClass *tc = tid->tinfo->isTypeClass (); |
b4c522fa IB |
1317 | tid->csym = get_classinfo_decl (tc->sym); |
1318 | } | |
1319 | }; | |
1320 | ||
1321 | /* Get the VAR_DECL of the TypeInfo for DECL. If this does not yet exist, | |
1322 | create it. The TypeInfo decl provides information about the type of a given | |
1323 | expression or object. */ | |
1324 | ||
1325 | tree | |
1326 | get_typeinfo_decl (TypeInfoDeclaration *decl) | |
1327 | { | |
1328 | if (decl->csym) | |
1329 | return decl->csym; | |
1330 | ||
1331 | gcc_assert (decl->tinfo->ty != Terror); | |
1332 | ||
1333 | TypeInfoDeclVisitor v = TypeInfoDeclVisitor (); | |
1334 | decl->accept (&v); | |
1335 | gcc_assert (decl->csym != NULL_TREE); | |
1336 | ||
1337 | return decl->csym; | |
1338 | } | |
1339 | ||
1340 | /* Get the VAR_DECL of the ClassInfo for DECL. If this does not yet exist, | |
1341 | create it. The ClassInfo decl provides information about the dynamic type | |
1342 | of a given class type or object. */ | |
1343 | ||
1344 | tree | |
1345 | get_classinfo_decl (ClassDeclaration *decl) | |
1346 | { | |
1347 | if (decl->csym) | |
1348 | return decl->csym; | |
1349 | ||
1350 | InterfaceDeclaration *id = decl->isInterfaceDeclaration (); | |
1351 | tree ident = mangle_internal_decl (decl, id ? "__Interface" : "__Class", "Z"); | |
1352 | tree type = layout_classinfo_interfaces (decl); | |
1353 | ||
1354 | decl->csym = declare_extern_var (ident, type); | |
1355 | DECL_LANG_SPECIFIC (decl->csym) = build_lang_decl (NULL); | |
1356 | ||
1357 | /* Class is a reference, want the record type. */ | |
1358 | DECL_CONTEXT (decl->csym) = TREE_TYPE (build_ctype (decl->type)); | |
1359 | /* ClassInfo cannot be const data, because we use the monitor on it. */ | |
1360 | TREE_READONLY (decl->csym) = 0; | |
1361 | ||
1362 | return decl->csym; | |
1363 | } | |
1364 | ||
1365 | /* Returns typeinfo reference for TYPE. */ | |
1366 | ||
1367 | tree | |
c0aebc60 | 1368 | build_typeinfo (const Loc &loc, Type *type) |
b4c522fa | 1369 | { |
c0aebc60 IB |
1370 | if (!global.params.useTypeInfo) |
1371 | { | |
1372 | static int warned = 0; | |
1373 | ||
1374 | if (!warned) | |
1375 | { | |
1376 | error_at (make_location_t (loc), | |
a9c697b8 | 1377 | "%<object.TypeInfo%> cannot be used with %<-fno-rtti%>"); |
c0aebc60 IB |
1378 | warned = 1; |
1379 | } | |
1380 | } | |
1381 | ||
b4c522fa IB |
1382 | gcc_assert (type->ty != Terror); |
1383 | create_typeinfo (type, NULL); | |
1384 | return build_address (get_typeinfo_decl (type->vtinfo)); | |
1385 | } | |
1386 | ||
1387 | /* Like layout_classinfo, but generates an Object that wraps around a | |
1388 | pointer to C++ type_info so it can be distinguished from D TypeInfo. */ | |
1389 | ||
1390 | void | |
1391 | layout_cpp_typeinfo (ClassDeclaration *cd) | |
1392 | { | |
88ad43b1 IB |
1393 | if (!Type::dtypeinfo) |
1394 | create_frontend_tinfo_types (); | |
1395 | ||
b4c522fa IB |
1396 | gcc_assert (cd->isCPPclass ()); |
1397 | ||
1398 | tree decl = get_cpp_typeinfo_decl (cd); | |
1399 | vec<constructor_elt, va_gc> *init = NULL; | |
1400 | ||
1401 | /* Use the vtable of __cpp_type_info_ptr, the EH personality routine | |
1402 | expects this, as it uses .classinfo identity comparison to test for | |
1403 | C++ catch handlers. */ | |
1404 | tree vptr = get_vtable_decl (ClassDeclaration::cpp_type_info_ptr); | |
1405 | CONSTRUCTOR_APPEND_ELT (init, NULL_TREE, build_address (vptr)); | |
1406 | CONSTRUCTOR_APPEND_ELT (init, NULL_TREE, null_pointer_node); | |
1407 | ||
1408 | /* Let C++ do the RTTI generation, and just reference the symbol as | |
1409 | extern, knowing the underlying type is not required. */ | |
5905cbdb | 1410 | const char *ident = target.cpp.typeInfoMangle (cd); |
b4c522fa IB |
1411 | tree typeinfo = declare_extern_var (get_identifier (ident), |
1412 | unknown_type_node); | |
1413 | TREE_READONLY (typeinfo) = 1; | |
1414 | CONSTRUCTOR_APPEND_ELT (init, NULL_TREE, build_address (typeinfo)); | |
1415 | ||
1416 | /* Build the initializer and emit. */ | |
1417 | DECL_INITIAL (decl) = build_struct_literal (TREE_TYPE (decl), init); | |
1418 | DECL_EXTERNAL (decl) = 0; | |
1419 | d_pushdecl (decl); | |
1420 | rest_of_decl_compilation (decl, 1, 0); | |
1421 | } | |
1422 | ||
1423 | /* Get the VAR_DECL of the __cpp_type_info_ptr for DECL. If this does not yet | |
1424 | exist, create it. The __cpp_type_info_ptr decl is then initialized with a | |
1425 | pointer to the C++ type_info for the given class. */ | |
1426 | ||
1427 | tree | |
1428 | get_cpp_typeinfo_decl (ClassDeclaration *decl) | |
1429 | { | |
1430 | gcc_assert (decl->isCPPclass ()); | |
1431 | ||
1432 | if (decl->cpp_type_info_ptr_sym) | |
1433 | return decl->cpp_type_info_ptr_sym; | |
1434 | ||
1435 | if (!tinfo_types[TK_CPPTI_TYPE]) | |
1436 | make_internal_typeinfo (TK_CPPTI_TYPE, | |
1437 | Identifier::idPool ("__cpp_type_info_ptr"), | |
1438 | ptr_type_node, NULL); | |
1439 | ||
1440 | tree ident = mangle_internal_decl (decl, "_cpp_type_info_ptr", ""); | |
1441 | tree type = tinfo_types[TK_CPPTI_TYPE]; | |
1442 | ||
1443 | decl->cpp_type_info_ptr_sym = declare_extern_var (ident, type); | |
1444 | DECL_LANG_SPECIFIC (decl->cpp_type_info_ptr_sym) = build_lang_decl (NULL); | |
1445 | ||
1446 | /* Class is a reference, want the record type. */ | |
1447 | DECL_CONTEXT (decl->cpp_type_info_ptr_sym) | |
1448 | = TREE_TYPE (build_ctype (decl->type)); | |
1449 | TREE_READONLY (decl->cpp_type_info_ptr_sym) = 1; | |
1450 | ||
1451 | d_comdat_linkage (decl->cpp_type_info_ptr_sym); | |
1452 | ||
1453 | /* Layout the initializer and emit the symbol. */ | |
1454 | layout_cpp_typeinfo (decl); | |
1455 | ||
1456 | return decl->cpp_type_info_ptr_sym; | |
1457 | } | |
1458 | ||
1459 | /* Get the exact TypeInfo for TYPE, if it doesn't exist, create it. */ | |
1460 | ||
1461 | void | |
1462 | create_typeinfo (Type *type, Module *mod) | |
1463 | { | |
88ad43b1 IB |
1464 | if (!Type::dtypeinfo) |
1465 | create_frontend_tinfo_types (); | |
1466 | ||
b4c522fa IB |
1467 | /* Do this since not all Type's are merged. */ |
1468 | Type *t = type->merge2 (); | |
1469 | Identifier *ident; | |
1470 | ||
1471 | if (!t->vtinfo) | |
1472 | { | |
1473 | tinfo_kind tk = get_typeinfo_kind (t); | |
1474 | switch (tk) | |
1475 | { | |
1476 | case TK_SHARED_TYPE: | |
1477 | case TK_CONST_TYPE: | |
1478 | case TK_IMMUTABLE_TYPE: | |
1479 | case TK_INOUT_TYPE: | |
1480 | case TK_POINTER_TYPE: | |
1481 | case TK_ARRAY_TYPE: | |
1482 | case TK_VECTOR_TYPE: | |
1483 | case TK_INTERFACE_TYPE: | |
1484 | /* Kinds of TypeInfo that add one extra pointer field. */ | |
1485 | if (tk == TK_SHARED_TYPE) | |
1486 | { | |
1487 | /* Does both 'shared' and 'shared const'. */ | |
1488 | t->vtinfo = TypeInfoSharedDeclaration::create (t); | |
1489 | ident = Identifier::idPool ("TypeInfo_Shared"); | |
1490 | } | |
1491 | else if (tk == TK_CONST_TYPE) | |
1492 | { | |
1493 | t->vtinfo = TypeInfoConstDeclaration::create (t); | |
1494 | ident = Identifier::idPool ("TypeInfo_Const"); | |
1495 | } | |
1496 | else if (tk == TK_IMMUTABLE_TYPE) | |
1497 | { | |
1498 | t->vtinfo = TypeInfoInvariantDeclaration::create (t); | |
1499 | ident = Identifier::idPool ("TypeInfo_Invariant"); | |
1500 | } | |
1501 | else if (tk == TK_INOUT_TYPE) | |
1502 | { | |
1503 | t->vtinfo = TypeInfoWildDeclaration::create (t); | |
1504 | ident = Identifier::idPool ("TypeInfo_Wild"); | |
1505 | } | |
1506 | else if (tk == TK_POINTER_TYPE) | |
1507 | { | |
1508 | t->vtinfo = TypeInfoPointerDeclaration::create (t); | |
1509 | ident = Identifier::idPool ("TypeInfo_Pointer"); | |
1510 | } | |
1511 | else if (tk == TK_ARRAY_TYPE) | |
1512 | { | |
1513 | t->vtinfo = TypeInfoArrayDeclaration::create (t); | |
1514 | ident = Identifier::idPool ("TypeInfo_Array"); | |
1515 | } | |
1516 | else if (tk == TK_VECTOR_TYPE) | |
1517 | { | |
1518 | t->vtinfo = TypeInfoVectorDeclaration::create (t); | |
1519 | ident = Identifier::idPool ("TypeInfo_Vector"); | |
1520 | } | |
1521 | else if (tk == TK_INTERFACE_TYPE) | |
1522 | { | |
1523 | t->vtinfo = TypeInfoInterfaceDeclaration::create (t); | |
1524 | ident = Identifier::idPool ("TypeInfo_Interface"); | |
1525 | } | |
1526 | else | |
1527 | gcc_unreachable (); | |
1528 | ||
1529 | if (!tinfo_types[tk]) | |
1530 | make_internal_typeinfo (tk, ident, ptr_type_node, NULL); | |
1531 | break; | |
1532 | ||
1533 | case TK_STATICARRAY_TYPE: | |
1534 | if (!tinfo_types[tk]) | |
1535 | { | |
1536 | ident = Identifier::idPool ("TypeInfo_StaticArray"); | |
1537 | make_internal_typeinfo (tk, ident, ptr_type_node, size_type_node, | |
1538 | NULL); | |
1539 | } | |
1540 | t->vtinfo = TypeInfoStaticArrayDeclaration::create (t); | |
1541 | break; | |
1542 | ||
1543 | case TK_ASSOCIATIVEARRAY_TYPE: | |
1544 | if (!tinfo_types[tk]) | |
1545 | { | |
1546 | ident = Identifier::idPool ("TypeInfo_AssociativeArray"); | |
1547 | make_internal_typeinfo (tk, ident, ptr_type_node, ptr_type_node, | |
1548 | NULL); | |
1549 | } | |
1550 | t->vtinfo = TypeInfoAssociativeArrayDeclaration::create (t); | |
1551 | break; | |
1552 | ||
1553 | case TK_STRUCT_TYPE: | |
1554 | if (!tinfo_types[tk]) | |
1555 | { | |
1556 | /* Some ABIs add extra TypeInfo fields on the end. */ | |
1557 | tree argtype = global.params.is64bit ? ptr_type_node : NULL_TREE; | |
1558 | ||
1559 | ident = Identifier::idPool ("TypeInfo_Struct"); | |
1560 | make_internal_typeinfo (tk, ident, | |
1561 | array_type_node, array_type_node, | |
1562 | ptr_type_node, ptr_type_node, | |
1563 | ptr_type_node, ptr_type_node, | |
130cc10e IB |
1564 | d_uint_type, ptr_type_node, |
1565 | ptr_type_node, d_uint_type, | |
b4c522fa IB |
1566 | ptr_type_node, argtype, argtype, NULL); |
1567 | } | |
1568 | t->vtinfo = TypeInfoStructDeclaration::create (t); | |
1569 | break; | |
1570 | ||
1571 | case TK_ENUMERAL_TYPE: | |
1572 | if (!tinfo_types[tk]) | |
1573 | { | |
1574 | ident = Identifier::idPool ("TypeInfo_Enum"); | |
1575 | make_internal_typeinfo (tk, ident, | |
1576 | ptr_type_node, array_type_node, | |
1577 | array_type_node, NULL); | |
1578 | } | |
1579 | t->vtinfo = TypeInfoEnumDeclaration::create (t); | |
1580 | break; | |
1581 | ||
1582 | case TK_FUNCTION_TYPE: | |
1583 | case TK_DELEGATE_TYPE: | |
1584 | /* Functions and delegates share a common TypeInfo layout. */ | |
1585 | if (tk == TK_FUNCTION_TYPE) | |
1586 | { | |
1587 | t->vtinfo = TypeInfoFunctionDeclaration::create (t); | |
1588 | ident = Identifier::idPool ("TypeInfo_Function"); | |
1589 | } | |
1590 | else if (tk == TK_DELEGATE_TYPE) | |
1591 | { | |
1592 | t->vtinfo = TypeInfoDelegateDeclaration::create (t); | |
1593 | ident = Identifier::idPool ("TypeInfo_Delegate"); | |
1594 | } | |
1595 | else | |
1596 | gcc_unreachable (); | |
1597 | ||
1598 | if (!tinfo_types[tk]) | |
1599 | make_internal_typeinfo (tk, ident, ptr_type_node, | |
1600 | array_type_node, NULL); | |
1601 | break; | |
1602 | ||
1603 | case TK_TYPELIST_TYPE: | |
1604 | if (!tinfo_types[tk]) | |
1605 | { | |
1606 | ident = Identifier::idPool ("TypeInfo_Tuple"); | |
1607 | make_internal_typeinfo (tk, ident, array_type_node, NULL); | |
1608 | } | |
1609 | t->vtinfo = TypeInfoTupleDeclaration::create (t); | |
1610 | break; | |
1611 | ||
1612 | case TK_CLASSINFO_TYPE: | |
1613 | t->vtinfo = TypeInfoClassDeclaration::create (t); | |
1614 | break; | |
1615 | ||
1616 | default: | |
1617 | t->vtinfo = TypeInfoDeclaration::create (t); | |
1618 | } | |
1619 | gcc_assert (t->vtinfo); | |
1620 | ||
1621 | /* If this has a custom implementation in rt/typeinfo, then | |
1622 | do not generate a COMDAT for it. */ | |
1623 | if (!builtin_typeinfo_p (t)) | |
1624 | { | |
1625 | /* Find module that will go all the way to an object file. */ | |
1626 | if (mod) | |
1627 | mod->members->push (t->vtinfo); | |
1628 | else | |
1629 | build_decl_tree (t->vtinfo); | |
1630 | } | |
1631 | } | |
1632 | /* Types aren't merged, but we can share the vtinfo's. */ | |
1633 | if (!type->vtinfo) | |
1634 | type->vtinfo = t->vtinfo; | |
1635 | ||
1636 | gcc_assert (type->vtinfo != NULL); | |
1637 | } | |
1638 | ||
1639 | /* Implements a visitor interface to check whether a type is speculative. | |
1640 | TypeInfo_Struct would reference the members of the struct it is representing | |
1641 | (e.g: opEquals via xopEquals field), so if it's instantiated in speculative | |
1642 | context, TypeInfo creation should also be stopped to avoid possible | |
1643 | `unresolved symbol' linker errors. */ | |
1644 | ||
1645 | class SpeculativeTypeVisitor : public Visitor | |
1646 | { | |
1647 | using Visitor::visit; | |
1648 | ||
1649 | bool result_; | |
1650 | ||
1651 | public: | |
1652 | SpeculativeTypeVisitor (void) | |
1653 | { | |
1654 | this->result_ = false; | |
1655 | } | |
1656 | ||
1657 | bool result (void) | |
1658 | { | |
1659 | return this->result_; | |
1660 | } | |
1661 | ||
1662 | void visit (Type *t) | |
1663 | { | |
1664 | Type *tb = t->toBasetype (); | |
1665 | if (tb != t) | |
1666 | tb->accept (this); | |
1667 | } | |
1668 | ||
1669 | void visit (TypeNext *t) | |
1670 | { | |
1671 | if (t->next) | |
1672 | t->next->accept (this); | |
1673 | } | |
1674 | ||
1675 | void visit (TypeBasic *) | |
1676 | { | |
1677 | } | |
1678 | ||
1679 | void visit (TypeVector *t) | |
1680 | { | |
1681 | t->basetype->accept (this); | |
1682 | } | |
1683 | ||
1684 | void visit (TypeAArray *t) | |
1685 | { | |
1686 | t->index->accept (this); | |
1687 | visit ((TypeNext *)t); | |
1688 | } | |
1689 | ||
1690 | void visit (TypeFunction *t) | |
1691 | { | |
1692 | visit ((TypeNext *)t); | |
1693 | } | |
1694 | ||
1695 | void visit (TypeStruct *t) | |
1696 | { | |
1697 | StructDeclaration *sd = t->sym; | |
1698 | if (TemplateInstance *ti = sd->isInstantiated ()) | |
1699 | { | |
1700 | if (!ti->needsCodegen ()) | |
1701 | { | |
1702 | if (ti->minst || sd->requestTypeInfo) | |
1703 | return; | |
1704 | ||
1705 | this->result_ |= true; | |
1706 | } | |
1707 | } | |
1708 | } | |
1709 | ||
1710 | void visit (TypeClass *t) | |
1711 | { | |
1712 | ClassDeclaration *cd = t->sym; | |
1713 | if (TemplateInstance *ti = cd->isInstantiated ()) | |
1714 | { | |
1715 | if (!ti->needsCodegen () && !ti->minst) | |
1716 | { | |
1717 | this->result_ |= true; | |
1718 | } | |
1719 | } | |
1720 | } | |
1721 | ||
1722 | void visit (TypeTuple *t) | |
1723 | { | |
1724 | if (!t->arguments) | |
1725 | return; | |
1726 | ||
2cbc99d1 | 1727 | for (size_t i = 0; i < t->arguments->length; i++) |
b4c522fa IB |
1728 | { |
1729 | Type *tprm = (*t->arguments)[i]->type; | |
1730 | if (tprm) | |
1731 | tprm->accept (this); | |
1732 | if (this->result_) | |
1733 | return; | |
1734 | } | |
1735 | } | |
1736 | }; | |
1737 | ||
1738 | /* Return true if type was instantiated in a speculative context. */ | |
1739 | ||
1740 | bool | |
1741 | speculative_type_p (Type *t) | |
1742 | { | |
1743 | SpeculativeTypeVisitor v = SpeculativeTypeVisitor (); | |
1744 | t->accept (&v); | |
1745 | return v.result (); | |
1746 | } | |
1747 | ||
1748 | #include "gt-d-typeinfo.h" |