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