]>
Commit | Line | Data |
---|---|---|
b4c522fa | 1 | /* modules.cc -- D module initialization and termination. |
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/declaration.h" | |
23 | #include "dmd/identifier.h" | |
24 | #include "dmd/module.h" | |
25 | ||
26 | #include "tree.h" | |
7cc9cfd2 | 27 | #include "diagnostic.h" |
b4c522fa IB |
28 | #include "fold-const.h" |
29 | #include "tm.h" | |
30 | #include "function.h" | |
31 | #include "cgraph.h" | |
32 | #include "stor-layout.h" | |
33 | #include "toplev.h" | |
34 | #include "target.h" | |
35 | #include "common/common-target.h" | |
36 | #include "stringpool.h" | |
37 | ||
38 | #include "d-tree.h" | |
39 | ||
40 | ||
41 | /* D generates module information to inform the runtime library which modules | |
42 | need some kind of special handling. All `static this()', `static ~this()', | |
43 | and `unittest' functions for a given module are aggregated into a single | |
44 | function - one for each kind - and a pointer to that function is inserted | |
45 | into the ModuleInfo instance for that module. | |
46 | ||
47 | Module information for a particular module is indicated with an ABI defined | |
48 | structure derived from ModuleInfo. ModuleInfo is a variably sized struct | |
49 | with two fixed base fields. The first field `flags' determines what | |
50 | information is packed immediately after the record type. | |
51 | ||
52 | Like TypeInfo, the runtime library provides the definitions of the ModuleInfo | |
53 | structure, as well as accessors for the variadic fields. So we only define | |
54 | layout compatible POD_structs for ModuleInfo. */ | |
55 | ||
56 | /* The internally represented ModuleInfo and CompilerDSO types. */ | |
57 | static tree moduleinfo_type; | |
58 | static tree compiler_dso_type; | |
59 | static tree dso_registry_fn; | |
60 | ||
61 | /* The DSO slot for use by the druntime implementation. */ | |
62 | static tree dso_slot_node; | |
63 | ||
64 | /* For registering and deregistering DSOs with druntime, we have one global | |
65 | constructor and destructor per object that calls _d_dso_registry with the | |
66 | respective DSO record. To ensure that this is only done once, a | |
67 | `dso_initialized' variable is introduced to guard repeated calls. */ | |
68 | static tree dso_initialized_node; | |
69 | ||
70 | /* The beginning and end of the `minfo' section. */ | |
71 | static tree start_minfo_node; | |
72 | static tree stop_minfo_node; | |
73 | ||
74 | /* Record information about module initialization, termination, | |
75 | unit testing, and thread local storage in the compilation. */ | |
76 | ||
77 | struct GTY(()) module_info | |
78 | { | |
79 | vec<tree, va_gc> *ctors; | |
80 | vec<tree, va_gc> *dtors; | |
81 | vec<tree, va_gc> *ctorgates; | |
82 | ||
83 | vec<tree, va_gc> *sharedctors; | |
84 | vec<tree, va_gc> *shareddtors; | |
85 | vec<tree, va_gc> *sharedctorgates; | |
86 | ||
87 | vec<tree, va_gc> *unitTests; | |
88 | }; | |
89 | ||
90 | /* These must match the values in libdruntime/object_.d. */ | |
91 | ||
92 | enum module_info_flags | |
93 | { | |
94 | MIctorstart = 0x1, | |
95 | MIctordone = 0x2, | |
96 | MIstandalone = 0x4, | |
97 | MItlsctor = 0x8, | |
98 | MItlsdtor = 0x10, | |
99 | MIctor = 0x20, | |
100 | MIdtor = 0x40, | |
101 | MIxgetMembers = 0x80, | |
102 | MIictor = 0x100, | |
103 | MIunitTest = 0x200, | |
104 | MIimportedModules = 0x400, | |
105 | MIlocalClasses = 0x800, | |
106 | MIname = 0x1000 | |
107 | }; | |
108 | ||
109 | /* The ModuleInfo information structure for the module currently being compiled. | |
110 | Assuming that only ever process one at a time. */ | |
111 | ||
112 | static module_info *current_moduleinfo; | |
113 | ||
c50eadba IB |
114 | /* When compiling with -fbuilding-libphobos-tests, this contains information |
115 | about the module that gets compiled in only when unittests are enabled. */ | |
116 | ||
117 | static module_info *current_testing_module; | |
118 | ||
b4c522fa IB |
119 | /* The declaration of the current module being compiled. */ |
120 | ||
121 | static Module *current_module_decl; | |
122 | ||
123 | /* Static constructors and destructors (not D `static this'). */ | |
124 | ||
125 | static GTY(()) vec<tree, va_gc> *static_ctor_list; | |
126 | static GTY(()) vec<tree, va_gc> *static_dtor_list; | |
127 | ||
128 | /* Returns an internal function identified by IDENT. This is used | |
129 | by both module initialization and dso handlers. */ | |
130 | ||
131 | static FuncDeclaration * | |
132 | get_internal_fn (tree ident) | |
133 | { | |
134 | Module *mod = current_module_decl; | |
135 | const char *name = IDENTIFIER_POINTER (ident); | |
136 | ||
137 | if (!mod) | |
138 | mod = Module::rootModule; | |
139 | ||
140 | if (name[0] == '*') | |
141 | { | |
142 | tree s = mangle_internal_decl (mod, name + 1, "FZv"); | |
143 | name = IDENTIFIER_POINTER (s); | |
144 | } | |
145 | ||
146 | FuncDeclaration *fd = FuncDeclaration::genCfunc (NULL, Type::tvoid, | |
147 | Identifier::idPool (name)); | |
148 | fd->loc = Loc (mod->srcfile->toChars (), 1, 0); | |
149 | fd->parent = mod; | |
0a2ee409 | 150 | fd->protection.kind = Prot::private_; |
b4c522fa IB |
151 | fd->semanticRun = PASSsemantic3done; |
152 | ||
153 | return fd; | |
154 | } | |
155 | ||
156 | /* Generate an internal function identified by IDENT. | |
157 | The function body to add is in EXPR. */ | |
158 | ||
159 | static tree | |
160 | build_internal_fn (tree ident, tree expr) | |
161 | { | |
162 | FuncDeclaration *fd = get_internal_fn (ident); | |
163 | tree decl = get_symbol_decl (fd); | |
164 | ||
165 | tree old_context = start_function (fd); | |
166 | rest_of_decl_compilation (decl, 1, 0); | |
167 | add_stmt (expr); | |
168 | finish_function (old_context); | |
169 | ||
170 | /* D static ctors, static dtors, unittests, and the ModuleInfo | |
171 | chain function are always private. */ | |
172 | TREE_PUBLIC (decl) = 0; | |
173 | TREE_USED (decl) = 1; | |
174 | DECL_ARTIFICIAL (decl) = 1; | |
175 | ||
176 | return decl; | |
177 | } | |
178 | ||
179 | /* Build and emit a function identified by IDENT that increments (in order) | |
180 | all variables in GATES, then calls the list of functions in FUNCTIONS. */ | |
181 | ||
182 | static tree | |
183 | build_funcs_gates_fn (tree ident, vec<tree, va_gc> *functions, | |
184 | vec<tree, va_gc> *gates) | |
185 | { | |
186 | tree expr_list = NULL_TREE; | |
187 | ||
188 | /* Increment gates first. */ | |
189 | for (size_t i = 0; i < vec_safe_length (gates); i++) | |
190 | { | |
191 | tree decl = (*gates)[i]; | |
192 | tree value = build2 (PLUS_EXPR, TREE_TYPE (decl), | |
193 | decl, integer_one_node); | |
194 | tree var_expr = modify_expr (decl, value); | |
195 | expr_list = compound_expr (expr_list, var_expr); | |
196 | } | |
197 | ||
198 | /* Call Functions. */ | |
199 | for (size_t i = 0; i < vec_safe_length (functions); i++) | |
200 | { | |
201 | tree decl = (*functions)[i]; | |
202 | tree call_expr = build_call_expr (decl, 0); | |
203 | expr_list = compound_expr (expr_list, call_expr); | |
204 | } | |
205 | ||
206 | if (expr_list) | |
207 | return build_internal_fn (ident, expr_list); | |
208 | ||
209 | return NULL_TREE; | |
210 | } | |
211 | ||
212 | /* Return the type for ModuleInfo, create it if it doesn't already exist. */ | |
213 | ||
214 | static tree | |
215 | get_moduleinfo_type (void) | |
216 | { | |
217 | if (moduleinfo_type) | |
218 | return moduleinfo_type; | |
219 | ||
220 | /* Layout of ModuleInfo is: | |
221 | uint flags; | |
222 | uint index; */ | |
223 | tree fields = create_field_decl (d_uint_type, NULL, 1, 1); | |
224 | DECL_CHAIN (fields) = create_field_decl (d_uint_type, NULL, 1, 1); | |
225 | ||
226 | moduleinfo_type = make_node (RECORD_TYPE); | |
227 | finish_builtin_struct (moduleinfo_type, "ModuleInfo", fields, NULL_TREE); | |
228 | ||
229 | return moduleinfo_type; | |
230 | } | |
231 | ||
232 | /* Get the VAR_DECL of the ModuleInfo for DECL. If this does not yet exist, | |
233 | create it. The ModuleInfo decl is used to keep track of constructors, | |
234 | destructors, unittests, members, classes, and imports for the given module. | |
235 | This is used by the D runtime for module initialization and termination. */ | |
236 | ||
237 | static tree | |
238 | get_moduleinfo_decl (Module *decl) | |
239 | { | |
240 | if (decl->csym) | |
241 | return decl->csym; | |
242 | ||
243 | tree ident = mangle_internal_decl (decl, "__ModuleInfo", "Z"); | |
244 | tree type = get_moduleinfo_type (); | |
245 | ||
246 | decl->csym = declare_extern_var (ident, type); | |
247 | DECL_LANG_SPECIFIC (decl->csym) = build_lang_decl (NULL); | |
248 | ||
249 | DECL_CONTEXT (decl->csym) = build_import_decl (decl); | |
250 | /* Not readonly, moduleinit depends on this. */ | |
251 | TREE_READONLY (decl->csym) = 0; | |
252 | ||
253 | return decl->csym; | |
254 | } | |
255 | ||
256 | /* Return the type for CompilerDSOData, create it if it doesn't exist. */ | |
257 | ||
258 | static tree | |
259 | get_compiler_dso_type (void) | |
260 | { | |
261 | if (compiler_dso_type) | |
262 | return compiler_dso_type; | |
263 | ||
264 | /* Layout of CompilerDSOData is: | |
265 | size_t version; | |
266 | void** slot; | |
267 | ModuleInfo** _minfo_beg; | |
268 | ModuleInfo** _minfo_end; | |
269 | FuncTable* _deh_beg; | |
270 | FuncTable* _deh_end; | |
271 | ||
272 | Note, finish_builtin_struct() expects these fields in reverse order. */ | |
273 | tree fields = create_field_decl (ptr_type_node, NULL, 1, 1); | |
274 | tree field = create_field_decl (ptr_type_node, NULL, 1, 1); | |
275 | DECL_CHAIN (field) = fields; | |
276 | fields = field; | |
277 | ||
278 | field = create_field_decl (build_pointer_type (get_moduleinfo_type ()), | |
279 | NULL, 1, 1); | |
280 | DECL_CHAIN (field) = fields; | |
281 | fields = field; | |
282 | field = create_field_decl (build_pointer_type (get_moduleinfo_type ()), | |
283 | NULL, 1, 1); | |
284 | DECL_CHAIN (field) = fields; | |
285 | fields = field; | |
286 | ||
287 | field = create_field_decl (build_pointer_type (ptr_type_node), NULL, 1, 1); | |
288 | DECL_CHAIN (field) = fields; | |
289 | fields = field; | |
290 | ||
291 | field = create_field_decl (size_type_node, NULL, 1, 1); | |
292 | DECL_CHAIN (field) = fields; | |
293 | fields = field; | |
294 | ||
295 | compiler_dso_type = make_node (RECORD_TYPE); | |
296 | finish_builtin_struct (compiler_dso_type, "CompilerDSOData", | |
297 | fields, NULL_TREE); | |
298 | ||
299 | return compiler_dso_type; | |
300 | } | |
301 | ||
302 | /* Returns the _d_dso_registry FUNCTION_DECL. */ | |
303 | ||
304 | static tree | |
305 | get_dso_registry_fn (void) | |
306 | { | |
307 | if (dso_registry_fn) | |
308 | return dso_registry_fn; | |
309 | ||
310 | tree dso_type = get_compiler_dso_type (); | |
311 | tree fntype = build_function_type_list (void_type_node, | |
312 | build_pointer_type (dso_type), | |
313 | NULL_TREE); | |
314 | dso_registry_fn = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, | |
315 | get_identifier ("_d_dso_registry"), fntype); | |
316 | TREE_PUBLIC (dso_registry_fn) = 1; | |
317 | DECL_EXTERNAL (dso_registry_fn) = 1; | |
318 | ||
319 | return dso_registry_fn; | |
320 | } | |
321 | ||
322 | /* Depending on CTOR_P, builds and emits eiter a constructor or destructor | |
323 | calling _d_dso_registry if `dso_initialized' is `false' in a constructor | |
324 | or `true' in a destructor. */ | |
325 | ||
326 | static tree | |
327 | build_dso_cdtor_fn (bool ctor_p) | |
328 | { | |
329 | const char *name = ctor_p ? GDC_PREFIX ("dso_ctor") : GDC_PREFIX ("dso_dtor"); | |
330 | tree condition = ctor_p ? boolean_true_node : boolean_false_node; | |
331 | ||
332 | /* Declaration of dso_ctor/dso_dtor is: | |
333 | ||
334 | extern(C) void dso_{c,d}tor (void) | |
335 | { | |
336 | if (dso_initialized != condition) | |
337 | { | |
338 | dso_initialized = condition; | |
339 | CompilerDSOData dso = {1, &dsoSlot, &__start_minfo, &__stop_minfo}; | |
340 | _d_dso_registry (&dso); | |
341 | } | |
342 | } | |
343 | */ | |
344 | FuncDeclaration *fd = get_internal_fn (get_identifier (name)); | |
345 | tree decl = get_symbol_decl (fd); | |
346 | ||
347 | TREE_PUBLIC (decl) = 1; | |
348 | DECL_ARTIFICIAL (decl) = 1; | |
349 | DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; | |
350 | DECL_VISIBILITY_SPECIFIED (decl) = 1; | |
351 | ||
352 | d_comdat_linkage (decl); | |
353 | ||
354 | /* Start laying out the body. */ | |
355 | tree old_context = start_function (fd); | |
356 | rest_of_decl_compilation (decl, 1, 0); | |
357 | ||
358 | /* if (dso_initialized != condition). */ | |
359 | tree if_cond = build_boolop (NE_EXPR, dso_initialized_node, condition); | |
360 | ||
361 | /* dso_initialized = condition; */ | |
362 | tree expr_list = modify_expr (dso_initialized_node, condition); | |
363 | ||
364 | /* CompilerDSOData dso = {1, &dsoSlot, &__start_minfo, &__stop_minfo}; */ | |
365 | tree dso_type = get_compiler_dso_type (); | |
366 | tree dso = build_local_temp (dso_type); | |
367 | ||
368 | vec<constructor_elt, va_gc> *ve = NULL; | |
369 | CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_integer_cst (1, size_type_node)); | |
370 | CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (dso_slot_node)); | |
371 | CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (start_minfo_node)); | |
372 | CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (stop_minfo_node)); | |
373 | ||
374 | tree assign_expr = modify_expr (dso, build_struct_literal (dso_type, ve)); | |
375 | expr_list = compound_expr (expr_list, assign_expr); | |
376 | ||
377 | /* _d_dso_registry (&dso); */ | |
378 | tree call_expr = build_call_expr (get_dso_registry_fn (), 1, | |
379 | build_address (dso)); | |
380 | expr_list = compound_expr (expr_list, call_expr); | |
381 | ||
382 | add_stmt (build_vcondition (if_cond, expr_list, void_node)); | |
383 | finish_function (old_context); | |
384 | ||
385 | return decl; | |
386 | } | |
387 | ||
388 | /* Build a variable used in the dso_registry code identified by NAME, | |
389 | and data type TYPE. The variable always has VISIBILITY_HIDDEN and | |
390 | TREE_PUBLIC flags set. */ | |
391 | ||
392 | static tree | |
393 | build_dso_registry_var (const char * name, tree type) | |
394 | { | |
395 | tree var = declare_extern_var (get_identifier (name), type); | |
396 | DECL_VISIBILITY (var) = VISIBILITY_HIDDEN; | |
397 | DECL_VISIBILITY_SPECIFIED (var) = 1; | |
398 | return var; | |
399 | } | |
400 | ||
401 | /* Place a reference to the ModuleInfo symbol MINFO for DECL into the | |
402 | `minfo' section. Then create the global ctors/dtors to call the | |
403 | _d_dso_registry function if necessary. */ | |
404 | ||
405 | static void | |
406 | register_moduleinfo (Module *decl, tree minfo) | |
407 | { | |
7cc9cfd2 IB |
408 | if (!targetm_common.have_named_sections) |
409 | sorry ("%<-fmoduleinfo%> is not supported on this target"); | |
b4c522fa IB |
410 | |
411 | /* Build the ModuleInfo reference, this is done once for every Module. */ | |
412 | tree ident = mangle_internal_decl (decl, "__moduleRef", "Z"); | |
413 | tree mref = declare_extern_var (ident, ptr_type_node); | |
414 | ||
415 | /* Build the initializer and emit. Do not start section with a `.' character | |
416 | so that the linker will provide a __start_ and __stop_ symbol to indicate | |
417 | the start and end address of the section respectively. | |
418 | https://sourceware.org/binutils/docs-2.26/ld/Orphan-Sections.html. */ | |
419 | DECL_INITIAL (mref) = build_address (minfo); | |
420 | DECL_EXTERNAL (mref) = 0; | |
421 | DECL_PRESERVE_P (mref) = 1; | |
422 | ||
423 | set_decl_section_name (mref, "minfo"); | |
424 | d_pushdecl (mref); | |
425 | rest_of_decl_compilation (mref, 1, 0); | |
426 | ||
427 | /* Only for the first D module being emitted do we need to generate a static | |
428 | constructor and destructor for. These are only required once per shared | |
429 | library, so it's safe to emit them only once per object file. */ | |
430 | static bool first_module = true; | |
431 | if (!first_module) | |
432 | return; | |
433 | ||
434 | start_minfo_node = build_dso_registry_var ("__start_minfo", ptr_type_node); | |
435 | rest_of_decl_compilation (start_minfo_node, 1, 0); | |
436 | ||
437 | stop_minfo_node = build_dso_registry_var ("__stop_minfo", ptr_type_node); | |
438 | rest_of_decl_compilation (stop_minfo_node, 1, 0); | |
439 | ||
440 | /* Declare dso_slot and dso_initialized. */ | |
441 | dso_slot_node = build_dso_registry_var (GDC_PREFIX ("dso_slot"), | |
442 | ptr_type_node); | |
443 | DECL_EXTERNAL (dso_slot_node) = 0; | |
444 | d_comdat_linkage (dso_slot_node); | |
445 | rest_of_decl_compilation (dso_slot_node, 1, 0); | |
446 | ||
447 | dso_initialized_node = build_dso_registry_var (GDC_PREFIX ("dso_initialized"), | |
448 | boolean_type_node); | |
449 | DECL_EXTERNAL (dso_initialized_node) = 0; | |
450 | d_comdat_linkage (dso_initialized_node); | |
451 | rest_of_decl_compilation (dso_initialized_node, 1, 0); | |
452 | ||
453 | /* Declare dso_ctor() and dso_dtor(). */ | |
454 | tree dso_ctor = build_dso_cdtor_fn (true); | |
455 | vec_safe_push (static_ctor_list, dso_ctor); | |
456 | ||
457 | tree dso_dtor = build_dso_cdtor_fn (false); | |
458 | vec_safe_push (static_dtor_list, dso_dtor); | |
459 | ||
460 | first_module = false; | |
461 | } | |
462 | ||
463 | /* Convenience function for layout_moduleinfo_fields. Adds a field of TYPE to | |
464 | the moduleinfo record at OFFSET, incrementing the offset to the next field | |
465 | position. No alignment is taken into account, all fields are packed. */ | |
466 | ||
467 | static void | |
468 | layout_moduleinfo_field (tree type, tree rec_type, HOST_WIDE_INT& offset) | |
469 | { | |
470 | tree field = create_field_decl (type, NULL, 1, 1); | |
471 | insert_aggregate_field (rec_type, field, offset); | |
472 | offset += int_size_in_bytes (type); | |
473 | } | |
474 | ||
475 | /* Layout fields that immediately come after the moduleinfo TYPE for DECL. | |
476 | Data relating to the module is packed into the type on an as-needed | |
477 | basis, this is done to keep its size to a minimum. */ | |
478 | ||
479 | static tree | |
480 | layout_moduleinfo_fields (Module *decl, tree type) | |
481 | { | |
482 | HOST_WIDE_INT offset = int_size_in_bytes (type); | |
483 | type = copy_aggregate_type (type); | |
484 | ||
485 | /* First fields added are all the function pointers. */ | |
486 | if (decl->sctor) | |
487 | layout_moduleinfo_field (ptr_type_node, type, offset); | |
488 | ||
489 | if (decl->sdtor) | |
490 | layout_moduleinfo_field (ptr_type_node, type, offset); | |
491 | ||
492 | if (decl->ssharedctor) | |
493 | layout_moduleinfo_field (ptr_type_node, type, offset); | |
494 | ||
495 | if (decl->sshareddtor) | |
496 | layout_moduleinfo_field (ptr_type_node, type, offset); | |
497 | ||
498 | if (decl->findGetMembers ()) | |
499 | layout_moduleinfo_field (ptr_type_node, type, offset); | |
500 | ||
501 | if (decl->sictor) | |
502 | layout_moduleinfo_field (ptr_type_node, type, offset); | |
503 | ||
504 | if (decl->stest) | |
505 | layout_moduleinfo_field (ptr_type_node, type, offset); | |
506 | ||
507 | /* Array of module imports is laid out as a length field, followed by | |
508 | a static array of ModuleInfo pointers. */ | |
2cbc99d1 IB |
509 | size_t aimports_dim = decl->aimports.length; |
510 | for (size_t i = 0; i < decl->aimports.length; i++) | |
b4c522fa IB |
511 | { |
512 | Module *mi = decl->aimports[i]; | |
513 | if (!mi->needmoduleinfo) | |
514 | aimports_dim--; | |
515 | } | |
516 | ||
517 | if (aimports_dim) | |
518 | { | |
519 | layout_moduleinfo_field (size_type_node, type, offset); | |
520 | layout_moduleinfo_field (make_array_type (Type::tvoidptr, aimports_dim), | |
521 | type, offset); | |
522 | } | |
523 | ||
524 | /* Array of local ClassInfo decls are laid out in the same way. */ | |
525 | ClassDeclarations aclasses; | |
2cbc99d1 | 526 | for (size_t i = 0; i < decl->members->length; i++) |
b4c522fa IB |
527 | { |
528 | Dsymbol *member = (*decl->members)[i]; | |
529 | member->addLocalClass (&aclasses); | |
530 | } | |
531 | ||
2cbc99d1 | 532 | if (aclasses.length) |
b4c522fa IB |
533 | { |
534 | layout_moduleinfo_field (size_type_node, type, offset); | |
2cbc99d1 IB |
535 | layout_moduleinfo_field (make_array_type (Type::tvoidptr, |
536 | aclasses.length), | |
b4c522fa IB |
537 | type, offset); |
538 | } | |
539 | ||
540 | /* Lastly, the name of the module is a static char array. */ | |
541 | size_t namelen = strlen (decl->toPrettyChars ()) + 1; | |
542 | layout_moduleinfo_field (make_array_type (Type::tchar, namelen), | |
543 | type, offset); | |
544 | ||
1605fb3e IB |
545 | size_t alignsize = MAX (TYPE_ALIGN_UNIT (type), |
546 | TYPE_ALIGN_UNIT (ptr_type_node)); | |
013fca64 | 547 | finish_aggregate_type (offset, alignsize, type); |
b4c522fa IB |
548 | |
549 | return type; | |
550 | } | |
551 | ||
552 | /* Output the ModuleInfo for module DECL and register it with druntime. */ | |
553 | ||
554 | static void | |
555 | layout_moduleinfo (Module *decl) | |
556 | { | |
557 | ClassDeclarations aclasses; | |
558 | FuncDeclaration *sgetmembers; | |
559 | ||
2cbc99d1 | 560 | for (size_t i = 0; i < decl->members->length; i++) |
b4c522fa IB |
561 | { |
562 | Dsymbol *member = (*decl->members)[i]; | |
563 | member->addLocalClass (&aclasses); | |
564 | } | |
565 | ||
2cbc99d1 IB |
566 | size_t aimports_dim = decl->aimports.length; |
567 | for (size_t i = 0; i < decl->aimports.length; i++) | |
b4c522fa IB |
568 | { |
569 | Module *mi = decl->aimports[i]; | |
570 | if (!mi->needmoduleinfo) | |
571 | aimports_dim--; | |
572 | } | |
573 | ||
574 | sgetmembers = decl->findGetMembers (); | |
575 | ||
576 | size_t flags = 0; | |
577 | if (decl->sctor) | |
578 | flags |= MItlsctor; | |
579 | if (decl->sdtor) | |
580 | flags |= MItlsdtor; | |
581 | if (decl->ssharedctor) | |
582 | flags |= MIctor; | |
583 | if (decl->sshareddtor) | |
584 | flags |= MIdtor; | |
585 | if (sgetmembers) | |
586 | flags |= MIxgetMembers; | |
587 | if (decl->sictor) | |
588 | flags |= MIictor; | |
589 | if (decl->stest) | |
590 | flags |= MIunitTest; | |
591 | if (aimports_dim) | |
592 | flags |= MIimportedModules; | |
2cbc99d1 | 593 | if (aclasses.length) |
b4c522fa IB |
594 | flags |= MIlocalClasses; |
595 | if (!decl->needmoduleinfo) | |
596 | flags |= MIstandalone; | |
597 | ||
598 | flags |= MIname; | |
599 | ||
600 | tree minfo = get_moduleinfo_decl (decl); | |
601 | tree type = layout_moduleinfo_fields (decl, TREE_TYPE (minfo)); | |
602 | ||
603 | /* Put out the two named fields in a ModuleInfo decl: | |
604 | uint flags; | |
605 | uint index; */ | |
606 | vec<constructor_elt, va_gc> *minit = NULL; | |
607 | ||
608 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, | |
609 | build_integer_cst (flags, d_uint_type)); | |
610 | ||
611 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, | |
612 | build_integer_cst (0, d_uint_type)); | |
613 | ||
614 | /* Order of appearance, depending on flags: | |
615 | void function() tlsctor; | |
616 | void function() tlsdtor; | |
617 | void* function() xgetMembers; | |
618 | void function() ctor; | |
619 | void function() dtor; | |
620 | void function() ictor; | |
621 | void function() unitTest; | |
622 | ModuleInfo*[] importedModules; | |
623 | TypeInfo_Class[] localClasses; | |
624 | char[N] name; | |
625 | */ | |
626 | if (flags & MItlsctor) | |
627 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, build_address (decl->sctor)); | |
628 | ||
629 | if (flags & MItlsdtor) | |
630 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, build_address (decl->sdtor)); | |
631 | ||
632 | if (flags & MIctor) | |
633 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, | |
634 | build_address (decl->ssharedctor)); | |
635 | ||
636 | if (flags & MIdtor) | |
637 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, | |
638 | build_address (decl->sshareddtor)); | |
639 | ||
640 | if (flags & MIxgetMembers) | |
641 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, | |
642 | build_address (get_symbol_decl (sgetmembers))); | |
643 | ||
644 | if (flags & MIictor) | |
645 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, build_address (decl->sictor)); | |
646 | ||
647 | if (flags & MIunitTest) | |
648 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, build_address (decl->stest)); | |
649 | ||
650 | if (flags & MIimportedModules) | |
651 | { | |
652 | vec<constructor_elt, va_gc> *elms = NULL; | |
653 | tree satype = make_array_type (Type::tvoidptr, aimports_dim); | |
654 | size_t idx = 0; | |
655 | ||
2cbc99d1 | 656 | for (size_t i = 0; i < decl->aimports.length; i++) |
b4c522fa IB |
657 | { |
658 | Module *mi = decl->aimports[i]; | |
659 | if (mi->needmoduleinfo) | |
660 | { | |
661 | CONSTRUCTOR_APPEND_ELT (elms, size_int (idx), | |
662 | build_address (get_moduleinfo_decl (mi))); | |
663 | idx++; | |
664 | } | |
665 | } | |
666 | ||
667 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, size_int (aimports_dim)); | |
668 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, | |
669 | build_constructor (satype, elms)); | |
670 | } | |
671 | ||
672 | if (flags & MIlocalClasses) | |
673 | { | |
674 | vec<constructor_elt, va_gc> *elms = NULL; | |
2cbc99d1 | 675 | tree satype = make_array_type (Type::tvoidptr, aclasses.length); |
b4c522fa | 676 | |
2cbc99d1 | 677 | for (size_t i = 0; i < aclasses.length; i++) |
b4c522fa IB |
678 | { |
679 | ClassDeclaration *cd = aclasses[i]; | |
680 | CONSTRUCTOR_APPEND_ELT (elms, size_int (i), | |
681 | build_address (get_classinfo_decl (cd))); | |
682 | } | |
683 | ||
2cbc99d1 | 684 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, size_int (aclasses.length)); |
b4c522fa IB |
685 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, |
686 | build_constructor (satype, elms)); | |
687 | } | |
688 | ||
689 | if (flags & MIname) | |
690 | { | |
691 | /* Put out module name as a 0-terminated C-string, to save bytes. */ | |
692 | const char *name = decl->toPrettyChars (); | |
693 | size_t namelen = strlen (name) + 1; | |
694 | tree strtree = build_string (namelen, name); | |
695 | TREE_TYPE (strtree) = make_array_type (Type::tchar, namelen); | |
696 | CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, strtree); | |
697 | } | |
698 | ||
699 | TREE_TYPE (minfo) = type; | |
700 | DECL_INITIAL (minfo) = build_struct_literal (type, minit); | |
701 | d_finish_decl (minfo); | |
702 | ||
703 | /* Register the module against druntime. */ | |
704 | register_moduleinfo (decl, minfo); | |
705 | } | |
706 | ||
707 | /* Send the Module AST class DECL to GCC back-end. */ | |
708 | ||
709 | void | |
710 | build_module_tree (Module *decl) | |
711 | { | |
712 | /* There may be more than one module per object file, but should only | |
713 | ever compile them one at a time. */ | |
714 | assert (!current_moduleinfo && !current_module_decl); | |
715 | ||
716 | module_info mi = module_info (); | |
c50eadba | 717 | module_info mitest = module_info (); |
b4c522fa IB |
718 | |
719 | current_moduleinfo = &mi; | |
c50eadba | 720 | current_testing_module = &mitest; |
b4c522fa IB |
721 | current_module_decl = decl; |
722 | ||
723 | /* Layout module members. */ | |
724 | if (decl->members) | |
725 | { | |
2cbc99d1 | 726 | for (size_t i = 0; i < decl->members->length; i++) |
b4c522fa IB |
727 | { |
728 | Dsymbol *s = (*decl->members)[i]; | |
729 | build_decl_tree (s); | |
730 | } | |
731 | } | |
732 | ||
c50eadba IB |
733 | /* For libphobos-internal use only. Generate a separate module info symbol |
734 | that references all compiled in unittests, this allows compiling library | |
735 | modules and linking to libphobos without having run-time conflicts because | |
736 | of two ModuleInfo records with the same name being present in two DSOs. */ | |
737 | if (flag_building_libphobos_tests) | |
738 | { | |
739 | /* Associate the module info symbol with a mock module. */ | |
740 | const char *name = concat (GDC_PREFIX ("modtest__"), | |
741 | decl->ident->toChars (), NULL); | |
742 | Module *tm = Module::create (decl->arg, Identifier::idPool (name), 0, 0); | |
743 | Dsymbols members; | |
744 | ||
745 | /* Setting parent puts module in the same package as the current, to | |
746 | avoid any symbol conflicts. */ | |
747 | tm->parent = decl->parent; | |
748 | tm->needmoduleinfo = decl->needmoduleinfo; | |
749 | tm->members = &members; | |
750 | /* Register the current module as being imported by the mock module. | |
751 | This informs run-time that there is a dependency between the two. */ | |
752 | tm->aimports.push (decl); | |
753 | ||
754 | if (mitest.ctors || mitest.ctorgates) | |
755 | tm->sctor = build_funcs_gates_fn (get_identifier ("*__modtestctor"), | |
756 | mitest.ctors, mitest.ctorgates); | |
757 | ||
758 | if (mitest.dtors) | |
759 | tm->sdtor = build_funcs_gates_fn (get_identifier ("*__modtestdtor"), | |
760 | mitest.dtors, NULL); | |
761 | ||
762 | if (mitest.sharedctors || mitest.sharedctorgates) | |
763 | tm->ssharedctor | |
764 | = build_funcs_gates_fn (get_identifier ("*__modtestsharedctor"), | |
765 | mitest.sharedctors, mitest.sharedctorgates); | |
766 | ||
767 | if (mitest.shareddtors) | |
768 | tm->sshareddtor | |
769 | = build_funcs_gates_fn (get_identifier ("*__modtestshareddtor"), | |
770 | mitest.shareddtors, NULL); | |
771 | ||
772 | if (mi.unitTests) | |
773 | tm->stest = build_funcs_gates_fn (get_identifier ("*__modtest"), | |
774 | mi.unitTests, NULL); | |
775 | ||
776 | mi.unitTests = NULL; | |
777 | layout_moduleinfo (tm); | |
778 | } | |
779 | ||
b4c522fa IB |
780 | /* Default behavior is to always generate module info because of templates. |
781 | Can be switched off for not compiling against runtime library. */ | |
c0aebc60 IB |
782 | if (global.params.useModuleInfo |
783 | && Module::moduleinfo != NULL | |
b4c522fa IB |
784 | && decl->ident != Identifier::idPool ("__entrypoint")) |
785 | { | |
786 | if (mi.ctors || mi.ctorgates) | |
787 | decl->sctor = build_funcs_gates_fn (get_identifier ("*__modctor"), | |
788 | mi.ctors, mi.ctorgates); | |
789 | ||
790 | if (mi.dtors) | |
791 | decl->sdtor = build_funcs_gates_fn (get_identifier ("*__moddtor"), | |
792 | mi.dtors, NULL); | |
793 | ||
794 | if (mi.sharedctors || mi.sharedctorgates) | |
795 | decl->ssharedctor | |
796 | = build_funcs_gates_fn (get_identifier ("*__modsharedctor"), | |
797 | mi.sharedctors, mi.sharedctorgates); | |
798 | ||
799 | if (mi.shareddtors) | |
800 | decl->sshareddtor | |
801 | = build_funcs_gates_fn (get_identifier ("*__modshareddtor"), | |
802 | mi.shareddtors, NULL); | |
803 | ||
804 | if (mi.unitTests) | |
805 | decl->stest = build_funcs_gates_fn (get_identifier ("*__modtest"), | |
806 | mi.unitTests, NULL); | |
807 | ||
808 | layout_moduleinfo (decl); | |
809 | } | |
810 | ||
811 | current_moduleinfo = NULL; | |
c50eadba | 812 | current_testing_module = NULL; |
b4c522fa IB |
813 | current_module_decl = NULL; |
814 | } | |
815 | ||
816 | /* Returns the current function or module context for the purpose | |
817 | of imported_module_or_decl. */ | |
818 | ||
819 | tree | |
820 | d_module_context (void) | |
821 | { | |
822 | if (cfun != NULL) | |
823 | return current_function_decl; | |
824 | ||
825 | gcc_assert (current_module_decl != NULL); | |
826 | return build_import_decl (current_module_decl); | |
827 | } | |
828 | ||
829 | /* Maybe record declaration D against our module information structure. */ | |
830 | ||
831 | void | |
832 | register_module_decl (Declaration *d) | |
833 | { | |
834 | FuncDeclaration *fd = d->isFuncDeclaration (); | |
835 | if (fd != NULL) | |
836 | { | |
837 | tree decl = get_symbol_decl (fd); | |
838 | ||
c50eadba IB |
839 | /* Any module constructors or destructors that are only present when |
840 | compiling in unittests are kept track of separately so they are | |
841 | not omitted when compiling with -fbuilding-libphobos-tests. */ | |
842 | module_info *minfo; | |
f452f0d6 IB |
843 | if (flag_building_libphobos_tests && !fd->isUnitTestDeclaration () |
844 | && DECL_IN_UNITTEST_CONDITION_P (decl)) | |
c50eadba IB |
845 | minfo = current_testing_module; |
846 | else | |
847 | minfo = current_moduleinfo; | |
848 | ||
849 | gcc_assert (minfo != NULL); | |
850 | ||
b4c522fa IB |
851 | /* If a static constructor, push into the current ModuleInfo. |
852 | Checks for `shared' first because it derives from the non-shared | |
853 | constructor type in the front-end. */ | |
854 | if (fd->isSharedStaticCtorDeclaration ()) | |
c50eadba | 855 | vec_safe_push (minfo->sharedctors, decl); |
b4c522fa | 856 | else if (fd->isStaticCtorDeclaration ()) |
c50eadba | 857 | vec_safe_push (minfo->ctors, decl); |
b4c522fa IB |
858 | |
859 | /* If a static destructor, do same as with constructors, but also | |
860 | increment the destructor's vgate at construction time. */ | |
861 | if (fd->isSharedStaticDtorDeclaration ()) | |
862 | { | |
863 | VarDeclaration *vgate = ((SharedStaticDtorDeclaration *) fd)->vgate; | |
864 | if (vgate != NULL) | |
865 | { | |
866 | tree gate = get_symbol_decl (vgate); | |
c50eadba | 867 | vec_safe_push (minfo->sharedctorgates, gate); |
b4c522fa | 868 | } |
c50eadba | 869 | vec_safe_insert (minfo->shareddtors, 0, decl); |
b4c522fa IB |
870 | } |
871 | else if (fd->isStaticDtorDeclaration ()) | |
872 | { | |
873 | VarDeclaration *vgate = ((StaticDtorDeclaration *) fd)->vgate; | |
874 | if (vgate != NULL) | |
875 | { | |
876 | tree gate = get_symbol_decl (vgate); | |
c50eadba | 877 | vec_safe_push (minfo->ctorgates, gate); |
b4c522fa | 878 | } |
c50eadba | 879 | vec_safe_insert (minfo->dtors, 0, decl); |
b4c522fa IB |
880 | } |
881 | ||
882 | /* If a unittest function. */ | |
883 | if (fd->isUnitTestDeclaration ()) | |
c50eadba | 884 | vec_safe_push (minfo->unitTests, decl); |
b4c522fa IB |
885 | } |
886 | } | |
887 | ||
888 | /* Wrapup all global declarations and start the final compilation. */ | |
889 | ||
890 | void | |
891 | d_finish_compilation (tree *vec, int len) | |
892 | { | |
893 | /* Complete all generated thunks. */ | |
894 | symtab->process_same_body_aliases (); | |
895 | ||
896 | /* Process all file scopes in this compilation, and the external_scope, | |
897 | through wrapup_global_declarations. */ | |
898 | for (int i = 0; i < len; i++) | |
899 | { | |
900 | tree decl = vec[i]; | |
901 | wrapup_global_declarations (&decl, 1); | |
902 | } | |
903 | ||
904 | /* If the target does not directly support static constructors, | |
905 | static_ctor_list contains a list of all static constructors defined | |
906 | so far. This routine will create a function to call all of those | |
907 | and is picked up by collect2. */ | |
908 | if (static_ctor_list) | |
909 | { | |
910 | tree decl = build_funcs_gates_fn (get_file_function_name ("I"), | |
911 | static_ctor_list, NULL); | |
912 | DECL_STATIC_CONSTRUCTOR (decl) = 1; | |
913 | decl_init_priority_insert (decl, DEFAULT_INIT_PRIORITY); | |
914 | } | |
915 | ||
916 | if (static_dtor_list) | |
917 | { | |
918 | tree decl = build_funcs_gates_fn (get_file_function_name ("D"), | |
919 | static_dtor_list, NULL); | |
920 | DECL_STATIC_DESTRUCTOR (decl) = 1; | |
921 | decl_fini_priority_insert (decl, DEFAULT_INIT_PRIORITY); | |
922 | } | |
923 | } | |
924 | ||
925 | ||
926 | #include "gt-d-modules.h" |