aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/modules.cc
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gcc.gnu.org>2018-10-28 19:51:47 +0000
committerIain Buclaw <ibuclaw@gcc.gnu.org>2018-10-28 19:51:47 +0000
commitb4c522fabd0df7be08882d2207df8b2765026110 (patch)
treeb5ffc312b0a441c1ba24323152aec463fdbe5e9f /gcc/d/modules.cc
parent01ce9e31a02c8039d88e90f983735104417bf034 (diff)
downloadgcc-b4c522fabd0df7be08882d2207df8b2765026110.zip
gcc-b4c522fabd0df7be08882d2207df8b2765026110.tar.gz
gcc-b4c522fabd0df7be08882d2207df8b2765026110.tar.bz2
Add D front-end, libphobos library, and D2 testsuite.
ChangeLog: * Makefile.def (target_modules): Add libphobos. (flags_to_pass): Add GDC, GDCFLAGS, GDC_FOR_TARGET and GDCFLAGS_FOR_TARGET. (dependencies): Make libphobos depend on libatomic, libbacktrace configure, and zlib configure. (language): Add language d. * Makefile.in: Rebuild. * Makefile.tpl (BUILD_EXPORTS): Add GDC and GDCFLAGS. (HOST_EXPORTS): Add GDC. (POSTSTAGE1_HOST_EXPORTS): Add GDC and GDC_FOR_BUILD. (BASE_TARGET_EXPORTS): Add GDC. (GDC_FOR_BUILD, GDC, GDCFLAGS): New variables. (GDC_FOR_TARGET, GDC_FLAGS_FOR_TARGET): New variables. (EXTRA_HOST_FLAGS): Add GDC. (STAGE1_FLAGS_TO_PASS): Add GDC. (EXTRA_TARGET_FLAGS): Add GDC and GDCFLAGS. * config-ml.in: Treat GDC and GDCFLAGS like other compiler/flag environment variables. * configure: Rebuild. * configure.ac: Add target-libphobos to target_libraries. Set and substitute GDC_FOR_BUILD and GDC_FOR_TARGET. config/ChangeLog: * multi.m4: Set GDC. gcc/ChangeLog: * Makefile.in (tm_d_file_list, tm_d_include_list): New variables. (TM_D_H, D_TARGET_DEF, D_TARGET_H, D_TARGET_OBJS): New variables. (tm_d.h, cs-tm_d.h, default-d.o): New rules. (d/d-target-hooks-def.h, s-d-target-hooks-def-h): New rules. (s-tm-texi): Also check timestamp on d-target.def. (generated_files): Add TM_D_H and d-target-hooks-def.h. (build/genhooks.o): Also depend on D_TARGET_DEF. * config.gcc (tm_d_file, d_target_objs, target_has_targetdm): New variables. * config/aarch64/aarch64-d.c: New file. * config/aarch64/aarch64-linux.h (GNU_USER_TARGET_D_CRITSEC_SIZE): Define. * config/aarch64/aarch64-protos.h (aarch64_d_target_versions): New prototype. * config/aarch64/aarch64.h (TARGET_D_CPU_VERSIONS): Define. * config/aarch64/t-aarch64 (aarch64-d.o): New rule. * config/arm/arm-d.c: New file. * config/arm/arm-protos.h (arm_d_target_versions): New prototype. * config/arm/arm.h (TARGET_D_CPU_VERSIONS): Define. * config/arm/linux-eabi.h (EXTRA_TARGET_D_OS_VERSIONS): Define. * config/arm/t-arm (arm-d.o): New rule. * config/default-d.c: New file. * config/glibc-d.c: New file. * config/gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/i386/i386-d.c: New file. * config/i386/i386-protos.h (ix86_d_target_versions): New prototype. * config/i386/i386.h (TARGET_D_CPU_VERSIONS): Define. * config/i386/linux-common.h (EXTRA_TARGET_D_OS_VERSIONS): Define. (GNU_USER_TARGET_D_CRITSEC_SIZE): Define. * config/i386/t-i386 (i386-d.o): New rule. * config/kfreebsd-gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/kopensolaris-gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/linux-android.h (ANDROID_TARGET_D_OS_VERSIONS): Define. * config/linux.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/mips/linux-common.h (EXTRA_TARGET_D_OS_VERSIONS): Define. * config/mips/mips-d.c: New file. * config/mips/mips-protos.h (mips_d_target_versions): New prototype. * config/mips/mips.h (TARGET_D_CPU_VERSIONS): Define. * config/mips/t-mips (mips-d.o): New rule. * config/powerpcspe/linux.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/powerpcspe/linux64.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/powerpcspe/powerpcspe-d.c: New file. * config/powerpcspe/powerpcspe-protos.h (rs6000_d_target_versions): New prototype. * config/powerpcspe/powerpcspe.c (rs6000_output_function_epilogue): Support GNU D by using 0 as the language type. * config/powerpcspe/powerpcspe.h (TARGET_D_CPU_VERSIONS): Define. * config/powerpcspe/t-powerpcspe (powerpcspe-d.o): New rule. * config/riscv/riscv-d.c: New file. * config/riscv/riscv-protos.h (riscv_d_target_versions): New prototype. * config/riscv/riscv.h (TARGET_D_CPU_VERSIONS): Define. * config/riscv/t-riscv (riscv-d.o): New rule. * config/rs6000/linux.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/rs6000/linux64.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/rs6000/rs6000-d.c: New file. * config/rs6000/rs6000-protos.h (rs6000_d_target_versions): New prototype. * config/rs6000/rs6000.c (rs6000_output_function_epilogue): Support GNU D by using 0 as the language type. * config/rs6000/rs6000.h (TARGET_D_CPU_VERSIONS): Define. * config/rs6000/t-rs6000 (rs6000-d.o): New rule. * config/s390/s390-d.c: New file. * config/s390/s390-protos.h (s390_d_target_versions): New prototype. * config/s390/s390.h (TARGET_D_CPU_VERSIONS): Define. * config/s390/t-s390 (s390-d.o): New rule. * config/sparc/sparc-d.c: New file. * config/sparc/sparc-protos.h (sparc_d_target_versions): New prototype. * config/sparc/sparc.h (TARGET_D_CPU_VERSIONS): Define. * config/sparc/t-sparc (sparc-d.o): New rule. * config/t-glibc (glibc-d.o): New rule. * configure: Regenerated. * configure.ac (tm_d_file): New variable. (tm_d_file_list, tm_d_include_list, d_target_objs): Add substitutes. * doc/contrib.texi (Contributors): Add self for the D frontend. * doc/frontends.texi (G++ and GCC): Mention D as a supported language. * doc/install.texi (Configuration): Mention libphobos as an option for --enable-shared. Mention d as an option for --enable-languages. (Testing): Mention check-d as a target. * doc/invoke.texi (Overall Options): Mention .d, .dd, and .di as file name suffixes. Mention d as a -x option. * doc/sourcebuild.texi (Top Level): Mention libphobos. * doc/standards.texi (Standards): Add section on D language. * doc/tm.texi: Regenerated. * doc/tm.texi.in: Add @node for D language and ABI, and @hook for TARGET_CPU_VERSIONS, TARGET_D_OS_VERSIONS, and TARGET_D_CRITSEC_SIZE. * dwarf2out.c (is_dlang): New function. (gen_compile_unit_die): Use DW_LANG_D for D. (declare_in_namespace): Return module die for D, instead of adding extra declarations into the namespace. (gen_namespace_die): Generate DW_TAG_module for D. (gen_decl_die): Handle CONST_DECLSs for D. (dwarf2out_decl): Likewise. (prune_unused_types_walk_local_classes): Handle DW_tag_interface_type. (prune_unused_types_walk): Handle DW_tag_interface_type same as other kinds of aggregates. * gcc.c (default_compilers): Add entries for .d, .dd and .di. * genhooks.c: Include d/d-target.def. gcc/po/ChangeLog: * EXCLUDES: Add sources from d/dmd. gcc/testsuite/ChangeLog: * gcc.misc-tests/help.exp: Add D to option descriptions check. * gdc.dg/asan/asan.exp: New file. * gdc.dg/asan/gdc272.d: New test. * gdc.dg/compilable.d: New test. * gdc.dg/dg.exp: New file. * gdc.dg/gdc254.d: New test. * gdc.dg/gdc260.d: New test. * gdc.dg/gdc270a.d: New test. * gdc.dg/gdc270b.d: New test. * gdc.dg/gdc282.d: New test. * gdc.dg/gdc283.d: New test. * gdc.dg/imports/gdc170.d: New test. * gdc.dg/imports/gdc231.d: New test. * gdc.dg/imports/gdc239.d: New test. * gdc.dg/imports/gdc241a.d: New test. * gdc.dg/imports/gdc241b.d: New test. * gdc.dg/imports/gdc251a.d: New test. * gdc.dg/imports/gdc251b.d: New test. * gdc.dg/imports/gdc253.d: New test. * gdc.dg/imports/gdc254a.d: New test. * gdc.dg/imports/gdc256.d: New test. * gdc.dg/imports/gdc27.d: New test. * gdc.dg/imports/gdcpkg256/package.d: New test. * gdc.dg/imports/runnable.d: New test. * gdc.dg/link.d: New test. * gdc.dg/lto/lto.exp: New file. * gdc.dg/lto/ltotests_0.d: New test. * gdc.dg/lto/ltotests_1.d: New test. * gdc.dg/runnable.d: New test. * gdc.dg/simd.d: New test. * gdc.test/gdc-test.exp: New file. * lib/gdc-dg.exp: New file. * lib/gdc.exp: New file. libphobos/ChangeLog: * Makefile.am: New file. * Makefile.in: New file. * acinclude.m4: New file. * aclocal.m4: New file. * config.h.in: New file. * configure: New file. * configure.ac: New file. * d_rules.am: New file. * libdruntime/Makefile.am: New file. * libdruntime/Makefile.in: New file. * libdruntime/__entrypoint.di: New file. * libdruntime/__main.di: New file. * libdruntime/gcc/attribute.d: New file. * libdruntime/gcc/backtrace.d: New file. * libdruntime/gcc/builtins.d: New file. * libdruntime/gcc/config.d.in: New file. * libdruntime/gcc/deh.d: New file. * libdruntime/gcc/libbacktrace.d.in: New file. * libdruntime/gcc/unwind/arm.d: New file. * libdruntime/gcc/unwind/arm_common.d: New file. * libdruntime/gcc/unwind/c6x.d: New file. * libdruntime/gcc/unwind/generic.d: New file. * libdruntime/gcc/unwind/package.d: New file. * libdruntime/gcc/unwind/pe.d: New file. * m4/autoconf.m4: New file. * m4/druntime.m4: New file. * m4/druntime/cpu.m4: New file. * m4/druntime/libraries.m4: New file. * m4/druntime/os.m4: New file. * m4/gcc_support.m4: New file. * m4/gdc.m4: New file. * m4/libtool.m4: New file. * src/Makefile.am: New file. * src/Makefile.in: New file. * src/libgphobos.spec.in: New file. * testsuite/Makefile.am: New file. * testsuite/Makefile.in: New file. * testsuite/config/default.exp: New file. * testsuite/lib/libphobos-dg.exp: New file. * testsuite/lib/libphobos.exp: New file. * testsuite/testsuite_flags.in: New file. From-SVN: r265573
Diffstat (limited to 'gcc/d/modules.cc')
-rw-r--r--gcc/d/modules.cc853
1 files changed, 853 insertions, 0 deletions
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
new file mode 100644
index 0000000..80573e1
--- /dev/null
+++ b/gcc/d/modules.cc
@@ -0,0 +1,853 @@
+/* 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 = PROTprivate;
+ 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.betterC
+ && 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"