/gcc/d/modules.cc
C++ | 854 lines | 529 code | 163 blank | 162 comment | 83 complexity | e1caa2b9ee9f5cd49ae8b3ed3974b374 MD5 | raw file
Possible License(s): AGPL-1.0
- /* modules.cc -- D module initialization and termination.
- Copyright (C) 2013-2018 Free Software Foundation, Inc.
- GCC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GCC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "dmd/declaration.h"
- #include "dmd/identifier.h"
- #include "dmd/module.h"
- #include "tree.h"
- #include "fold-const.h"
- #include "tm.h"
- #include "function.h"
- #include "cgraph.h"
- #include "stor-layout.h"
- #include "toplev.h"
- #include "target.h"
- #include "common/common-target.h"
- #include "stringpool.h"
- #include "d-tree.h"
- /* D generates module information to inform the runtime library which modules
- need some kind of special handling. All `static this()', `static ~this()',
- and `unittest' functions for a given module are aggregated into a single
- function - one for each kind - and a pointer to that function is inserted
- into the ModuleInfo instance for that module.
- Module information for a particular module is indicated with an ABI defined
- structure derived from ModuleInfo. ModuleInfo is a variably sized struct
- with two fixed base fields. The first field `flags' determines what
- information is packed immediately after the record type.
- Like TypeInfo, the runtime library provides the definitions of the ModuleInfo
- structure, as well as accessors for the variadic fields. So we only define
- layout compatible POD_structs for ModuleInfo. */
- /* The internally represented ModuleInfo and CompilerDSO types. */
- static tree moduleinfo_type;
- static tree compiler_dso_type;
- static tree dso_registry_fn;
- /* The DSO slot for use by the druntime implementation. */
- static tree dso_slot_node;
- /* For registering and deregistering DSOs with druntime, we have one global
- constructor and destructor per object that calls _d_dso_registry with the
- respective DSO record. To ensure that this is only done once, a
- `dso_initialized' variable is introduced to guard repeated calls. */
- static tree dso_initialized_node;
- /* The beginning and end of the `minfo' section. */
- static tree start_minfo_node;
- static tree stop_minfo_node;
- /* Record information about module initialization, termination,
- unit testing, and thread local storage in the compilation. */
- struct GTY(()) module_info
- {
- vec<tree, va_gc> *ctors;
- vec<tree, va_gc> *dtors;
- vec<tree, va_gc> *ctorgates;
- vec<tree, va_gc> *sharedctors;
- vec<tree, va_gc> *shareddtors;
- vec<tree, va_gc> *sharedctorgates;
- vec<tree, va_gc> *unitTests;
- };
- /* These must match the values in libdruntime/object_.d. */
- enum module_info_flags
- {
- MIctorstart = 0x1,
- MIctordone = 0x2,
- MIstandalone = 0x4,
- MItlsctor = 0x8,
- MItlsdtor = 0x10,
- MIctor = 0x20,
- MIdtor = 0x40,
- MIxgetMembers = 0x80,
- MIictor = 0x100,
- MIunitTest = 0x200,
- MIimportedModules = 0x400,
- MIlocalClasses = 0x800,
- MIname = 0x1000
- };
- /* The ModuleInfo information structure for the module currently being compiled.
- Assuming that only ever process one at a time. */
- static module_info *current_moduleinfo;
- /* The declaration of the current module being compiled. */
- static Module *current_module_decl;
- /* Static constructors and destructors (not D `static this'). */
- static GTY(()) vec<tree, va_gc> *static_ctor_list;
- static GTY(()) vec<tree, va_gc> *static_dtor_list;
- /* Returns an internal function identified by IDENT. This is used
- by both module initialization and dso handlers. */
- static FuncDeclaration *
- get_internal_fn (tree ident)
- {
- Module *mod = current_module_decl;
- const char *name = IDENTIFIER_POINTER (ident);
- if (!mod)
- mod = Module::rootModule;
- if (name[0] == '*')
- {
- tree s = mangle_internal_decl (mod, name + 1, "FZv");
- name = IDENTIFIER_POINTER (s);
- }
- FuncDeclaration *fd = FuncDeclaration::genCfunc (NULL, Type::tvoid,
- Identifier::idPool (name));
- fd->loc = Loc (mod->srcfile->toChars (), 1, 0);
- fd->parent = mod;
- fd->protection.kind = Prot::private_;
- fd->semanticRun = PASSsemantic3done;
- return fd;
- }
- /* Generate an internal function identified by IDENT.
- The function body to add is in EXPR. */
- static tree
- build_internal_fn (tree ident, tree expr)
- {
- FuncDeclaration *fd = get_internal_fn (ident);
- tree decl = get_symbol_decl (fd);
- tree old_context = start_function (fd);
- rest_of_decl_compilation (decl, 1, 0);
- add_stmt (expr);
- finish_function (old_context);
- /* D static ctors, static dtors, unittests, and the ModuleInfo
- chain function are always private. */
- TREE_PUBLIC (decl) = 0;
- TREE_USED (decl) = 1;
- DECL_ARTIFICIAL (decl) = 1;
- return decl;
- }
- /* Build and emit a function identified by IDENT that increments (in order)
- all variables in GATES, then calls the list of functions in FUNCTIONS. */
- static tree
- build_funcs_gates_fn (tree ident, vec<tree, va_gc> *functions,
- vec<tree, va_gc> *gates)
- {
- tree expr_list = NULL_TREE;
- /* Increment gates first. */
- for (size_t i = 0; i < vec_safe_length (gates); i++)
- {
- tree decl = (*gates)[i];
- tree value = build2 (PLUS_EXPR, TREE_TYPE (decl),
- decl, integer_one_node);
- tree var_expr = modify_expr (decl, value);
- expr_list = compound_expr (expr_list, var_expr);
- }
- /* Call Functions. */
- for (size_t i = 0; i < vec_safe_length (functions); i++)
- {
- tree decl = (*functions)[i];
- tree call_expr = build_call_expr (decl, 0);
- expr_list = compound_expr (expr_list, call_expr);
- }
- if (expr_list)
- return build_internal_fn (ident, expr_list);
- return NULL_TREE;
- }
- /* Return the type for ModuleInfo, create it if it doesn't already exist. */
- static tree
- get_moduleinfo_type (void)
- {
- if (moduleinfo_type)
- return moduleinfo_type;
- /* Layout of ModuleInfo is:
- uint flags;
- uint index; */
- tree fields = create_field_decl (d_uint_type, NULL, 1, 1);
- DECL_CHAIN (fields) = create_field_decl (d_uint_type, NULL, 1, 1);
- moduleinfo_type = make_node (RECORD_TYPE);
- finish_builtin_struct (moduleinfo_type, "ModuleInfo", fields, NULL_TREE);
- return moduleinfo_type;
- }
- /* Get the VAR_DECL of the ModuleInfo for DECL. If this does not yet exist,
- create it. The ModuleInfo decl is used to keep track of constructors,
- destructors, unittests, members, classes, and imports for the given module.
- This is used by the D runtime for module initialization and termination. */
- static tree
- get_moduleinfo_decl (Module *decl)
- {
- if (decl->csym)
- return decl->csym;
- tree ident = mangle_internal_decl (decl, "__ModuleInfo", "Z");
- tree type = get_moduleinfo_type ();
- decl->csym = declare_extern_var (ident, type);
- DECL_LANG_SPECIFIC (decl->csym) = build_lang_decl (NULL);
- DECL_CONTEXT (decl->csym) = build_import_decl (decl);
- /* Not readonly, moduleinit depends on this. */
- TREE_READONLY (decl->csym) = 0;
- return decl->csym;
- }
- /* Return the type for CompilerDSOData, create it if it doesn't exist. */
- static tree
- get_compiler_dso_type (void)
- {
- if (compiler_dso_type)
- return compiler_dso_type;
- /* Layout of CompilerDSOData is:
- size_t version;
- void** slot;
- ModuleInfo** _minfo_beg;
- ModuleInfo** _minfo_end;
- FuncTable* _deh_beg;
- FuncTable* _deh_end;
- Note, finish_builtin_struct() expects these fields in reverse order. */
- tree fields = create_field_decl (ptr_type_node, NULL, 1, 1);
- tree field = create_field_decl (ptr_type_node, NULL, 1, 1);
- DECL_CHAIN (field) = fields;
- fields = field;
- field = create_field_decl (build_pointer_type (get_moduleinfo_type ()),
- NULL, 1, 1);
- DECL_CHAIN (field) = fields;
- fields = field;
- field = create_field_decl (build_pointer_type (get_moduleinfo_type ()),
- NULL, 1, 1);
- DECL_CHAIN (field) = fields;
- fields = field;
- field = create_field_decl (build_pointer_type (ptr_type_node), NULL, 1, 1);
- DECL_CHAIN (field) = fields;
- fields = field;
- field = create_field_decl (size_type_node, NULL, 1, 1);
- DECL_CHAIN (field) = fields;
- fields = field;
- compiler_dso_type = make_node (RECORD_TYPE);
- finish_builtin_struct (compiler_dso_type, "CompilerDSOData",
- fields, NULL_TREE);
- return compiler_dso_type;
- }
- /* Returns the _d_dso_registry FUNCTION_DECL. */
- static tree
- get_dso_registry_fn (void)
- {
- if (dso_registry_fn)
- return dso_registry_fn;
- tree dso_type = get_compiler_dso_type ();
- tree fntype = build_function_type_list (void_type_node,
- build_pointer_type (dso_type),
- NULL_TREE);
- dso_registry_fn = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
- get_identifier ("_d_dso_registry"), fntype);
- TREE_PUBLIC (dso_registry_fn) = 1;
- DECL_EXTERNAL (dso_registry_fn) = 1;
- return dso_registry_fn;
- }
- /* Depending on CTOR_P, builds and emits eiter a constructor or destructor
- calling _d_dso_registry if `dso_initialized' is `false' in a constructor
- or `true' in a destructor. */
- static tree
- build_dso_cdtor_fn (bool ctor_p)
- {
- const char *name = ctor_p ? GDC_PREFIX ("dso_ctor") : GDC_PREFIX ("dso_dtor");
- tree condition = ctor_p ? boolean_true_node : boolean_false_node;
- /* Declaration of dso_ctor/dso_dtor is:
- extern(C) void dso_{c,d}tor (void)
- {
- if (dso_initialized != condition)
- {
- dso_initialized = condition;
- CompilerDSOData dso = {1, &dsoSlot, &__start_minfo, &__stop_minfo};
- _d_dso_registry (&dso);
- }
- }
- */
- FuncDeclaration *fd = get_internal_fn (get_identifier (name));
- tree decl = get_symbol_decl (fd);
- TREE_PUBLIC (decl) = 1;
- DECL_ARTIFICIAL (decl) = 1;
- DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
- DECL_VISIBILITY_SPECIFIED (decl) = 1;
- d_comdat_linkage (decl);
- /* Start laying out the body. */
- tree old_context = start_function (fd);
- rest_of_decl_compilation (decl, 1, 0);
- /* if (dso_initialized != condition). */
- tree if_cond = build_boolop (NE_EXPR, dso_initialized_node, condition);
- /* dso_initialized = condition; */
- tree expr_list = modify_expr (dso_initialized_node, condition);
- /* CompilerDSOData dso = {1, &dsoSlot, &__start_minfo, &__stop_minfo}; */
- tree dso_type = get_compiler_dso_type ();
- tree dso = build_local_temp (dso_type);
- vec<constructor_elt, va_gc> *ve = NULL;
- CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_integer_cst (1, size_type_node));
- CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (dso_slot_node));
- CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (start_minfo_node));
- CONSTRUCTOR_APPEND_ELT (ve, NULL_TREE, build_address (stop_minfo_node));
- tree assign_expr = modify_expr (dso, build_struct_literal (dso_type, ve));
- expr_list = compound_expr (expr_list, assign_expr);
- /* _d_dso_registry (&dso); */
- tree call_expr = build_call_expr (get_dso_registry_fn (), 1,
- build_address (dso));
- expr_list = compound_expr (expr_list, call_expr);
- add_stmt (build_vcondition (if_cond, expr_list, void_node));
- finish_function (old_context);
- return decl;
- }
- /* Build a variable used in the dso_registry code identified by NAME,
- and data type TYPE. The variable always has VISIBILITY_HIDDEN and
- TREE_PUBLIC flags set. */
- static tree
- build_dso_registry_var (const char * name, tree type)
- {
- tree var = declare_extern_var (get_identifier (name), type);
- DECL_VISIBILITY (var) = VISIBILITY_HIDDEN;
- DECL_VISIBILITY_SPECIFIED (var) = 1;
- return var;
- }
- /* Place a reference to the ModuleInfo symbol MINFO for DECL into the
- `minfo' section. Then create the global ctors/dtors to call the
- _d_dso_registry function if necessary. */
- static void
- register_moduleinfo (Module *decl, tree minfo)
- {
- gcc_assert (targetm_common.have_named_sections);
- /* Build the ModuleInfo reference, this is done once for every Module. */
- tree ident = mangle_internal_decl (decl, "__moduleRef", "Z");
- tree mref = declare_extern_var (ident, ptr_type_node);
- /* Build the initializer and emit. Do not start section with a `.' character
- so that the linker will provide a __start_ and __stop_ symbol to indicate
- the start and end address of the section respectively.
- https://sourceware.org/binutils/docs-2.26/ld/Orphan-Sections.html. */
- DECL_INITIAL (mref) = build_address (minfo);
- DECL_EXTERNAL (mref) = 0;
- DECL_PRESERVE_P (mref) = 1;
- set_decl_section_name (mref, "minfo");
- d_pushdecl (mref);
- rest_of_decl_compilation (mref, 1, 0);
- /* Only for the first D module being emitted do we need to generate a static
- constructor and destructor for. These are only required once per shared
- library, so it's safe to emit them only once per object file. */
- static bool first_module = true;
- if (!first_module)
- return;
- start_minfo_node = build_dso_registry_var ("__start_minfo", ptr_type_node);
- rest_of_decl_compilation (start_minfo_node, 1, 0);
- stop_minfo_node = build_dso_registry_var ("__stop_minfo", ptr_type_node);
- rest_of_decl_compilation (stop_minfo_node, 1, 0);
- /* Declare dso_slot and dso_initialized. */
- dso_slot_node = build_dso_registry_var (GDC_PREFIX ("dso_slot"),
- ptr_type_node);
- DECL_EXTERNAL (dso_slot_node) = 0;
- d_comdat_linkage (dso_slot_node);
- rest_of_decl_compilation (dso_slot_node, 1, 0);
- dso_initialized_node = build_dso_registry_var (GDC_PREFIX ("dso_initialized"),
- boolean_type_node);
- DECL_EXTERNAL (dso_initialized_node) = 0;
- d_comdat_linkage (dso_initialized_node);
- rest_of_decl_compilation (dso_initialized_node, 1, 0);
- /* Declare dso_ctor() and dso_dtor(). */
- tree dso_ctor = build_dso_cdtor_fn (true);
- vec_safe_push (static_ctor_list, dso_ctor);
- tree dso_dtor = build_dso_cdtor_fn (false);
- vec_safe_push (static_dtor_list, dso_dtor);
- first_module = false;
- }
- /* Convenience function for layout_moduleinfo_fields. Adds a field of TYPE to
- the moduleinfo record at OFFSET, incrementing the offset to the next field
- position. No alignment is taken into account, all fields are packed. */
- static void
- layout_moduleinfo_field (tree type, tree rec_type, HOST_WIDE_INT& offset)
- {
- tree field = create_field_decl (type, NULL, 1, 1);
- insert_aggregate_field (rec_type, field, offset);
- offset += int_size_in_bytes (type);
- }
- /* Layout fields that immediately come after the moduleinfo TYPE for DECL.
- Data relating to the module is packed into the type on an as-needed
- basis, this is done to keep its size to a minimum. */
- static tree
- layout_moduleinfo_fields (Module *decl, tree type)
- {
- HOST_WIDE_INT offset = int_size_in_bytes (type);
- type = copy_aggregate_type (type);
- /* First fields added are all the function pointers. */
- if (decl->sctor)
- layout_moduleinfo_field (ptr_type_node, type, offset);
- if (decl->sdtor)
- layout_moduleinfo_field (ptr_type_node, type, offset);
- if (decl->ssharedctor)
- layout_moduleinfo_field (ptr_type_node, type, offset);
- if (decl->sshareddtor)
- layout_moduleinfo_field (ptr_type_node, type, offset);
- if (decl->findGetMembers ())
- layout_moduleinfo_field (ptr_type_node, type, offset);
- if (decl->sictor)
- layout_moduleinfo_field (ptr_type_node, type, offset);
- if (decl->stest)
- layout_moduleinfo_field (ptr_type_node, type, offset);
- /* Array of module imports is laid out as a length field, followed by
- a static array of ModuleInfo pointers. */
- size_t aimports_dim = decl->aimports.dim;
- for (size_t i = 0; i < decl->aimports.dim; i++)
- {
- Module *mi = decl->aimports[i];
- if (!mi->needmoduleinfo)
- aimports_dim--;
- }
- if (aimports_dim)
- {
- layout_moduleinfo_field (size_type_node, type, offset);
- layout_moduleinfo_field (make_array_type (Type::tvoidptr, aimports_dim),
- type, offset);
- }
- /* Array of local ClassInfo decls are laid out in the same way. */
- ClassDeclarations aclasses;
- for (size_t i = 0; i < decl->members->dim; i++)
- {
- Dsymbol *member = (*decl->members)[i];
- member->addLocalClass (&aclasses);
- }
- if (aclasses.dim)
- {
- layout_moduleinfo_field (size_type_node, type, offset);
- layout_moduleinfo_field (make_array_type (Type::tvoidptr, aclasses.dim),
- type, offset);
- }
- /* Lastly, the name of the module is a static char array. */
- size_t namelen = strlen (decl->toPrettyChars ()) + 1;
- layout_moduleinfo_field (make_array_type (Type::tchar, namelen),
- type, offset);
- finish_aggregate_type (offset, 1, type, NULL);
- return type;
- }
- /* Output the ModuleInfo for module DECL and register it with druntime. */
- static void
- layout_moduleinfo (Module *decl)
- {
- ClassDeclarations aclasses;
- FuncDeclaration *sgetmembers;
- for (size_t i = 0; i < decl->members->dim; i++)
- {
- Dsymbol *member = (*decl->members)[i];
- member->addLocalClass (&aclasses);
- }
- size_t aimports_dim = decl->aimports.dim;
- for (size_t i = 0; i < decl->aimports.dim; i++)
- {
- Module *mi = decl->aimports[i];
- if (!mi->needmoduleinfo)
- aimports_dim--;
- }
- sgetmembers = decl->findGetMembers ();
- size_t flags = 0;
- if (decl->sctor)
- flags |= MItlsctor;
- if (decl->sdtor)
- flags |= MItlsdtor;
- if (decl->ssharedctor)
- flags |= MIctor;
- if (decl->sshareddtor)
- flags |= MIdtor;
- if (sgetmembers)
- flags |= MIxgetMembers;
- if (decl->sictor)
- flags |= MIictor;
- if (decl->stest)
- flags |= MIunitTest;
- if (aimports_dim)
- flags |= MIimportedModules;
- if (aclasses.dim)
- flags |= MIlocalClasses;
- if (!decl->needmoduleinfo)
- flags |= MIstandalone;
- flags |= MIname;
- tree minfo = get_moduleinfo_decl (decl);
- tree type = layout_moduleinfo_fields (decl, TREE_TYPE (minfo));
- /* Put out the two named fields in a ModuleInfo decl:
- uint flags;
- uint index; */
- vec<constructor_elt, va_gc> *minit = NULL;
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE,
- build_integer_cst (flags, d_uint_type));
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE,
- build_integer_cst (0, d_uint_type));
- /* Order of appearance, depending on flags:
- void function() tlsctor;
- void function() tlsdtor;
- void* function() xgetMembers;
- void function() ctor;
- void function() dtor;
- void function() ictor;
- void function() unitTest;
- ModuleInfo*[] importedModules;
- TypeInfo_Class[] localClasses;
- char[N] name;
- */
- if (flags & MItlsctor)
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, build_address (decl->sctor));
- if (flags & MItlsdtor)
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, build_address (decl->sdtor));
- if (flags & MIctor)
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE,
- build_address (decl->ssharedctor));
- if (flags & MIdtor)
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE,
- build_address (decl->sshareddtor));
- if (flags & MIxgetMembers)
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE,
- build_address (get_symbol_decl (sgetmembers)));
- if (flags & MIictor)
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, build_address (decl->sictor));
- if (flags & MIunitTest)
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, build_address (decl->stest));
- if (flags & MIimportedModules)
- {
- vec<constructor_elt, va_gc> *elms = NULL;
- tree satype = make_array_type (Type::tvoidptr, aimports_dim);
- size_t idx = 0;
- for (size_t i = 0; i < decl->aimports.dim; i++)
- {
- Module *mi = decl->aimports[i];
- if (mi->needmoduleinfo)
- {
- CONSTRUCTOR_APPEND_ELT (elms, size_int (idx),
- build_address (get_moduleinfo_decl (mi)));
- idx++;
- }
- }
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, size_int (aimports_dim));
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE,
- build_constructor (satype, elms));
- }
- if (flags & MIlocalClasses)
- {
- vec<constructor_elt, va_gc> *elms = NULL;
- tree satype = make_array_type (Type::tvoidptr, aclasses.dim);
- for (size_t i = 0; i < aclasses.dim; i++)
- {
- ClassDeclaration *cd = aclasses[i];
- CONSTRUCTOR_APPEND_ELT (elms, size_int (i),
- build_address (get_classinfo_decl (cd)));
- }
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, size_int (aclasses.dim));
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE,
- build_constructor (satype, elms));
- }
- if (flags & MIname)
- {
- /* Put out module name as a 0-terminated C-string, to save bytes. */
- const char *name = decl->toPrettyChars ();
- size_t namelen = strlen (name) + 1;
- tree strtree = build_string (namelen, name);
- TREE_TYPE (strtree) = make_array_type (Type::tchar, namelen);
- CONSTRUCTOR_APPEND_ELT (minit, NULL_TREE, strtree);
- }
- TREE_TYPE (minfo) = type;
- DECL_INITIAL (minfo) = build_struct_literal (type, minit);
- d_finish_decl (minfo);
- /* Register the module against druntime. */
- register_moduleinfo (decl, minfo);
- }
- /* Send the Module AST class DECL to GCC back-end. */
- void
- build_module_tree (Module *decl)
- {
- /* There may be more than one module per object file, but should only
- ever compile them one at a time. */
- assert (!current_moduleinfo && !current_module_decl);
- module_info mi = module_info ();
- current_moduleinfo = &mi;
- current_module_decl = decl;
- /* Layout module members. */
- if (decl->members)
- {
- for (size_t i = 0; i < decl->members->dim; i++)
- {
- Dsymbol *s = (*decl->members)[i];
- build_decl_tree (s);
- }
- }
- /* Default behavior is to always generate module info because of templates.
- Can be switched off for not compiling against runtime library. */
- if (global.params.useModuleInfo
- && Module::moduleinfo != NULL
- && decl->ident != Identifier::idPool ("__entrypoint"))
- {
- if (mi.ctors || mi.ctorgates)
- decl->sctor = build_funcs_gates_fn (get_identifier ("*__modctor"),
- mi.ctors, mi.ctorgates);
- if (mi.dtors)
- decl->sdtor = build_funcs_gates_fn (get_identifier ("*__moddtor"),
- mi.dtors, NULL);
- if (mi.sharedctors || mi.sharedctorgates)
- decl->ssharedctor
- = build_funcs_gates_fn (get_identifier ("*__modsharedctor"),
- mi.sharedctors, mi.sharedctorgates);
- if (mi.shareddtors)
- decl->sshareddtor
- = build_funcs_gates_fn (get_identifier ("*__modshareddtor"),
- mi.shareddtors, NULL);
- if (mi.unitTests)
- decl->stest = build_funcs_gates_fn (get_identifier ("*__modtest"),
- mi.unitTests, NULL);
- layout_moduleinfo (decl);
- }
- current_moduleinfo = NULL;
- current_module_decl = NULL;
- }
- /* Returns the current function or module context for the purpose
- of imported_module_or_decl. */
- tree
- d_module_context (void)
- {
- if (cfun != NULL)
- return current_function_decl;
- gcc_assert (current_module_decl != NULL);
- return build_import_decl (current_module_decl);
- }
- /* Maybe record declaration D against our module information structure. */
- void
- register_module_decl (Declaration *d)
- {
- FuncDeclaration *fd = d->isFuncDeclaration ();
- if (fd != NULL)
- {
- tree decl = get_symbol_decl (fd);
- /* If a static constructor, push into the current ModuleInfo.
- Checks for `shared' first because it derives from the non-shared
- constructor type in the front-end. */
- if (fd->isSharedStaticCtorDeclaration ())
- vec_safe_push (current_moduleinfo->sharedctors, decl);
- else if (fd->isStaticCtorDeclaration ())
- vec_safe_push (current_moduleinfo->ctors, decl);
- /* If a static destructor, do same as with constructors, but also
- increment the destructor's vgate at construction time. */
- if (fd->isSharedStaticDtorDeclaration ())
- {
- VarDeclaration *vgate = ((SharedStaticDtorDeclaration *) fd)->vgate;
- if (vgate != NULL)
- {
- tree gate = get_symbol_decl (vgate);
- vec_safe_push (current_moduleinfo->sharedctorgates, gate);
- }
- vec_safe_insert (current_moduleinfo->shareddtors, 0, decl);
- }
- else if (fd->isStaticDtorDeclaration ())
- {
- VarDeclaration *vgate = ((StaticDtorDeclaration *) fd)->vgate;
- if (vgate != NULL)
- {
- tree gate = get_symbol_decl (vgate);
- vec_safe_push (current_moduleinfo->ctorgates, gate);
- }
- vec_safe_insert (current_moduleinfo->dtors, 0, decl);
- }
- /* If a unittest function. */
- if (fd->isUnitTestDeclaration ())
- vec_safe_push (current_moduleinfo->unitTests, decl);
- }
- }
- /* Wrapup all global declarations and start the final compilation. */
- void
- d_finish_compilation (tree *vec, int len)
- {
- /* Complete all generated thunks. */
- symtab->process_same_body_aliases ();
- /* Process all file scopes in this compilation, and the external_scope,
- through wrapup_global_declarations. */
- for (int i = 0; i < len; i++)
- {
- tree decl = vec[i];
- wrapup_global_declarations (&decl, 1);
- }
- /* If the target does not directly support static constructors,
- static_ctor_list contains a list of all static constructors defined
- so far. This routine will create a function to call all of those
- and is picked up by collect2. */
- if (static_ctor_list)
- {
- tree decl = build_funcs_gates_fn (get_file_function_name ("I"),
- static_ctor_list, NULL);
- DECL_STATIC_CONSTRUCTOR (decl) = 1;
- decl_init_priority_insert (decl, DEFAULT_INIT_PRIORITY);
- }
- if (static_dtor_list)
- {
- tree decl = build_funcs_gates_fn (get_file_function_name ("D"),
- static_dtor_list, NULL);
- DECL_STATIC_DESTRUCTOR (decl) = 1;
- decl_fini_priority_insert (decl, DEFAULT_INIT_PRIORITY);
- }
- }
- #include "gt-d-modules.h"