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