public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/ibuclaw/heads/mingw)] More MSVC support
@ 2021-03-24 15:25 Iain Buclaw
  0 siblings, 0 replies; 5+ messages in thread
From: Iain Buclaw @ 2021-03-24 15:25 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:ab68c3421560f9546c77a7a7f1693a55259715b1

commit ab68c3421560f9546c77a7a7f1693a55259715b1
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Wed Mar 24 16:24:04 2021 +0100

    More MSVC support

Diff:
---
 gcc/config/i386/cygming.h                          |   2 +
 gcc/config/i386/i386-d.c                           |  11 +
 gcc/config/i386/i386-protos.h                      |   1 +
 gcc/config/i386/i386.h                             |   3 +-
 gcc/config/i386/winnt-d.c                          |   5 +
 gcc/d/d-target-def.h                               |   1 +
 gcc/d/d-target.cc                                  |  10 +-
 gcc/d/d-target.def                                 |   7 +
 gcc/d/d-target.h                                   |   3 +
 gcc/doc/tm.texi                                    |   2 +
 gcc/doc/tm.texi.in                                 |   2 +
 libphobos/Makefile.in                              |   3 +
 libphobos/configure                                |  24 +-
 libphobos/configure.ac                             |  17 +-
 libphobos/libdruntime/Makefile.am                  |   7 +-
 libphobos/libdruntime/Makefile.in                  |  68 +-
 libphobos/libdruntime/config/mingw/msvc.c          |  54 ++
 libphobos/libdruntime/config/mingw/switchcontext.S |  12 +-
 libphobos/libdruntime/core/stdc/stdlib.d           |  27 +-
 libphobos/libdruntime/core/stdc/tgmath.d           |  11 +-
 libphobos/libdruntime/core/sys/windows/com.d       |   4 +-
 libphobos/libdruntime/core/sys/windows/dbghelp.d   |   2 +-
 libphobos/libdruntime/core/sys/windows/dll.d       |  12 +-
 libphobos/libdruntime/core/thread/osthread.d       |   4 +-
 libphobos/libdruntime/gcc/deh.d                    |   2 +-
 libphobos/libdruntime/gcc/gthread.d                |   6 +-
 libphobos/libdruntime/gcc/sections/package.d       |  28 +-
 libphobos/libdruntime/gcc/sections/pecoff.d        | 830 +++++++++++++++++++++
 libphobos/libdruntime/gcc/sections/win32.d         | 183 -----
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/libdruntime/gcc/unwind/generic.d         |   2 +-
 libphobos/libdruntime/rt/dmain2.d                  |  64 --
 libphobos/src/Makefile.am                          |   2 +-
 libphobos/src/Makefile.in                          |   5 +-
 libphobos/testsuite/Makefile.in                    |   3 +
 35 files changed, 1066 insertions(+), 359 deletions(-)

diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index cfbca34f996..59eb812c1cf 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -209,6 +209,8 @@ along with GCC; see the file COPYING3.  If not see
 #define SUBTARGET_OVERRIDE_OPTIONS					\
 do {									\
   flag_pic = TARGET_64BIT ? 1 : 0;                                      \
+  if (!global_options_set.x_dwarf_version)				\
+    dwarf_version = 4;							\
 } while (0)
 
 /* Define this macro if references to a symbol must be treated
diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c
index cbd3ceb187d..05c0f21066d 100644
--- a/gcc/config/i386/i386-d.c
+++ b/gcc/config/i386/i386-d.c
@@ -42,3 +42,14 @@ ix86_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Implement TARGET_D_EXTERN_SYSTEM_LINKAGE for x86 targets.  */
+
+int
+ix86_d_extern_system_linkage (void)
+{
+  if (ix86_abi == MS_ABI)
+    return LINKwindows;
+
+  return LINKc;
+}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 9f8a69ea7dc..d07bf09bc65 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void);
 
 /* In i386-d.c  */
 extern void ix86_d_target_versions (void);
+extern int ix86_d_extern_system_linkage (void);
 
 /* In winnt.c  */
 extern void i386_pe_unique_section (tree, int);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 058c1cc25b2..10954fb0aab 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -799,8 +799,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 /* Target Pragmas.  */
 #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
 
-/* Target CPU versions for D.  */
+/* Target hooks for D language.  */
 #define TARGET_D_CPU_VERSIONS ix86_d_target_versions
+#define TARGET_D_EXTERN_SYSTEM_LINKAGE ix86_d_extern_system_linkage
 
 #ifndef CC1_SPEC
 #define CC1_SPEC "%(cc1_cpu) "
diff --git a/gcc/config/i386/winnt-d.c b/gcc/config/i386/winnt-d.c
index 3b5791a7bff..5d20fbf51dc 100644
--- a/gcc/config/i386/winnt-d.c
+++ b/gcc/config/i386/winnt-d.c
@@ -30,6 +30,11 @@ winnt_d_os_builtins (void)
 {
   d_add_builtin_version ("Windows");
 
+  if (ix86_abi == SYSV_ABI)
+    d_add_builtin_version ("SYSV_ABI");
+  else
+    d_add_builtin_version ("MS_ABI");
+
 #define builtin_version(TXT) d_add_builtin_version (TXT)
 
 #ifdef EXTRA_TARGET_D_OS_VERSIONS
diff --git a/gcc/d/d-target-def.h b/gcc/d/d-target-def.h
index eb3236f174d..63389a5d82a 100644
--- a/gcc/d/d-target-def.h
+++ b/gcc/d/d-target-def.h
@@ -17,4 +17,5 @@
 
 #include "d/d-target-hooks-def.h"
 #include "tree.h"
+#include "d-target.h"
 #include "hooks.h"
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index d50fcef22e2..a33e04197b8 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -417,10 +417,18 @@ TargetCPP::fundamentalType (const Type *, bool &)
   return false;
 }
 
-/* Return the default system linkage for the target.  */
+/* Return the default `extern (System)` linkage for the target.  */
 
 LINK
 Target::systemLinkage (void)
+{
+  return (LINK) targetdm.d_extern_system_linkage ();
+}
+
+/* */
+
+int
+d_default_system_linkage (void)
 {
   return LINKc;
 }
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index d1426a17e99..5a419731faa 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -46,6 +46,13 @@ relating to the target operating system.",
  void, (void),
  hook_void_void)
 
+/* */
+DEFHOOK
+(d_extern_system_linkage,
+ "",
+ int, (void),
+ d_default_system_linkage)
+
 /* ModuleInfo section name and brackets.  */
 DEFHOOKPOD
 (d_minfo_section,
diff --git a/gcc/d/d-target.h b/gcc/d/d-target.h
index 56595d225bf..2020b3c2e76 100644
--- a/gcc/d/d-target.h
+++ b/gcc/d/d-target.h
@@ -46,4 +46,7 @@ struct d_target_info_spec
 /* Used by target to add getTargetInfo handlers.  */
 extern void d_add_target_info_handlers (const d_target_info_spec *);
 
+/* If the target does not provide its own override.  */
+extern LINK d_default_system_linkage (void);
+
 #endif /* GCC_D_TARGET_H  */
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b272fa4806d..84de504775d 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10808,6 +10808,8 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions
 relating to the target operating system.
 @end deftypefn
 
+@deftypefn {D Target Hook} int TARGET_D_EXTERN_SYSTEM_LINKAGE (void)
+
 @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION
 Contains the name of the section in which module info references should be
 placed.  This section is expected to be bracketed by two symbols to indicate
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index bf724dc093c..ef15417a791 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7357,6 +7357,8 @@ floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_OS_VERSIONS
 
+@hook TARGET_D_EXTERN_SYSTEM_LINKAGE
+
 @hook TARGET_D_MINFO_SECTION
 
 @hook TARGET_D_MINFO_START_NAME
diff --git a/libphobos/Makefile.in b/libphobos/Makefile.in
index d42248405a2..eab12688867 100644
--- a/libphobos/Makefile.in
+++ b/libphobos/Makefile.in
@@ -298,6 +298,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -327,6 +329,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
diff --git a/libphobos/configure b/libphobos/configure
index c940a404be4..59ca64aa1e0 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -705,6 +705,9 @@ libphobos_builddir
 get_gcc_base_ver
 phobos_compiler_shared_flag
 phobos_compiler_pic_flag
+phobos_lt_pic_flag
+enable_static
+enable_shared
 OTOOL64
 OTOOL
 LIPO
@@ -11746,7 +11749,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11749 "configure"
+#line 11752 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11852,7 +11855,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11855 "configure"
+#line 11858 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13997,8 +14000,14 @@ CFLAGS=$lt_save_CFLAGS
   GDCFLAGS=$gdc_save_DFLAGS
 
 
+
+
 # libtool variables for Phobos shared and position-independent compiles.
 #
+# Use phobos_lt_pic_flag to designate the automake variable
+# used to encapsulate the default libtool approach to creating objects
+# with position-independent code. Default: -prefer-pic.
+#
 # Use phobos_compiler_shared_flag to designate the compile-time flags for
 # creating shared objects. Default: -fversion=Shared.
 #
@@ -14010,26 +14019,23 @@ CFLAGS=$lt_save_CFLAGS
 # libtool, and so we make it here.  How it is handled is that in shared
 # compilations the `lt_prog_compiler_pic_D' variable is used to instead
 # ensure that conditional compilation of shared runtime code is compiled in.
-# The original PIC flags are then used in the compilation of every object.
-#
-# Why are objects destined for libgphobos.a compiled with -fPIC?
-# Because -fPIC is not harmful to use for objects destined for static
-# libraries. In addition, using -fPIC will allow the use of static
-# libgphobos.a in the creation of other D shared libraries.
 if test "$enable_shared" = yes; then
+  phobos_lt_pic_flag="-prefer-pic"
   phobos_compiler_pic_flag="$lt_prog_compiler_pic_D"
   phobos_compiler_shared_flag="-fversion=Shared"
 else
+  phobos_lt_pic_flag=
   phobos_compiler_pic_flag=
   phobos_compiler_shared_flag=
 fi
 
 
 
+
 # Override the libtool's pic_flag and pic_mode.
 # Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT.
 # NB: this impacts --with-pic and --without-pic.
-lt_prog_compiler_pic_D="$phobos_compiler_shared_flag"
+lt_prog_compiler_pic_D="$phobos_compiler_pic_flag $phobos_compiler_shared_flag"
 pic_mode='default'
 
 # Determine what GCC version number to use in filesystem paths.
diff --git a/libphobos/configure.ac b/libphobos/configure.ac
index cc9af29754f..248d0ebbc19 100644
--- a/libphobos/configure.ac
+++ b/libphobos/configure.ac
@@ -91,9 +91,15 @@ AC_SUBST(CFLAGS_FOR_BUILD)
 LT_INIT(dlopen)
 AM_PROG_LIBTOOL
 WITH_LOCAL_DRUNTIME([LT_LANG([D])], [])
+AC_SUBST(enable_shared)
+AC_SUBST(enable_static)
 
 # libtool variables for Phobos shared and position-independent compiles.
 #
+# Use phobos_lt_pic_flag to designate the automake variable
+# used to encapsulate the default libtool approach to creating objects
+# with position-independent code. Default: -prefer-pic.
+#
 # Use phobos_compiler_shared_flag to designate the compile-time flags for
 # creating shared objects. Default: -fversion=Shared.
 #
@@ -105,26 +111,23 @@ WITH_LOCAL_DRUNTIME([LT_LANG([D])], [])
 # libtool, and so we make it here.  How it is handled is that in shared
 # compilations the `lt_prog_compiler_pic_D' variable is used to instead
 # ensure that conditional compilation of shared runtime code is compiled in.
-# The original PIC flags are then used in the compilation of every object.
-#
-# Why are objects destined for libgphobos.a compiled with -fPIC?
-# Because -fPIC is not harmful to use for objects destined for static
-# libraries. In addition, using -fPIC will allow the use of static
-# libgphobos.a in the creation of other D shared libraries.
 if test "$enable_shared" = yes; then
+  phobos_lt_pic_flag="-prefer-pic"
   phobos_compiler_pic_flag="$lt_prog_compiler_pic_D"
   phobos_compiler_shared_flag="-fversion=Shared"
 else
+  phobos_lt_pic_flag=
   phobos_compiler_pic_flag=
   phobos_compiler_shared_flag=
 fi
+AC_SUBST(phobos_lt_pic_flag)
 AC_SUBST(phobos_compiler_pic_flag)
 AC_SUBST(phobos_compiler_shared_flag)
 
 # Override the libtool's pic_flag and pic_mode.
 # Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT.
 # NB: this impacts --with-pic and --without-pic.
-lt_prog_compiler_pic_D="$phobos_compiler_shared_flag"
+lt_prog_compiler_pic_D="$phobos_compiler_pic_flag $phobos_compiler_shared_flag"
 pic_mode='default'
 
 # Determine what GCC version number to use in filesystem paths.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 945271e028f..bedd7a325ec 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -23,7 +23,7 @@ D_EXTRA_DFLAGS=-nostdinc -I $(srcdir) -I .
 
 # D flags for compilation
 AM_DFLAGS= \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 # Flags for other kinds of sources
@@ -69,7 +69,8 @@ if DRUNTIME_OS_LINUX
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_LINUX)
 endif
 if DRUNTIME_OS_MINGW
-    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS)
+    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS) \
+				   config/mingw/msvc.c
 endif
 if DRUNTIME_OS_SOLARIS
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_SOLARIS)
@@ -187,7 +188,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
 	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \
+	gcc/sections/package.d gcc/sections/pecoff.d \
 	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 06c02961c86..665af30e09d 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -117,7 +117,9 @@ target_triplet = @target@
 @DRUNTIME_OS_NETBSD_TRUE@am__append_6 = $(DRUNTIME_DSOURCES_NETBSD)
 @DRUNTIME_OS_OPENBSD_TRUE@am__append_7 = $(DRUNTIME_DSOURCES_OPENBSD)
 @DRUNTIME_OS_LINUX_TRUE@am__append_8 = $(DRUNTIME_DSOURCES_LINUX)
-@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS)
+@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS) \
+@DRUNTIME_OS_MINGW_TRUE@				   config/mingw/msvc.c
+
 @DRUNTIME_OS_SOLARIS_TRUE@am__append_10 = $(DRUNTIME_DSOURCES_SOLARIS)
 # CPU specific sources
 @DRUNTIME_CPU_AARCH64_TRUE@am__append_11 = config/aarch64/switchcontext.S
@@ -213,7 +215,7 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
 	gcc/sections/android.lo gcc/sections/elf_shared.lo \
 	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/pecoff.lo gcc/unwind/arm.lo \
 	gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
 	gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
 	object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
@@ -425,7 +427,8 @@ am__objects_19 = core/sys/windows/accctrl.lo \
 	core/sys/windows/winspool.lo core/sys/windows/winsvc.lo \
 	core/sys/windows/winuser.lo core/sys/windows/winver.lo \
 	core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo
-@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19)
+@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_la-msvc.lo
 am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
 	core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \
 	core/sys/solaris/libelf.lo core/sys/solaris/link.lo \
@@ -460,24 +463,26 @@ am_libgdruntime_la_OBJECTS = $(am__objects_33)
 libgdruntime_la_OBJECTS = $(am_libgdruntime_la_OBJECTS)
 am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_34 = core/stdc/libgdruntime_convenience_la-errno_.lo
-@DRUNTIME_CPU_AARCH64_TRUE@am__objects_35 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_ARM_TRUE@am__objects_36 = config/arm/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_MIPS_TRUE@am__objects_37 = config/mips/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_POWERPC_TRUE@am__objects_38 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_39 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_40 = config/x86/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_41 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
-@DRUNTIME_CPU_S390_TRUE@am__objects_42 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
-am__objects_43 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
+@DRUNTIME_OS_MINGW_TRUE@am__objects_35 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_convenience_la-msvc.lo
+@DRUNTIME_CPU_AARCH64_TRUE@am__objects_36 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_ARM_TRUE@am__objects_37 = config/arm/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_MIPS_TRUE@am__objects_38 = config/mips/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_POWERPC_TRUE@am__objects_39 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_40 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_41 = config/x86/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_42 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
+@DRUNTIME_CPU_S390_TRUE@am__objects_43 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
+am__objects_44 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
 	$(am__objects_10) $(am__objects_12) $(am__objects_14) \
-	$(am__objects_16) $(am__objects_18) $(am__objects_20) \
-	$(am__objects_22) $(am__objects_35) $(am__objects_36) \
-	$(am__objects_37) $(am__objects_38) $(am__objects_39) \
-	$(am__objects_40) $(am__objects_41) $(am__objects_42)
-am__objects_44 = $(am__objects_1) $(am__objects_34) $(am__objects_43) \
+	$(am__objects_16) $(am__objects_18) $(am__objects_35) \
+	$(am__objects_22) $(am__objects_36) $(am__objects_37) \
+	$(am__objects_38) $(am__objects_39) $(am__objects_40) \
+	$(am__objects_41) $(am__objects_42) $(am__objects_43)
+am__objects_45 = $(am__objects_1) $(am__objects_34) $(am__objects_44) \
 	$(am__objects_32)
-am__objects_45 = $(am__objects_44)
-am_libgdruntime_convenience_la_OBJECTS = $(am__objects_45)
+am__objects_46 = $(am__objects_45)
+am_libgdruntime_convenience_la_OBJECTS = $(am__objects_46)
 libgdruntime_convenience_la_OBJECTS =  \
 	$(am_libgdruntime_convenience_la_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
@@ -659,6 +664,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -688,6 +695,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
@@ -720,7 +728,7 @@ D_EXTRA_DFLAGS = -nostdinc -I $(srcdir) -I .
 
 # D flags for compilation
 AM_DFLAGS = \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 
@@ -813,7 +821,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
 	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \
+	gcc/sections/package.d gcc/sections/pecoff.d \
 	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
@@ -1213,8 +1221,7 @@ gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/elf_shared.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/osx.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/package.lo: gcc/sections/$(am__dirstamp)
-gcc/sections/win32.lo: gcc/sections/$(am__dirstamp)
-gcc/sections/win64.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/pecoff.lo: gcc/sections/$(am__dirstamp)
 gcc/unwind/$(am__dirstamp):
 	@$(MKDIR_P) gcc/unwind
 	@: > gcc/unwind/$(am__dirstamp)
@@ -1720,6 +1727,10 @@ core/sys/windows/winuser.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/winver.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtsapi32.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtypes.lo: core/sys/windows/$(am__dirstamp)
+config/mingw/$(am__dirstamp):
+	@$(MKDIR_P) config/mingw
+	@: > config/mingw/$(am__dirstamp)
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/$(am__dirstamp)
 core/sys/solaris/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/solaris
 	@: > core/sys/solaris/$(am__dirstamp)
@@ -1769,9 +1780,6 @@ config/powerpc/$(am__dirstamp):
 	@: > config/powerpc/$(am__dirstamp)
 config/powerpc/libgdruntime_la-switchcontext.lo:  \
 	config/powerpc/$(am__dirstamp)
-config/mingw/$(am__dirstamp):
-	@$(MKDIR_P) config/mingw
-	@: > config/mingw/$(am__dirstamp)
 config/mingw/libgdruntime_la-switchcontext.lo:  \
 	config/mingw/$(am__dirstamp)
 config/x86/$(am__dirstamp):
@@ -1796,6 +1804,8 @@ libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EX
 	$(AM_V_GEN)$(libgdruntime_la_LINK) -rpath $(toolexeclibdir) $(libgdruntime_la_OBJECTS) $(libgdruntime_la_LIBADD) $(LIBS)
 core/stdc/libgdruntime_convenience_la-errno_.lo:  \
 	core/stdc/$(am__dirstamp)
+config/mingw/libgdruntime_convenience_la-msvc.lo:  \
+	config/mingw/$(am__dirstamp)
 config/aarch64/libgdruntime_convenience_la-switchcontext.lo:  \
 	config/aarch64/$(am__dirstamp)
 config/arm/libgdruntime_convenience_la-switchcontext.lo:  \
@@ -1991,9 +2001,15 @@ config/s390/libgdruntime_convenience_la-get_tls_offset.lo: config/s390/get_tls_o
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 core/stdc/libgdruntime_convenience_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_convenience_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_convenience_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_convenience_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/libphobos/libdruntime/config/mingw/msvc.c b/libphobos/libdruntime/config/mingw/msvc.c
new file mode 100644
index 00000000000..25b15a06950
--- /dev/null
+++ b/libphobos/libdruntime/config/mingw/msvc.c
@@ -0,0 +1,54 @@
+/* Windows support code to wrap differences between different
+   versions of the Microsoft C libaries.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+
+/* The symbols for stdin, stdout, and stderr are defined for D in the
+   core.stdc.stdio module.  Save the macros and redeclare them here.  */
+#define c_stdin stdin
+#undef stdin
+extern FILE *stdin;
+
+#define c_stdout stdout
+#undef stdout
+extern FILE *stdout;
+
+#define c_stderr stderr
+#undef stderr
+extern FILE *stderr;
+
+/* Set to 1 if run-time is using ucrtbase.dll.  */
+unsigned char msvcUsesUCRT;
+
+void init_msvc()
+{
+#if __MSVCRT_VERSION__ >= 0x1400
+  msvcUsedUCRT = 1;
+#endif
+
+  stdin = c_stdin;
+  stdout = c_stdout;
+  stderr = c_stderr;
+}
diff --git a/libphobos/libdruntime/config/mingw/switchcontext.S b/libphobos/libdruntime/config/mingw/switchcontext.S
index 6592ff604bc..0cb8b015bfc 100644
--- a/libphobos/libdruntime/config/mingw/switchcontext.S
+++ b/libphobos/libdruntime/config/mingw/switchcontext.S
@@ -28,7 +28,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -63,13 +66,15 @@ CSYM(fiber_switchContext):
     popq %RCX;
     jmp *%RCX;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #elif defined(_X86_)
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -104,6 +109,5 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #endif
diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d
index 7caef4c1339..b048a944a88 100644
--- a/libphobos/libdruntime/core/stdc/stdlib.d
+++ b/libphobos/libdruntime/core/stdc/stdlib.d
@@ -121,19 +121,22 @@ ulong   strtoull(scope inout(char)* nptr, scope inout(char)** endptr, int base);
 
 version (CRuntime_Microsoft)
 {
-    // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
-    ///
-    extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
-    {   // Fake it 'till we make it
-        return strtod(nptr, endptr);
+    version (MinGW)
+    {
+        ///
+        real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
+        ///
+        alias __mingw_strtold strtold;
+    }
+    else
+    {
+        // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
+        ///
+        extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
+        {   // Fake it 'till we make it
+            return strtod(nptr, endptr);
+        }
     }
-}
-else version (MinGW)
-{
-    ///
-    real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
-    ///
-    alias __mingw_strtold strtold;
 }
 else
 {
diff --git a/libphobos/libdruntime/core/stdc/tgmath.d b/libphobos/libdruntime/core/stdc/tgmath.d
index 4dd1b3ccc66..9a351db3861 100644
--- a/libphobos/libdruntime/core/stdc/tgmath.d
+++ b/libphobos/libdruntime/core/stdc/tgmath.d
@@ -1409,13 +1409,20 @@ else
     alias core.stdc.math.fabs          fabs;
     version (CRuntime_Microsoft)
     {
+        version (MinGW)
+        {
+            ///
+            alias core.stdc.math.fabsf fabs;
+            ///
+            alias core.stdc.math.fabsl fabs;
+        }
     }
     else
     {
         ///
-        alias core.stdc.math.fabsf         fabs;
+        alias core.stdc.math.fabsf     fabs;
         ///
-        alias core.stdc.math.fabsl         fabs;
+        alias core.stdc.math.fabsl     fabs;
     }
 
     ///
diff --git a/libphobos/libdruntime/core/sys/windows/com.d b/libphobos/libdruntime/core/sys/windows/com.d
index 90a294343fc..2808a6c59fc 100644
--- a/libphobos/libdruntime/core/sys/windows/com.d
+++ b/libphobos/libdruntime/core/sys/windows/com.d
@@ -57,12 +57,12 @@ alias COINIT_SPEED_OVER_MEMORY   = COINIT.COINIT_SPEED_OVER_MEMORY;
 
 public import core.sys.windows.uuid;
 
-extern (System)
+extern (Windows)
 {
 
 class ComObject : IUnknown
 {
-extern (System):
+extern (Windows):
     HRESULT QueryInterface(const(IID)* riid, void** ppv)
     {
         if (*riid == IID_IUnknown)
diff --git a/libphobos/libdruntime/core/sys/windows/dbghelp.d b/libphobos/libdruntime/core/sys/windows/dbghelp.d
index 8c9827034e9..9848fb99115 100644
--- a/libphobos/libdruntime/core/sys/windows/dbghelp.d
+++ b/libphobos/libdruntime/core/sys/windows/dbghelp.d
@@ -18,7 +18,7 @@ import core.sys.windows.windef;
 
 public import core.sys.windows.dbghelp_types;
 
-extern(System)
+extern(Windows)
 {
     alias BOOL         function(HANDLE hProcess, DWORD64 lpBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) ReadProcessMemoryProc64;
     alias PVOID        function(HANDLE hProcess, DWORD64 AddrBase) FunctionTableAccessProc64;
diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d
index 9f36ac389a6..3df0d7fd41b 100644
--- a/libphobos/libdruntime/core/sys/windows/dll.d
+++ b/libphobos/libdruntime/core/sys/windows/dll.d
@@ -31,17 +31,7 @@ public import core.sys.windows.threadaux;
 //  not access tls_array[tls_index] as needed for thread local _tlsstart and _tlsend
 extern (C)
 {
-        version (MinGW)
-        {
-            extern __gshared void* _tls_start;
-            extern __gshared void* _tls_end;
-            extern __gshared void* __xl_a;
-
-            alias _tls_start _tlsstart;
-            alias _tls_end   _tlsend;
-            alias __xl_a     _tls_callbacks_a;
-        }
-        else version (Win32)
+    version (Win32)
     {
         version (CRuntime_DigitalMars)
         {
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index defdc9586f1..638eada3e43 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -1539,9 +1539,9 @@ package extern(D) void* getStackBottom() nothrow @nogc
             void *bottom;
 
             version (X86)
-                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" (bottom); }
             else version (X86_64)
-                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" (bottom); }
             else
                 static assert(false, "Platform not supported.");
 
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index c747b5132d1..7e02dabd221 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -805,7 +805,7 @@ version (GNU_SEH_Exceptions)
                                                            void* ms_orig_context, void* ms_disp)
     {
         return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context,
-                                     ms_disp, &__gdc_personality_imp);
+                                     ms_disp, &gdc_personality);
     }
 }
 else version (GNU_SjLj_Exceptions)
diff --git a/libphobos/libdruntime/gcc/gthread.d b/libphobos/libdruntime/gcc/gthread.d
index ef35a3c27ec..5003637b9ea 100644
--- a/libphobos/libdruntime/gcc/gthread.d
+++ b/libphobos/libdruntime/gcc/gthread.d
@@ -86,10 +86,12 @@ else static if (GNU_Thread_Model == ThreadModel.Single)
 }
 else static if (GNU_Thread_Model == ThreadModel.Win32)
 {
+    import core.stdc.config;
+
     struct __gthread_once_t
     {
-        INT done;
-        LONG started;
+        int done;
+        c_long started;
     }
 
     int __gthr_win32_key_create(__gthread_key_t* keyp, GthreadDestroyFn dtor);
diff --git a/libphobos/libdruntime/gcc/sections/package.d b/libphobos/libdruntime/gcc/sections/package.d
index fdaf039fcfa..5d76072af25 100644
--- a/libphobos/libdruntime/gcc/sections/package.d
+++ b/libphobos/libdruntime/gcc/sections/package.d
@@ -22,26 +22,20 @@
 
 module gcc.sections;
 
-version (CRuntime_Glibc)
-    public import gcc.sections.elf_shared;
-else version (CRuntime_Musl)
-    public import gcc.sections.elf_shared;
-else version (CRuntime_UClibc)
-    public import gcc.sections.elf_shared;
-else version (FreeBSD)
-    public import gcc.sections.elf_shared;
-else version (NetBSD)
-    public import gcc.sections.elf_shared;
-else version (DragonFlyBSD)
-    public import gcc.sections.elf_shared;
-else version (Solaris)
+version (CRuntime_Glibc)  version = ElfShared;
+version (CRuntime_Musl)   version = ElfShared;
+version (CRuntime_UClibc) version = ElfShared;
+version (FreeBSD)         version = ElfShared;
+version (NetBSD)          version = ElfShared;
+version (DragonFlyBSD)    version = ElfShared;
+version (Solaris)         version = ElfShared;
+
+version (ElfShared)
     public import gcc.sections.elf_shared;
 else version (OSX)
     public import gcc.sections.osx;
-else version (CRuntime_DigitalMars)
-    public import gcc.sections.win32;
-else version (CRuntime_Microsoft)
-    public import gcc.sections.win64;
+else version (Windows)
+    public import gcc.sections.pecoff;
 else version (CRuntime_Bionic)
     public import gcc.sections.android;
 else
diff --git a/libphobos/libdruntime/gcc/sections/pecoff.d b/libphobos/libdruntime/gcc/sections/pecoff.d
new file mode 100644
index 00000000000..5fa1df2ac54
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/pecoff.d
@@ -0,0 +1,830 @@
+// PE/COFF-specific support for sections.
+// Copyright (C) 2021 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.pecoff;
+
+version (Windows):
+
+import core.memory;
+import core.stdc.stdlib;
+import core.sys.windows.winbase;
+import core.sys.windows.windef;
+import core.sys.windows.winnt;
+import rt.minfo;
+import rt.util.container.array;
+import rt.util.container.hashtab;
+
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+/****
+ * Asserts the specified condition, independent from -release, by abort()ing.
+ * Regular assertions throw an AssertError and thus require an initialized
+ * GC, which isn't the case (yet or anymore) for the startup/shutdown code in
+ * this module (called by CRT ctors/dtors etc.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+alias DSO SectionGroup;
+struct DSO
+{
+    static int opApply(scope int delegate(ref DSO) dg)
+    {
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
+    {
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+
+    invariant()
+    {
+        safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO.");
+    }
+
+    void** _slot;
+    ModuleGroup _moduleGroup;
+    Array!(void[]) _gcRanges;
+
+    version (Shared)
+    {
+        Array!(void[]) _codeSegments; // array of code segments
+        Array!(DSO*) _deps; // D libraries needed by this DSO
+        void* _handle; // corresponding handle
+    }
+}
+
+/****
+ * Boolean flag set to true while the runtime is initialized.
+ */
+__gshared bool _isRuntimeInitialized;
+
+/****
+ * Gets called on program startup just before GC is initialized.
+ */
+void initSections() nothrow @nogc
+{
+    _isRuntimeInitialized = true;
+}
+
+/***
+ * Gets called on program shutdown just after GC is terminated.
+ */
+void finiSections() nothrow @nogc
+{
+    _isRuntimeInitialized = false;
+}
+
+alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
+
+version (Shared)
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(ThreadDSO)* initTLSRanges() @nogc nothrow
+    {
+        return &_loadedDSOs();
+    }
+
+    void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow
+    {
+        // Nothing to do here. tdsos used to point to the _loadedDSOs instance
+        // in the dying thread's TLS segment and as such is not valid anymore.
+        // The memory for the array contents was already reclaimed in
+        // cleanupLoadedLibraries().
+    }
+
+    void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
+
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof);
+        res.length = _loadedDSOs.length;
+        foreach (i, ref tdso; _loadedDSOs)
+        {
+            (*res)[i] = tdso;
+            if (tdso._addCnt)
+            {
+                // Increment the DLL ref for explicitly loaded libraries to pin them.
+                char[MAX_PATH] buf;
+                char[] buffer = buf[];
+                const success = .LoadLibraryA(nameForDSO(tdso._pdso, buffer)) !is null;
+                safeAssert(success, "Failed to increment DLL ref.");
+                (*res)[i]._addCnt = 1; // new array takes over the additional ref count
+            }
+        }
+        return res;
+    }
+
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+        auto pary = cast(Array!(ThreadDSO)*)p;
+        // In case something failed we need to undo the pinning.
+        foreach (ref tdso; *pary)
+        {
+            if (tdso._addCnt)
+            {
+                auto handle = tdso._pdso._handle;
+                safeAssert(handle !is null, "Invalid library handle.");
+                .FreeLibrary(handle);
+            }
+        }
+        pary.reset();
+        .free(pary);
+    }
+
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
+    {
+        safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread.");
+        _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p);
+        .free(p);
+    }
+
+    // Called after all TLS dtors ran, decrements all remaining DLL refs.
+    void cleanupLoadedLibraries() nothrow @nogc
+    {
+        foreach (ref tdso; _loadedDSOs)
+        {
+            if (tdso._addCnt == 0) continue;
+
+            auto handle = tdso._pdso._handle;
+            safeAssert(handle !is null, "Invalid DSO handle.");
+            for (; tdso._addCnt > 0; --tdso._addCnt)
+                .FreeLibrary(handle);
+        }
+
+        // Free the memory for the array contents.
+        _loadedDSOs.reset();
+    }
+}
+else
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(void[])* initTLSRanges() nothrow @nogc
+    {
+        return null;
+    }
+
+    void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc
+    {
+    }
+
+    void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
+}
+
+private:
+
+version (Shared)
+{
+    /*
+     * Array of thread local DSO metadata for all libraries loaded and
+     * initialized in this thread.
+     *
+     * Note:
+     *     A newly spawned thread will inherit these libraries.
+     * Note:
+     *     We use an array here to preserve the order of
+     *     initialization.  If that became a performance issue, we
+     *     could use a hash table and enumerate the DSOs during
+     *     loading so that the hash table values could be sorted when
+     *     necessary.
+     */
+    struct ThreadDSO
+    {
+        DSO* _pdso;
+        static if (_pdso.sizeof == 8) uint _refCnt, _addCnt;
+        else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt;
+        else static assert(0, "unimplemented");
+        alias _pdso this;
+    }
+
+    @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow
+    {
+        static Array!(ThreadDSO) x;
+        return x;
+    }
+
+    /*
+     * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+     */
+    bool _rtLoading;
+
+    /*
+     * Hash table to map the native handle (as returned by dlopen)
+     * to the corresponding DSO*, protected by a mutex.
+     */
+    __gshared CRITICAL_SECTION _handleToDSOMutex;
+    @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow
+    {
+        __gshared HashTab!(void*, DSO*) x;
+        return x;
+    }
+}
+else
+{
+    /*
+     * Static DSOs loaded by the runtime linker. This includes the
+     * executable. These can't be unloaded.
+     */
+    @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
+    {
+        __gshared Array!(DSO*) x;
+        return x;
+    }
+
+    enum _rtLoading = false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
+
+/****
+ * This data structure is generated by the compiler, and then passed to
+ * _d_dso_registry().
+ */
+struct CompilerDSOData
+{
+    size_t _version;                                       // currently 1
+    void** _slot;                                          // can be used to store runtime data
+    immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file
+}
+
+T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; }
+
+/* For each shared library and executable, the compiler generates code that
+ * sets up CompilerDSOData and calls _d_dso_registry().
+ * A pointer to that code is inserted into both the .ctors and .dtors
+ * segment so it gets called by the loader on startup and shutdown.
+ */
+extern(C) void _d_dso_registry(CompilerDSOData* data)
+{
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
+
+    // no backlink => register
+    if (*data._slot is null)
+    {
+        immutable firstDSO = _loadedDSOs.empty;
+        if (firstDSO) initLocks();
+
+        DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
+        assert(typeid(DSO).initializer().ptr is null);
+        pdso._slot = data._slot;
+        *data._slot = pdso; // store backlink in library record
+
+        pdso._moduleGroup = ModuleGroup(toRange(data._minfo_beg, data._minfo_end));
+
+        HMODULE handle = void;
+        const moduleFound = findModuleHandleForAddr(data._slot, handle);
+        safeAssert(moduleFound, "Failed to find image header.");
+
+        scanSegments(handle, pdso);
+
+        version (Shared)
+        {
+            getDependencies(handle, pdso._deps);
+            pdso._handle = handle;
+            setDSOForHandle(pdso, pdso._handle);
+
+            if (!_rtLoading)
+            {
+                /* This DSO was not loaded by rt_loadLibrary which
+                 * happens for all dependencies of an executable or
+                 * the first dlopen call from a C program.
+                 * In this case we add the DSO to the _loadedDSOs of this
+                 * thread with a refCnt of 1 and call the TlsCtors.
+                 */
+                immutable ushort refCnt = 1, addCnt = 0;
+                _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            }
+        }
+        else
+        {
+            foreach (p; _loadedDSOs)
+                safeAssert(p !is pdso, "DSO already registered.");
+            _loadedDSOs.insertBack(pdso);
+        }
+
+        // don't initialize modules before rt_init was called
+        if (_isRuntimeInitialized)
+        {
+            registerGCRanges(pdso);
+            // rt_loadLibrary will run tls ctors, so do this only for dlopen
+            immutable runTlsCtors = !_rtLoading;
+            runModuleConstructors(pdso, runTlsCtors);
+        }
+    }
+    // has backlink => unregister
+    else
+    {
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
+
+        // don't finalizes modules after rt_term was called (see Bugzilla 11378)
+        if (_isRuntimeInitialized)
+        {
+            // rt_unloadLibrary already ran tls dtors, so do this only for dlclose
+            immutable runTlsDtors = !_rtLoading;
+            runModuleDestructors(pdso, runTlsDtors);
+            unregisterGCRanges(pdso);
+            // run finalizers after module dtors (same order as in rt_term)
+            version (Shared) runFinalizers(pdso);
+        }
+
+        version (Shared)
+        {
+            if (!_rtLoading)
+            {
+                /* This DSO was not unloaded by rt_unloadLibrary so we
+                 * have to remove it from _loadedDSOs here.
+                 */
+                foreach (i, ref tdso; _loadedDSOs)
+                {
+                    if (tdso._pdso == pdso)
+                    {
+                        _loadedDSOs.remove(i);
+                        break;
+                    }
+                }
+            }
+
+            unsetDSOForHandle(pdso, pdso._handle);
+        }
+        else
+        {
+            // static DSOs are unloaded in reverse order
+            safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+            _loadedDSOs.popBack();
+        }
+
+        freeDSO(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+            version (Shared)
+            {
+                safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs.");
+                _handleToDSO.reset();
+            }
+            finiLocks();
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// dynamic loading
+///////////////////////////////////////////////////////////////////////////////
+
+// Shared D libraries are only supported when linking against a shared druntime library.
+
+version (Shared)
+{
+    ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc
+    {
+        foreach (ref tdata; _loadedDSOs)
+            if (tdata._pdso == pdso) return &tdata;
+        return null;
+    }
+
+    void incThreadRef(DSO* pdso, bool incAdd)
+    {
+        if (auto tdata = findThreadDSO(pdso)) // already initialized
+        {
+            if (incAdd && ++tdata._addCnt > 1) return;
+            ++tdata._refCnt;
+        }
+        else
+        {
+            foreach (dep; pdso._deps)
+                incThreadRef(dep, false);
+            immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
+            _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            pdso._moduleGroup.runTlsCtors();
+        }
+    }
+
+    void decThreadRef(DSO* pdso, bool decAdd)
+    {
+        auto tdata = findThreadDSO(pdso);
+        safeAssert(tdata !is null, "Failed to find thread DSO.");
+        safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call.");
+
+        if (decAdd && --tdata._addCnt > 0) return;
+        if (--tdata._refCnt > 0) return;
+
+        pdso._moduleGroup.runTlsDtors();
+        foreach (i, ref td; _loadedDSOs)
+            if (td._pdso == pdso) _loadedDSOs.remove(i);
+        foreach (dep; pdso._deps)
+            decThreadRef(dep, false);
+    }
+}
+
+/***********************************
+ * These are a temporary means of providing a GC hook for DLL use.  They may be
+ * replaced with some other similar functionality later.
+ */
+extern (C)
+{
+    void* gc_getProxy();
+    void  gc_setProxy(void* p);
+    void  gc_clrProxy();
+
+    alias void  function(void*) gcSetFn;
+    alias void  function()      gcClrFn;
+}
+
+/*******************************************
+ * Loads a DLL written in D with the name 'name'.
+ * Returns:
+ *      opaque handle to the DLL if successfully loaded
+ *      null if failure
+ */
+extern(C) void* rt_loadLibrary(const char* name)
+{
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+    }
+    return initLibrary(.LoadLibraryA(name));
+}
+
+extern (C) void* rt_loadLibraryW(const wchar_t* name)
+{
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+    }
+    return initLibrary(.LoadLibraryW(name));
+}
+
+void* initLibrary(void* handle)
+{
+    if (handle is null)
+        return null;
+
+    version (Shared)
+    {
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            incThreadRef(pdso, true);
+    }
+    gcSetFn gcSet = cast(gcSetFn) GetProcAddress(handle, "gc_setProxy");
+    if (gcSet !is null)
+    {
+        // BUG: Set proxy, but too late
+        gcSet(gc_getProxy());
+    }
+    return handle;
+}
+
+/*************************************
+ * Unloads DLL that was previously loaded by rt_loadLibrary().
+ * Input:
+ *      handle  the handle returned by rt_loadLibrary()
+ * Returns:
+ *      1   succeeded
+ *      0   some failure happened
+ */
+extern(C) int rt_unloadLibrary(void* handle)
+{
+    if (handle is null)
+        return false;
+
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            decThreadRef(pdso, true);
+    }
+    gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(handle, "gc_clrProxy");
+    if (gcClr !is null)
+        gcClr();
+    return .FreeLibrary(handle) != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// helper functions
+///////////////////////////////////////////////////////////////////////////////
+
+void initLocks() nothrow @nogc
+{
+    version (Shared)
+        InitializeCriticalSection(&_handleToDSOMutex);
+}
+
+void finiLocks() nothrow @nogc
+{
+    version (Shared)
+        DeleteCriticalSection(&_handleToDSOMutex);
+}
+
+void runModuleConstructors(DSO* pdso, bool runTlsCtors)
+{
+    pdso._moduleGroup.sortCtors();
+    pdso._moduleGroup.runCtors();
+    if (runTlsCtors) pdso._moduleGroup.runTlsCtors();
+}
+
+void runModuleDestructors(DSO* pdso, bool runTlsDtors)
+{
+    if (runTlsDtors) pdso._moduleGroup.runTlsDtors();
+    pdso._moduleGroup.runDtors();
+}
+
+void registerGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.addRange(rng.ptr, rng.length);
+}
+
+void unregisterGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.removeRange(rng.ptr);
+}
+
+version (Shared) void runFinalizers(DSO* pdso)
+{
+    foreach (seg; pdso._codeSegments)
+        GC.runFinalizers(seg);
+}
+
+void freeDSO(DSO* pdso) nothrow @nogc
+{
+    pdso._gcRanges.reset();
+    version (Shared)
+    {
+        pdso._codeSegments.reset();
+        pdso._deps.reset();
+        pdso._handle = null;
+    }
+    .free(pdso);
+}
+
+version (Shared)
+{
+@nogc nothrow:
+    const(char)* nameForDSO(DSO* pdso, ref char[] buffer)
+    {
+        const success = GetModuleFileNameA(pdso._handle, buffer.ptr, cast(DWORD)buffer.length) != 0;
+        safeAssert(success, "Failed to get DLL name.");
+        return buffer.ptr;
+    }
+
+    DSO* dsoForHandle(in void* handle)
+    {
+        DSO* pdso;
+        .EnterCriticalSection(&_handleToDSOMutex);
+        if (auto ppdso = handle in _handleToDSO)
+            pdso = *ppdso;
+        .LeaveCriticalSection(&_handleToDSOMutex);
+        return pdso;
+    }
+
+    void setDSOForHandle(DSO* pdso, void* handle)
+    {
+        .EnterCriticalSection(&_handleToDSOMutex);
+        safeAssert(handle !in _handleToDSO, "DSO already registered.");
+        _handleToDSO[handle] = pdso;
+        .LeaveCriticalSection(&_handleToDSOMutex);
+    }
+
+    void unsetDSOForHandle(DSO* pdso, void* handle)
+    {
+        .EnterCriticalSection(&_handleToDSOMutex);
+        safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO.");
+        _handleToDSO.remove(handle);
+        .LeaveCriticalSection(&_handleToDSOMutex);
+    }
+
+    void getDependencies(in HMODULE handle, ref Array!(DSO*) deps)
+    {
+        auto nthdr = getNTHeader(handle);
+        auto import_entry = nthdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+        auto addr = import_entry.VirtualAddress;
+        auto datasize = import_entry.Size;
+
+        if (addr == 0 && datasize == 0)
+        {
+            // Maybe the optional header isn't there, look for the section.
+            foreach (section; getSectionHeader(handle))
+            {
+                if (!compareSectionName(section, ".idata"))
+                    continue;
+                addr = section.VirtualAddress;
+                datasize = section.Misc.VirtualSize;
+                break;
+            }
+            if (datasize == 0)
+                return;
+        }
+        else
+        {
+            bool foundSection = false;
+            foreach (section; getSectionHeader(handle))
+            {
+                if (!compareSectionName(section, ".idata"))
+                    continue;
+                // Section containing import table has no contents.
+                if (section.Misc.VirtualSize == 0)
+                    return;
+                foundSection = true;
+                break;
+            }
+            // There is an import table, but the section containing it could not be found
+            if (!foundSection)
+                return;
+        }
+
+        // Get the names of each DLL
+        for (uint i = 0; i + IMAGE_IMPORT_DESCRIPTOR.sizeof <= datasize;
+             i += IMAGE_IMPORT_DESCRIPTOR.sizeof)
+        {
+            const data = cast(PIMAGE_IMPORT_DESCRIPTOR)(handle + addr + i);
+            if (data.Name == 0)
+                break;
+
+            // dll name of dependency
+            auto name = cast(char*)(handle + data.Name);
+            // get handle without loading the library
+            auto libhandle = handleForName(name);
+            // the runtime linker has already loaded all dependencies
+            safeAssert(handle !is null, "Failed to get library handle.");
+            // if it's a D library
+            if (auto pdso = dsoForHandle(handle))
+                deps.insertBack(pdso); // append it to the dependencies
+        }
+    }
+
+    void* handleForName(const char* name)
+    {
+        return GetModuleHandleA(name);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PE/COFF program header iteration
+///////////////////////////////////////////////////////////////////////////////
+
+bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc
+{
+    if (name[] != cast(char[])section.Name[0 .. name.length])
+        return false;
+    return name.length == 8 || section.Name[name.length] == 0;
+}
+
+/************
+ * Scan segments in the image header and store
+ * the writeable data segments in *pdso.
+ */
+
+void scanSegments(in HMODULE handle, DSO* pdso) nothrow @nogc
+{
+    foreach (section; getSectionHeader(handle))
+    {
+        // the ".data" image section includes both object file sections ".data" and ".bss"
+        if (compareSectionName(section, ".data"))
+        {
+            auto data = cast(void*)handle + section.VirtualAddress;
+            pdso._gcRanges.insertBack(data[0 .. section.Misc.VirtualSize]);
+            continue;
+        }
+
+        version (Shared)
+        {
+            if (compareSectionName(section, ".text"))
+            {
+                auto text = cast(void*)handle + section.VirtualAddress;
+                pdso._codeSegments.insertBack(text[0 .. section.Misc.VirtualSize]);
+                continue;
+            }
+        }
+    }
+}
+
+/**************************
+ * Input:
+ *      handle  where the output is to be written
+ * Returns:
+ *      true if found, and *handle is filled in
+ */
+
+bool findModuleHandleForAddr(in void* addr, out HMODULE handle) nothrow @nogc
+{
+    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+                           cast(const(wchar)*) addr, &handle))
+        return true;
+
+    return false;
+}
+
+/**
+ * Returns the image NT header for the HMODULE handle passed,
+ * or null if not found.
+ */
+PIMAGE_NT_HEADERS getNTHeader(in HMODULE handle) nothrow @nogc
+{
+    auto doshdr = cast(PIMAGE_DOS_HEADER)handle;
+    if (doshdr.e_magic != IMAGE_DOS_SIGNATURE)
+        return null;
+
+    return cast(typeof(return))(cast(void*)doshdr + doshdr.e_lfanew);
+}
+
+/**
+ * Returns the image section header for the HMODULE handle passed,
+ * or null if not found.
+ */
+IMAGE_SECTION_HEADER[] getSectionHeader(in HMODULE handle) nothrow @nogc
+{
+    if (auto nthdr = getNTHeader(handle))
+    {
+        const void* opthdr = &nthdr.OptionalHeader;
+        const offset = nthdr.FileHeader.SizeOfOptionalHeader;
+        const length = nthdr.FileHeader.NumberOfSections;
+        return (cast(PIMAGE_SECTION_HEADER)(opthdr + offset))[0 .. length];
+    }
+    return null;
+}
diff --git a/libphobos/libdruntime/gcc/sections/win32.d b/libphobos/libdruntime/gcc/sections/win32.d
deleted file mode 100644
index b355dfc5068..00000000000
--- a/libphobos/libdruntime/gcc/sections/win32.d
+++ /dev/null
@@ -1,183 +0,0 @@
-// Win32-specific support for sections.
-// Copyright (C) 2019-2021 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.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-module gcc.sections.win32;
-
-version (CRuntime_DigitalMars):
-
-// debug = PRINTF;
-debug(PRINTF) import core.stdc.stdio;
-import rt.minfo;
-import core.stdc.stdlib : malloc, free;
-
-struct SectionGroup
-{
-    static int opApply(scope int delegate(ref SectionGroup) dg)
-    {
-        return dg(_sections);
-    }
-
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
-    {
-        return dg(_sections);
-    }
-
-    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-    ModuleGroup _moduleGroup;
-    void[][] _gcRanges;
-}
-
-shared(bool) conservative;
-
-void initSections() nothrow @nogc
-{
-    _sections._moduleGroup = ModuleGroup(getModuleInfos());
-
-    import rt.sections;
-    conservative = !scanDataSegPrecisely();
-
-    if (conservative)
-    {
-        _sections._gcRanges = (cast(void[]*) malloc(2 * (void[]).sizeof))[0..2];
-
-        auto databeg = cast(void*)&_xi_a;
-        auto dataend = cast(void*)_moduleinfo_array.ptr;
-        _sections._gcRanges[0] = databeg[0 .. dataend - databeg];
-
-        // skip module info and CONST segment
-        auto bssbeg = cast(void*)&_edata;
-        auto bssend = cast(void*)&_end;
-        _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg];
-    }
-    else
-    {
-        size_t count = &_DPend - &_DPbegin;
-        auto ranges = cast(void[]*) malloc(count * (void[]).sizeof);
-        size_t r = 0;
-        void* prev = null;
-        for (size_t i = 0; i < count; i++)
-        {
-            void* addr = (&_DPbegin)[i];
-            if (prev + (void*).sizeof == addr)
-                ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof];
-            else
-                ranges[r++] = (cast(void**)addr)[0..1];
-            prev = addr;
-        }
-        _sections._gcRanges = ranges[0..r];
-    }
-}
-
-void finiSections() nothrow @nogc
-{
-    free(_sections._gcRanges.ptr);
-}
-
-void[] initTLSRanges() nothrow @nogc
-{
-    auto pbeg = cast(void*)&_tlsstart;
-    auto pend = cast(void*)&_tlsend;
-    return pbeg[0 .. pend - pbeg];
-}
-
-void finiTLSRanges(void[] rng) nothrow @nogc
-{
-}
-
-void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    if (conservative)
-    {
-        dg(rng.ptr, rng.ptr + rng.length);
-    }
-    else
-    {
-        for (auto p = &_TPbegin; p < &_TPend; )
-        {
-            uint beg = *p++;
-            uint end = beg + cast(uint)((void*).sizeof);
-            while (p < &_TPend && *p == end)
-            {
-                end += (void*).sizeof;
-                p++;
-            }
-            dg(rng.ptr + beg, rng.ptr + end);
-        }
-    }
-}
-
-private:
-
-__gshared SectionGroup _sections;
-
-// Windows: this gets initialized by minit.asm
-extern(C) __gshared immutable(ModuleInfo*)[] _moduleinfo_array;
-extern(C) void _minit() nothrow @nogc;
-
-immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc
-out (result)
-{
-    foreach (m; result)
-        assert(m !is null);
-}
-body
-{
-    // _minit directly alters the global _moduleinfo_array
-    _minit();
-    return _moduleinfo_array;
-}
-
-extern(C)
-{
-    extern __gshared
-    {
-        int _xi_a;      // &_xi_a just happens to be start of data segment
-        int _edata;     // &_edata is start of BSS segment
-        int _end;       // &_end is past end of BSS
-
-        void* _DPbegin; // first entry in the array of pointers addresses
-        void* _DPend;   // &_DPend points after last entry of array
-        uint _TPbegin;  // first entry in the array of TLS offsets of pointers
-        uint _TPend;    // &_DPend points after last entry of array
-    }
-
-    extern
-    {
-        int _tlsstart;
-        int _tlsend;
-    }
-}
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         return _moduleGroup;
     }
 
-    version (Win64)
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        auto pbeg = cast(immutable(FuncTable)*)&_deh_beg;
-        auto pend = cast(immutable(FuncTable)*)&_deh_end;
-        return pbeg[0 .. pend - pbeg];
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
diff --git a/libphobos/libdruntime/gcc/unwind/generic.d b/libphobos/libdruntime/gcc/unwind/generic.d
index 5315739f82f..592b3afcb71 100644
--- a/libphobos/libdruntime/gcc/unwind/generic.d
+++ b/libphobos/libdruntime/gcc/unwind/generic.d
@@ -269,6 +269,6 @@ version (GNU_SEH_Exceptions)
         ExceptionCollidedUnwind
     }
 
-    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*,
+    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, void*,
                                                           _Unwind_Personality_Fn);
 }
diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d
index 3d5ba299863..e4a2c6571d4 100644
--- a/libphobos/libdruntime/rt/dmain2.d
+++ b/libphobos/libdruntime/rt/dmain2.d
@@ -70,70 +70,6 @@ version (CRuntime_Microsoft)
     extern(C) void init_msvc();
 }
 
-/***********************************
- * These are a temporary means of providing a GC hook for DLL use.  They may be
- * replaced with some other similar functionality later.
- */
-extern (C)
-{
-    void* gc_getProxy();
-    void  gc_setProxy(void* p);
-    void  gc_clrProxy();
-
-    alias void* function()      gcGetFn;
-    alias void  function(void*) gcSetFn;
-    alias void  function()      gcClrFn;
-}
-
-version (Windows)
-{
-    /*******************************************
-     * Loads a DLL written in D with the name 'name'.
-     * Returns:
-     *      opaque handle to the DLL if successfully loaded
-     *      null if failure
-     */
-    extern (C) void* rt_loadLibrary(const char* name)
-    {
-        return initLibrary(.LoadLibraryA(name));
-    }
-
-    extern (C) void* rt_loadLibraryW(const wchar_t* name)
-    {
-        return initLibrary(.LoadLibraryW(name));
-    }
-
-    void* initLibrary(void* mod)
-    {
-        // BUG: LoadLibrary() call calls rt_init(), which fails if proxy is not set!
-        // (What? LoadLibrary() is a Windows API call, it shouldn't call rt_init().)
-        if (mod is null)
-            return mod;
-        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(mod, "gc_setProxy");
-        if (gcSet !is null)
-        {   // BUG: Set proxy, but too late
-            gcSet(gc_getProxy());
-        }
-        return mod;
-    }
-
-    /*************************************
-     * Unloads DLL that was previously loaded by rt_loadLibrary().
-     * Input:
-     *      ptr     the handle returned by rt_loadLibrary()
-     * Returns:
-     *      1   succeeded
-     *      0   some failure happened
-     */
-    extern (C) int rt_unloadLibrary(void* ptr)
-    {
-        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
-        if (gcClr !is null)
-            gcClr();
-        return FreeLibrary(ptr) != 0;
-    }
-}
-
 /* To get out-of-band access to the args[] passed to main().
  */
 
diff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am
index 2de8ab951b4..0dc2a2625a9 100644
--- a/libphobos/src/Makefile.am
+++ b/libphobos/src/Makefile.am
@@ -24,7 +24,7 @@ D_EXTRA_DFLAGS=-nostdinc -I $(srcdir) \
 
 # D flags for compilation
 AM_DFLAGS= \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 # Flags for other kinds of sources
diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in
index 2e721783d06..33453517153 100644
--- a/libphobos/src/Makefile.in
+++ b/libphobos/src/Makefile.in
@@ -414,6 +414,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -443,6 +445,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
@@ -477,7 +480,7 @@ D_EXTRA_DFLAGS = -nostdinc -I $(srcdir) \
 
 # D flags for compilation
 AM_DFLAGS = \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 
diff --git a/libphobos/testsuite/Makefile.in b/libphobos/testsuite/Makefile.in
index c38a4688258..51eb4efc79d 100644
--- a/libphobos/testsuite/Makefile.in
+++ b/libphobos/testsuite/Makefile.in
@@ -242,6 +242,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -271,6 +273,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [gcc(refs/users/ibuclaw/heads/mingw)] More MSVC support
@ 2021-04-10 15:22 Iain Buclaw
  0 siblings, 0 replies; 5+ messages in thread
From: Iain Buclaw @ 2021-04-10 15:22 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:df32ce552c241bd63ef401bafedc31f10fff06c8

commit df32ce552c241bd63ef401bafedc31f10fff06c8
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Wed Mar 24 16:24:04 2021 +0100

    More MSVC support

Diff:
---
 gcc/config/i386/cygming.h                          |  2 +
 gcc/config/i386/i386-d.c                           | 11 ++++
 gcc/config/i386/i386-protos.h                      |  1 +
 gcc/config/i386/i386.h                             |  3 +-
 gcc/config/i386/winnt-d.c                          |  5 ++
 gcc/d/d-target.cc                                  |  5 +-
 gcc/d/d-target.def                                 | 10 ++++
 gcc/doc/tm.texi                                    |  7 +++
 gcc/doc/tm.texi.in                                 |  2 +
 libphobos/libdruntime/Makefile.am                  |  3 +-
 libphobos/libdruntime/Makefile.in                  | 56 ++++++++++++-------
 libphobos/libdruntime/config/mingw/msvc.c          | 54 ++++++++++++++++++
 libphobos/libdruntime/config/mingw/switchcontext.S | 12 ++--
 libphobos/libdruntime/core/stdc/stdlib.d           | 27 +++++----
 libphobos/libdruntime/core/stdc/tgmath.d           | 11 +++-
 libphobos/libdruntime/core/sys/windows/com.d       |  4 +-
 libphobos/libdruntime/core/sys/windows/dbghelp.d   |  2 +-
 libphobos/libdruntime/core/thread/osthread.d       |  4 +-
 libphobos/libdruntime/gcc/deh.d                    |  2 +-
 libphobos/libdruntime/gcc/gthread.d                |  6 +-
 libphobos/libdruntime/gcc/unwind/generic.d         |  2 +-
 libphobos/libdruntime/rt/dmain2.d                  | 64 ----------------------
 22 files changed, 178 insertions(+), 115 deletions(-)

diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index cfbca34f996..59eb812c1cf 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -209,6 +209,8 @@ along with GCC; see the file COPYING3.  If not see
 #define SUBTARGET_OVERRIDE_OPTIONS					\
 do {									\
   flag_pic = TARGET_64BIT ? 1 : 0;                                      \
+  if (!global_options_set.x_dwarf_version)				\
+    dwarf_version = 4;							\
 } while (0)
 
 /* Define this macro if references to a symbol must be treated
diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c
index b79be85e661..34f53ba046d 100644
--- a/gcc/config/i386/i386-d.c
+++ b/gcc/config/i386/i386-d.c
@@ -44,3 +44,14 @@ ix86_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Implement TARGET_D_EXTERN_SYSTEM_LINKAGE for x86 targets.  */
+
+int
+ix86_d_extern_system_linkage (void)
+{
+  if (ix86_abi == MS_ABI)
+    return LINKwindows;
+
+  return LINKc;
+}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 9f8a69ea7dc..d07bf09bc65 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void);
 
 /* In i386-d.c  */
 extern void ix86_d_target_versions (void);
+extern int ix86_d_extern_system_linkage (void);
 
 /* In winnt.c  */
 extern void i386_pe_unique_section (tree, int);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index b4001d21b70..0c24ada8bd5 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -801,8 +801,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 /* Target Pragmas.  */
 #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
 
-/* Target CPU versions for D.  */
+/* Target hooks for D language.  */
 #define TARGET_D_CPU_VERSIONS ix86_d_target_versions
+#define TARGET_D_EXTERN_SYSTEM_LINKAGE ix86_d_extern_system_linkage
 
 #ifndef CC1_SPEC
 #define CC1_SPEC "%(cc1_cpu) "
diff --git a/gcc/config/i386/winnt-d.c b/gcc/config/i386/winnt-d.c
index 8a6b9c57d8d..d05ea8a92bf 100644
--- a/gcc/config/i386/winnt-d.c
+++ b/gcc/config/i386/winnt-d.c
@@ -32,6 +32,11 @@ winnt_d_os_builtins (void)
 {
   d_add_builtin_version ("Windows");
 
+  if (ix86_abi == SYSV_ABI)
+    d_add_builtin_version ("SYSV_ABI");
+  else
+    d_add_builtin_version ("MS_ABI");
+
 #define builtin_version(TXT) d_add_builtin_version (TXT)
 
 #ifdef EXTRA_TARGET_D_OS_VERSIONS
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index a1dc2ee286f..4e37c998934 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -435,11 +435,14 @@ TargetCPP::derivedClassOffset(ClassDeclaration *base_class)
   return base_class->structsize;
 }
 
-/* Return the default system linkage for the target.  */
+/* Return the default `extern (System)` linkage for the target.  */
 
 LINK
 Target::systemLinkage (void)
 {
+  if (targetdm.d_extern_system_linkage)
+    return (LINK) targetdm.d_extern_system_linkage ();
+
   return LINKc;
 }
 
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index d1426a17e99..9fb3c7d23d9 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -46,6 +46,16 @@ relating to the target operating system.",
  void, (void),
  hook_void_void)
 
+/* */
+DEFHOOK
+(d_extern_system_linkage,
+ "If defined, this hook returns the extern linkage which should be applied\n\
+ for all declarations annotated with @code{extern (System)}.  Typically,\n\
+ @code{extern (System)} is the same as @code{extern (Windows)} on Microsoft\n\
+ Windows platforms, and @code{extern (C)} on other platforms.",
+ int, (void),
+ NULL)
+
 /* ModuleInfo section name and brackets.  */
 DEFHOOKPOD
 (d_minfo_section,
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b272fa4806d..0265ef0df5c 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10808,6 +10808,13 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions
 relating to the target operating system.
 @end deftypefn
 
+@deftypefn {D Target Hook} int TARGET_D_EXTERN_SYSTEM_LINKAGE (void)
+If defined, this hook returns the extern linkage which should be applied
+ for all declarations annotated with @code{extern (System)}.  Typically,
+ @code{extern (System)} is the same as @code{extern (Windows)} on Microsoft
+ Windows platforms, and @code{extern (C)} on other platforms.
+@end deftypefn
+
 @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION
 Contains the name of the section in which module info references should be
 placed.  This section is expected to be bracketed by two symbols to indicate
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index bf724dc093c..ef15417a791 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7357,6 +7357,8 @@ floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_OS_VERSIONS
 
+@hook TARGET_D_EXTERN_SYSTEM_LINKAGE
+
 @hook TARGET_D_MINFO_SECTION
 
 @hook TARGET_D_MINFO_START_NAME
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 02a68b10424..fdac627364d 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -69,7 +69,8 @@ if DRUNTIME_OS_LINUX
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_LINUX)
 endif
 if DRUNTIME_OS_MINGW
-    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS)
+    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS) \
+				   config/mingw/msvc.c
 endif
 if DRUNTIME_OS_SOLARIS
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_SOLARIS)
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 853a7fc1981..1ff2ac665ee 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -117,7 +117,9 @@ target_triplet = @target@
 @DRUNTIME_OS_NETBSD_TRUE@am__append_6 = $(DRUNTIME_DSOURCES_NETBSD)
 @DRUNTIME_OS_OPENBSD_TRUE@am__append_7 = $(DRUNTIME_DSOURCES_OPENBSD)
 @DRUNTIME_OS_LINUX_TRUE@am__append_8 = $(DRUNTIME_DSOURCES_LINUX)
-@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS)
+@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS) \
+@DRUNTIME_OS_MINGW_TRUE@				   config/mingw/msvc.c
+
 @DRUNTIME_OS_SOLARIS_TRUE@am__append_10 = $(DRUNTIME_DSOURCES_SOLARIS)
 # CPU specific sources
 @DRUNTIME_CPU_AARCH64_TRUE@am__append_11 = config/aarch64/switchcontext.S
@@ -428,7 +430,8 @@ am__objects_19 = core/sys/windows/accctrl.lo \
 	core/sys/windows/winsvc.lo core/sys/windows/winuser.lo \
 	core/sys/windows/winver.lo core/sys/windows/wtsapi32.lo \
 	core/sys/windows/wtypes.lo
-@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19)
+@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_la-msvc.lo
 am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
 	core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \
 	core/sys/solaris/libelf.lo core/sys/solaris/link.lo \
@@ -463,24 +466,26 @@ am_libgdruntime_la_OBJECTS = $(am__objects_33)
 libgdruntime_la_OBJECTS = $(am_libgdruntime_la_OBJECTS)
 am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_34 = core/stdc/libgdruntime_convenience_la-errno_.lo
-@DRUNTIME_CPU_AARCH64_TRUE@am__objects_35 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_ARM_TRUE@am__objects_36 = config/arm/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_MIPS_TRUE@am__objects_37 = config/mips/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_POWERPC_TRUE@am__objects_38 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_39 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_40 = config/x86/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_41 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
-@DRUNTIME_CPU_S390_TRUE@am__objects_42 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
-am__objects_43 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
+@DRUNTIME_OS_MINGW_TRUE@am__objects_35 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_convenience_la-msvc.lo
+@DRUNTIME_CPU_AARCH64_TRUE@am__objects_36 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_ARM_TRUE@am__objects_37 = config/arm/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_MIPS_TRUE@am__objects_38 = config/mips/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_POWERPC_TRUE@am__objects_39 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_40 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_41 = config/x86/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_42 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
+@DRUNTIME_CPU_S390_TRUE@am__objects_43 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
+am__objects_44 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
 	$(am__objects_10) $(am__objects_12) $(am__objects_14) \
-	$(am__objects_16) $(am__objects_18) $(am__objects_20) \
-	$(am__objects_22) $(am__objects_35) $(am__objects_36) \
-	$(am__objects_37) $(am__objects_38) $(am__objects_39) \
-	$(am__objects_40) $(am__objects_41) $(am__objects_42)
-am__objects_44 = $(am__objects_1) $(am__objects_34) $(am__objects_43) \
+	$(am__objects_16) $(am__objects_18) $(am__objects_35) \
+	$(am__objects_22) $(am__objects_36) $(am__objects_37) \
+	$(am__objects_38) $(am__objects_39) $(am__objects_40) \
+	$(am__objects_41) $(am__objects_42) $(am__objects_43)
+am__objects_45 = $(am__objects_1) $(am__objects_34) $(am__objects_44) \
 	$(am__objects_32)
-am__objects_45 = $(am__objects_44)
-am_libgdruntime_convenience_la_OBJECTS = $(am__objects_45)
+am__objects_46 = $(am__objects_45)
+am_libgdruntime_convenience_la_OBJECTS = $(am__objects_46)
 libgdruntime_convenience_la_OBJECTS =  \
 	$(am_libgdruntime_convenience_la_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
@@ -1732,6 +1737,10 @@ core/sys/windows/winuser.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/winver.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtsapi32.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtypes.lo: core/sys/windows/$(am__dirstamp)
+config/mingw/$(am__dirstamp):
+	@$(MKDIR_P) config/mingw
+	@: > config/mingw/$(am__dirstamp)
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/$(am__dirstamp)
 core/sys/solaris/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/solaris
 	@: > core/sys/solaris/$(am__dirstamp)
@@ -1781,9 +1790,6 @@ config/powerpc/$(am__dirstamp):
 	@: > config/powerpc/$(am__dirstamp)
 config/powerpc/libgdruntime_la-switchcontext.lo:  \
 	config/powerpc/$(am__dirstamp)
-config/mingw/$(am__dirstamp):
-	@$(MKDIR_P) config/mingw
-	@: > config/mingw/$(am__dirstamp)
 config/mingw/libgdruntime_la-switchcontext.lo:  \
 	config/mingw/$(am__dirstamp)
 config/x86/$(am__dirstamp):
@@ -1808,6 +1814,8 @@ libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EX
 	$(AM_V_GEN)$(libgdruntime_la_LINK) -rpath $(toolexeclibdir) $(libgdruntime_la_OBJECTS) $(libgdruntime_la_LIBADD) $(LIBS)
 core/stdc/libgdruntime_convenience_la-errno_.lo:  \
 	core/stdc/$(am__dirstamp)
+config/mingw/libgdruntime_convenience_la-msvc.lo:  \
+	config/mingw/$(am__dirstamp)
 config/aarch64/libgdruntime_convenience_la-switchcontext.lo:  \
 	config/aarch64/$(am__dirstamp)
 config/arm/libgdruntime_convenience_la-switchcontext.lo:  \
@@ -2003,9 +2011,15 @@ config/s390/libgdruntime_convenience_la-get_tls_offset.lo: config/s390/get_tls_o
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 core/stdc/libgdruntime_convenience_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_convenience_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_convenience_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_convenience_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/libphobos/libdruntime/config/mingw/msvc.c b/libphobos/libdruntime/config/mingw/msvc.c
new file mode 100644
index 00000000000..25b15a06950
--- /dev/null
+++ b/libphobos/libdruntime/config/mingw/msvc.c
@@ -0,0 +1,54 @@
+/* Windows support code to wrap differences between different
+   versions of the Microsoft C libaries.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+
+/* The symbols for stdin, stdout, and stderr are defined for D in the
+   core.stdc.stdio module.  Save the macros and redeclare them here.  */
+#define c_stdin stdin
+#undef stdin
+extern FILE *stdin;
+
+#define c_stdout stdout
+#undef stdout
+extern FILE *stdout;
+
+#define c_stderr stderr
+#undef stderr
+extern FILE *stderr;
+
+/* Set to 1 if run-time is using ucrtbase.dll.  */
+unsigned char msvcUsesUCRT;
+
+void init_msvc()
+{
+#if __MSVCRT_VERSION__ >= 0x1400
+  msvcUsedUCRT = 1;
+#endif
+
+  stdin = c_stdin;
+  stdout = c_stdout;
+  stderr = c_stderr;
+}
diff --git a/libphobos/libdruntime/config/mingw/switchcontext.S b/libphobos/libdruntime/config/mingw/switchcontext.S
index 6592ff604bc..0cb8b015bfc 100644
--- a/libphobos/libdruntime/config/mingw/switchcontext.S
+++ b/libphobos/libdruntime/config/mingw/switchcontext.S
@@ -28,7 +28,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -63,13 +66,15 @@ CSYM(fiber_switchContext):
     popq %RCX;
     jmp *%RCX;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #elif defined(_X86_)
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -104,6 +109,5 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #endif
diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d
index 5d69b880bc8..35e81a25414 100644
--- a/libphobos/libdruntime/core/stdc/stdlib.d
+++ b/libphobos/libdruntime/core/stdc/stdlib.d
@@ -121,19 +121,22 @@ ulong   strtoull(scope inout(char)* nptr, scope inout(char)** endptr, int base);
 
 version (CRuntime_Microsoft)
 {
-    // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
-    ///
-    extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
-    {   // Fake it 'till we make it
-        return strtod(nptr, endptr);
+    version (MinGW)
+    {
+        ///
+        real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
+        ///
+        alias __mingw_strtold strtold;
+    }
+    else
+    {
+        // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
+        ///
+        extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
+        {   // Fake it 'till we make it
+            return strtod(nptr, endptr);
+        }
     }
-}
-else version (MinGW)
-{
-    ///
-    real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
-    ///
-    alias __mingw_strtold strtold;
 }
 else
 {
diff --git a/libphobos/libdruntime/core/stdc/tgmath.d b/libphobos/libdruntime/core/stdc/tgmath.d
index 2ff1522fd81..cd80bf7c9b1 100644
--- a/libphobos/libdruntime/core/stdc/tgmath.d
+++ b/libphobos/libdruntime/core/stdc/tgmath.d
@@ -1285,13 +1285,20 @@ else
     alias core.stdc.math.fabs          fabs;
     version (CRuntime_Microsoft)
     {
+        version (MinGW)
+        {
+            ///
+            alias core.stdc.math.fabsf fabs;
+            ///
+            alias core.stdc.math.fabsl fabs;
+        }
     }
     else
     {
         ///
-        alias core.stdc.math.fabsf         fabs;
+        alias core.stdc.math.fabsf     fabs;
         ///
-        alias core.stdc.math.fabsl         fabs;
+        alias core.stdc.math.fabsl     fabs;
     }
 
     // @@@DEPRECATED_2.105@@@
diff --git a/libphobos/libdruntime/core/sys/windows/com.d b/libphobos/libdruntime/core/sys/windows/com.d
index 88007adb141..6935dd94f95 100644
--- a/libphobos/libdruntime/core/sys/windows/com.d
+++ b/libphobos/libdruntime/core/sys/windows/com.d
@@ -57,12 +57,12 @@ alias COINIT_SPEED_OVER_MEMORY   = COINIT.COINIT_SPEED_OVER_MEMORY;
 
 public import core.sys.windows.uuid;
 
-extern (System)
+extern (Windows)
 {
 
 class ComObject : IUnknown
 {
-extern (System):
+extern (Windows):
     HRESULT QueryInterface(const(IID)* riid, void** ppv)
     {
         if (*riid == IID_IUnknown)
diff --git a/libphobos/libdruntime/core/sys/windows/dbghelp.d b/libphobos/libdruntime/core/sys/windows/dbghelp.d
index 8c9827034e9..9848fb99115 100644
--- a/libphobos/libdruntime/core/sys/windows/dbghelp.d
+++ b/libphobos/libdruntime/core/sys/windows/dbghelp.d
@@ -18,7 +18,7 @@ import core.sys.windows.windef;
 
 public import core.sys.windows.dbghelp_types;
 
-extern(System)
+extern(Windows)
 {
     alias BOOL         function(HANDLE hProcess, DWORD64 lpBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) ReadProcessMemoryProc64;
     alias PVOID        function(HANDLE hProcess, DWORD64 AddrBase) FunctionTableAccessProc64;
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index 880836e3a25..5ee909ae793 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -1539,9 +1539,9 @@ package extern(D) void* getStackBottom() nothrow @nogc
             void *bottom;
 
             version (X86)
-                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" (bottom); }
             else version (X86_64)
-                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" (bottom); }
             else
                 static assert(false, "Platform not supported.");
 
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 2e679320c38..5ce4869d096 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -805,7 +805,7 @@ version (GNU_SEH_Exceptions)
                                                            void* ms_orig_context, void* ms_disp)
     {
         return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context,
-                                     ms_disp, &__gdc_personality_imp);
+                                     ms_disp, &gdc_personality);
     }
 }
 else version (GNU_SjLj_Exceptions)
diff --git a/libphobos/libdruntime/gcc/gthread.d b/libphobos/libdruntime/gcc/gthread.d
index ef35a3c27ec..5003637b9ea 100644
--- a/libphobos/libdruntime/gcc/gthread.d
+++ b/libphobos/libdruntime/gcc/gthread.d
@@ -86,10 +86,12 @@ else static if (GNU_Thread_Model == ThreadModel.Single)
 }
 else static if (GNU_Thread_Model == ThreadModel.Win32)
 {
+    import core.stdc.config;
+
     struct __gthread_once_t
     {
-        INT done;
-        LONG started;
+        int done;
+        c_long started;
     }
 
     int __gthr_win32_key_create(__gthread_key_t* keyp, GthreadDestroyFn dtor);
diff --git a/libphobos/libdruntime/gcc/unwind/generic.d b/libphobos/libdruntime/gcc/unwind/generic.d
index 5315739f82f..592b3afcb71 100644
--- a/libphobos/libdruntime/gcc/unwind/generic.d
+++ b/libphobos/libdruntime/gcc/unwind/generic.d
@@ -269,6 +269,6 @@ version (GNU_SEH_Exceptions)
         ExceptionCollidedUnwind
     }
 
-    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*,
+    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, void*,
                                                           _Unwind_Personality_Fn);
 }
diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d
index 3d5ba299863..e4a2c6571d4 100644
--- a/libphobos/libdruntime/rt/dmain2.d
+++ b/libphobos/libdruntime/rt/dmain2.d
@@ -70,70 +70,6 @@ version (CRuntime_Microsoft)
     extern(C) void init_msvc();
 }
 
-/***********************************
- * These are a temporary means of providing a GC hook for DLL use.  They may be
- * replaced with some other similar functionality later.
- */
-extern (C)
-{
-    void* gc_getProxy();
-    void  gc_setProxy(void* p);
-    void  gc_clrProxy();
-
-    alias void* function()      gcGetFn;
-    alias void  function(void*) gcSetFn;
-    alias void  function()      gcClrFn;
-}
-
-version (Windows)
-{
-    /*******************************************
-     * Loads a DLL written in D with the name 'name'.
-     * Returns:
-     *      opaque handle to the DLL if successfully loaded
-     *      null if failure
-     */
-    extern (C) void* rt_loadLibrary(const char* name)
-    {
-        return initLibrary(.LoadLibraryA(name));
-    }
-
-    extern (C) void* rt_loadLibraryW(const wchar_t* name)
-    {
-        return initLibrary(.LoadLibraryW(name));
-    }
-
-    void* initLibrary(void* mod)
-    {
-        // BUG: LoadLibrary() call calls rt_init(), which fails if proxy is not set!
-        // (What? LoadLibrary() is a Windows API call, it shouldn't call rt_init().)
-        if (mod is null)
-            return mod;
-        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(mod, "gc_setProxy");
-        if (gcSet !is null)
-        {   // BUG: Set proxy, but too late
-            gcSet(gc_getProxy());
-        }
-        return mod;
-    }
-
-    /*************************************
-     * Unloads DLL that was previously loaded by rt_loadLibrary().
-     * Input:
-     *      ptr     the handle returned by rt_loadLibrary()
-     * Returns:
-     *      1   succeeded
-     *      0   some failure happened
-     */
-    extern (C) int rt_unloadLibrary(void* ptr)
-    {
-        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
-        if (gcClr !is null)
-            gcClr();
-        return FreeLibrary(ptr) != 0;
-    }
-}
-
 /* To get out-of-band access to the args[] passed to main().
  */


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [gcc(refs/users/ibuclaw/heads/mingw)] More MSVC support
@ 2021-04-08 13:35 Iain Buclaw
  0 siblings, 0 replies; 5+ messages in thread
From: Iain Buclaw @ 2021-04-08 13:35 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:e280567b330fca770add9808c9ea2cf766c55bd9

commit e280567b330fca770add9808c9ea2cf766c55bd9
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Wed Mar 24 16:24:04 2021 +0100

    More MSVC support

Diff:
---
 gcc/config/i386/cygming.h                          |   2 +
 gcc/config/i386/i386-d.c                           |  11 +
 gcc/config/i386/i386-protos.h                      |   1 +
 gcc/config/i386/i386.h                             |   3 +-
 gcc/config/i386/winnt-d.c                          |   5 +
 gcc/d/d-target.cc                                  |   5 +-
 gcc/d/d-target.def                                 |  10 +
 gcc/doc/tm.texi                                    |   7 +
 gcc/doc/tm.texi.in                                 |   2 +
 libphobos/libdruntime/Makefile.am                  |   5 +-
 libphobos/libdruntime/Makefile.in                  |  62 +-
 libphobos/libdruntime/config/mingw/msvc.c          |  54 ++
 libphobos/libdruntime/config/mingw/switchcontext.S |  12 +-
 libphobos/libdruntime/core/stdc/stdlib.d           |  27 +-
 libphobos/libdruntime/core/stdc/tgmath.d           |  11 +-
 libphobos/libdruntime/core/sys/windows/com.d       |   4 +-
 libphobos/libdruntime/core/sys/windows/dbghelp.d   |   2 +-
 libphobos/libdruntime/core/thread/osthread.d       |   4 +-
 libphobos/libdruntime/gcc/deh.d                    |   2 +-
 libphobos/libdruntime/gcc/gthread.d                |   6 +-
 libphobos/libdruntime/gcc/sections/package.d       |  28 +-
 libphobos/libdruntime/gcc/sections/pecoff.d        | 830 +++++++++++++++++++++
 libphobos/libdruntime/gcc/sections/win32.d         | 183 -----
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/libdruntime/gcc/unwind/generic.d         |   2 +-
 libphobos/libdruntime/rt/dmain2.d                  |  64 --
 26 files changed, 1023 insertions(+), 327 deletions(-)

diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index cfbca34f996..59eb812c1cf 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -209,6 +209,8 @@ along with GCC; see the file COPYING3.  If not see
 #define SUBTARGET_OVERRIDE_OPTIONS					\
 do {									\
   flag_pic = TARGET_64BIT ? 1 : 0;                                      \
+  if (!global_options_set.x_dwarf_version)				\
+    dwarf_version = 4;							\
 } while (0)
 
 /* Define this macro if references to a symbol must be treated
diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c
index b79be85e661..34f53ba046d 100644
--- a/gcc/config/i386/i386-d.c
+++ b/gcc/config/i386/i386-d.c
@@ -44,3 +44,14 @@ ix86_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Implement TARGET_D_EXTERN_SYSTEM_LINKAGE for x86 targets.  */
+
+int
+ix86_d_extern_system_linkage (void)
+{
+  if (ix86_abi == MS_ABI)
+    return LINKwindows;
+
+  return LINKc;
+}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 9f8a69ea7dc..d07bf09bc65 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void);
 
 /* In i386-d.c  */
 extern void ix86_d_target_versions (void);
+extern int ix86_d_extern_system_linkage (void);
 
 /* In winnt.c  */
 extern void i386_pe_unique_section (tree, int);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index b4001d21b70..0c24ada8bd5 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -801,8 +801,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 /* Target Pragmas.  */
 #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
 
-/* Target CPU versions for D.  */
+/* Target hooks for D language.  */
 #define TARGET_D_CPU_VERSIONS ix86_d_target_versions
+#define TARGET_D_EXTERN_SYSTEM_LINKAGE ix86_d_extern_system_linkage
 
 #ifndef CC1_SPEC
 #define CC1_SPEC "%(cc1_cpu) "
diff --git a/gcc/config/i386/winnt-d.c b/gcc/config/i386/winnt-d.c
index 8a6b9c57d8d..d05ea8a92bf 100644
--- a/gcc/config/i386/winnt-d.c
+++ b/gcc/config/i386/winnt-d.c
@@ -32,6 +32,11 @@ winnt_d_os_builtins (void)
 {
   d_add_builtin_version ("Windows");
 
+  if (ix86_abi == SYSV_ABI)
+    d_add_builtin_version ("SYSV_ABI");
+  else
+    d_add_builtin_version ("MS_ABI");
+
 #define builtin_version(TXT) d_add_builtin_version (TXT)
 
 #ifdef EXTRA_TARGET_D_OS_VERSIONS
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index a1dc2ee286f..4e37c998934 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -435,11 +435,14 @@ TargetCPP::derivedClassOffset(ClassDeclaration *base_class)
   return base_class->structsize;
 }
 
-/* Return the default system linkage for the target.  */
+/* Return the default `extern (System)` linkage for the target.  */
 
 LINK
 Target::systemLinkage (void)
 {
+  if (targetdm.d_extern_system_linkage)
+    return (LINK) targetdm.d_extern_system_linkage ();
+
   return LINKc;
 }
 
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index d1426a17e99..9fb3c7d23d9 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -46,6 +46,16 @@ relating to the target operating system.",
  void, (void),
  hook_void_void)
 
+/* */
+DEFHOOK
+(d_extern_system_linkage,
+ "If defined, this hook returns the extern linkage which should be applied\n\
+ for all declarations annotated with @code{extern (System)}.  Typically,\n\
+ @code{extern (System)} is the same as @code{extern (Windows)} on Microsoft\n\
+ Windows platforms, and @code{extern (C)} on other platforms.",
+ int, (void),
+ NULL)
+
 /* ModuleInfo section name and brackets.  */
 DEFHOOKPOD
 (d_minfo_section,
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b272fa4806d..0265ef0df5c 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10808,6 +10808,13 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions
 relating to the target operating system.
 @end deftypefn
 
+@deftypefn {D Target Hook} int TARGET_D_EXTERN_SYSTEM_LINKAGE (void)
+If defined, this hook returns the extern linkage which should be applied
+ for all declarations annotated with @code{extern (System)}.  Typically,
+ @code{extern (System)} is the same as @code{extern (Windows)} on Microsoft
+ Windows platforms, and @code{extern (C)} on other platforms.
+@end deftypefn
+
 @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION
 Contains the name of the section in which module info references should be
 placed.  This section is expected to be bracketed by two symbols to indicate
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index bf724dc093c..ef15417a791 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7357,6 +7357,8 @@ floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_OS_VERSIONS
 
+@hook TARGET_D_EXTERN_SYSTEM_LINKAGE
+
 @hook TARGET_D_MINFO_SECTION
 
 @hook TARGET_D_MINFO_START_NAME
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 5137f85b571..385ab7a497a 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -69,7 +69,8 @@ if DRUNTIME_OS_LINUX
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_LINUX)
 endif
 if DRUNTIME_OS_MINGW
-    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS)
+    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS) \
+				   config/mingw/msvc.c
 endif
 if DRUNTIME_OS_SOLARIS
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_SOLARIS)
@@ -187,7 +188,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/attributes.d \
 	gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
 	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \
+	gcc/sections/package.d gcc/sections/pecoff.d gcc/sections/win64.d \
 	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 4a93b4921a4..70d9e0cbfc2 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -117,7 +117,9 @@ target_triplet = @target@
 @DRUNTIME_OS_NETBSD_TRUE@am__append_6 = $(DRUNTIME_DSOURCES_NETBSD)
 @DRUNTIME_OS_OPENBSD_TRUE@am__append_7 = $(DRUNTIME_DSOURCES_OPENBSD)
 @DRUNTIME_OS_LINUX_TRUE@am__append_8 = $(DRUNTIME_DSOURCES_LINUX)
-@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS)
+@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS) \
+@DRUNTIME_OS_MINGW_TRUE@				   config/mingw/msvc.c
+
 @DRUNTIME_OS_SOLARIS_TRUE@am__append_10 = $(DRUNTIME_DSOURCES_SOLARIS)
 # CPU specific sources
 @DRUNTIME_CPU_AARCH64_TRUE@am__append_11 = config/aarch64/switchcontext.S
@@ -213,7 +215,7 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo gcc/emutls.lo \
 	gcc/gthread.lo gcc/sections/android.lo \
 	gcc/sections/elf_shared.lo gcc/sections/osx.lo \
-	gcc/sections/package.lo gcc/sections/win32.lo \
+	gcc/sections/package.lo gcc/sections/pecoff.lo \
 	gcc/sections/win64.lo gcc/unwind/arm.lo \
 	gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
 	gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
@@ -429,7 +431,8 @@ am__objects_19 = core/sys/windows/accctrl.lo \
 	core/sys/windows/winsvc.lo core/sys/windows/winuser.lo \
 	core/sys/windows/winver.lo core/sys/windows/wtsapi32.lo \
 	core/sys/windows/wtypes.lo
-@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19)
+@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_la-msvc.lo
 am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
 	core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \
 	core/sys/solaris/libelf.lo core/sys/solaris/link.lo \
@@ -464,24 +467,26 @@ am_libgdruntime_la_OBJECTS = $(am__objects_33)
 libgdruntime_la_OBJECTS = $(am_libgdruntime_la_OBJECTS)
 am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_34 = core/stdc/libgdruntime_convenience_la-errno_.lo
-@DRUNTIME_CPU_AARCH64_TRUE@am__objects_35 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_ARM_TRUE@am__objects_36 = config/arm/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_MIPS_TRUE@am__objects_37 = config/mips/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_POWERPC_TRUE@am__objects_38 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_39 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_40 = config/x86/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_41 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
-@DRUNTIME_CPU_S390_TRUE@am__objects_42 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
-am__objects_43 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
+@DRUNTIME_OS_MINGW_TRUE@am__objects_35 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_convenience_la-msvc.lo
+@DRUNTIME_CPU_AARCH64_TRUE@am__objects_36 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_ARM_TRUE@am__objects_37 = config/arm/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_MIPS_TRUE@am__objects_38 = config/mips/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_POWERPC_TRUE@am__objects_39 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_40 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_41 = config/x86/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_42 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
+@DRUNTIME_CPU_S390_TRUE@am__objects_43 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
+am__objects_44 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
 	$(am__objects_10) $(am__objects_12) $(am__objects_14) \
-	$(am__objects_16) $(am__objects_18) $(am__objects_20) \
-	$(am__objects_22) $(am__objects_35) $(am__objects_36) \
-	$(am__objects_37) $(am__objects_38) $(am__objects_39) \
-	$(am__objects_40) $(am__objects_41) $(am__objects_42)
-am__objects_44 = $(am__objects_1) $(am__objects_34) $(am__objects_43) \
+	$(am__objects_16) $(am__objects_18) $(am__objects_35) \
+	$(am__objects_22) $(am__objects_36) $(am__objects_37) \
+	$(am__objects_38) $(am__objects_39) $(am__objects_40) \
+	$(am__objects_41) $(am__objects_42) $(am__objects_43)
+am__objects_45 = $(am__objects_1) $(am__objects_34) $(am__objects_44) \
 	$(am__objects_32)
-am__objects_45 = $(am__objects_44)
-am_libgdruntime_convenience_la_OBJECTS = $(am__objects_45)
+am__objects_46 = $(am__objects_45)
+am_libgdruntime_convenience_la_OBJECTS = $(am__objects_46)
 libgdruntime_convenience_la_OBJECTS =  \
 	$(am_libgdruntime_convenience_la_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
@@ -820,7 +825,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/attributes.d \
 	gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
 	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \
+	gcc/sections/package.d gcc/sections/pecoff.d gcc/sections/win64.d \
 	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
@@ -1223,7 +1228,7 @@ gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/elf_shared.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/osx.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/package.lo: gcc/sections/$(am__dirstamp)
-gcc/sections/win32.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/pecoff.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/win64.lo: gcc/sections/$(am__dirstamp)
 gcc/unwind/$(am__dirstamp):
 	@$(MKDIR_P) gcc/unwind
@@ -1734,6 +1739,10 @@ core/sys/windows/winuser.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/winver.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtsapi32.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtypes.lo: core/sys/windows/$(am__dirstamp)
+config/mingw/$(am__dirstamp):
+	@$(MKDIR_P) config/mingw
+	@: > config/mingw/$(am__dirstamp)
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/$(am__dirstamp)
 core/sys/solaris/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/solaris
 	@: > core/sys/solaris/$(am__dirstamp)
@@ -1783,9 +1792,6 @@ config/powerpc/$(am__dirstamp):
 	@: > config/powerpc/$(am__dirstamp)
 config/powerpc/libgdruntime_la-switchcontext.lo:  \
 	config/powerpc/$(am__dirstamp)
-config/mingw/$(am__dirstamp):
-	@$(MKDIR_P) config/mingw
-	@: > config/mingw/$(am__dirstamp)
 config/mingw/libgdruntime_la-switchcontext.lo:  \
 	config/mingw/$(am__dirstamp)
 config/x86/$(am__dirstamp):
@@ -1810,6 +1816,8 @@ libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EX
 	$(AM_V_GEN)$(libgdruntime_la_LINK) -rpath $(toolexeclibdir) $(libgdruntime_la_OBJECTS) $(libgdruntime_la_LIBADD) $(LIBS)
 core/stdc/libgdruntime_convenience_la-errno_.lo:  \
 	core/stdc/$(am__dirstamp)
+config/mingw/libgdruntime_convenience_la-msvc.lo:  \
+	config/mingw/$(am__dirstamp)
 config/aarch64/libgdruntime_convenience_la-switchcontext.lo:  \
 	config/aarch64/$(am__dirstamp)
 config/arm/libgdruntime_convenience_la-switchcontext.lo:  \
@@ -2005,9 +2013,15 @@ config/s390/libgdruntime_convenience_la-get_tls_offset.lo: config/s390/get_tls_o
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 core/stdc/libgdruntime_convenience_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_convenience_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_convenience_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_convenience_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/libphobos/libdruntime/config/mingw/msvc.c b/libphobos/libdruntime/config/mingw/msvc.c
new file mode 100644
index 00000000000..25b15a06950
--- /dev/null
+++ b/libphobos/libdruntime/config/mingw/msvc.c
@@ -0,0 +1,54 @@
+/* Windows support code to wrap differences between different
+   versions of the Microsoft C libaries.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+
+/* The symbols for stdin, stdout, and stderr are defined for D in the
+   core.stdc.stdio module.  Save the macros and redeclare them here.  */
+#define c_stdin stdin
+#undef stdin
+extern FILE *stdin;
+
+#define c_stdout stdout
+#undef stdout
+extern FILE *stdout;
+
+#define c_stderr stderr
+#undef stderr
+extern FILE *stderr;
+
+/* Set to 1 if run-time is using ucrtbase.dll.  */
+unsigned char msvcUsesUCRT;
+
+void init_msvc()
+{
+#if __MSVCRT_VERSION__ >= 0x1400
+  msvcUsedUCRT = 1;
+#endif
+
+  stdin = c_stdin;
+  stdout = c_stdout;
+  stderr = c_stderr;
+}
diff --git a/libphobos/libdruntime/config/mingw/switchcontext.S b/libphobos/libdruntime/config/mingw/switchcontext.S
index 6592ff604bc..0cb8b015bfc 100644
--- a/libphobos/libdruntime/config/mingw/switchcontext.S
+++ b/libphobos/libdruntime/config/mingw/switchcontext.S
@@ -28,7 +28,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -63,13 +66,15 @@ CSYM(fiber_switchContext):
     popq %RCX;
     jmp *%RCX;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #elif defined(_X86_)
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -104,6 +109,5 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #endif
diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d
index 5d69b880bc8..35e81a25414 100644
--- a/libphobos/libdruntime/core/stdc/stdlib.d
+++ b/libphobos/libdruntime/core/stdc/stdlib.d
@@ -121,19 +121,22 @@ ulong   strtoull(scope inout(char)* nptr, scope inout(char)** endptr, int base);
 
 version (CRuntime_Microsoft)
 {
-    // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
-    ///
-    extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
-    {   // Fake it 'till we make it
-        return strtod(nptr, endptr);
+    version (MinGW)
+    {
+        ///
+        real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
+        ///
+        alias __mingw_strtold strtold;
+    }
+    else
+    {
+        // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
+        ///
+        extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
+        {   // Fake it 'till we make it
+            return strtod(nptr, endptr);
+        }
     }
-}
-else version (MinGW)
-{
-    ///
-    real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
-    ///
-    alias __mingw_strtold strtold;
 }
 else
 {
diff --git a/libphobos/libdruntime/core/stdc/tgmath.d b/libphobos/libdruntime/core/stdc/tgmath.d
index 2ff1522fd81..cd80bf7c9b1 100644
--- a/libphobos/libdruntime/core/stdc/tgmath.d
+++ b/libphobos/libdruntime/core/stdc/tgmath.d
@@ -1285,13 +1285,20 @@ else
     alias core.stdc.math.fabs          fabs;
     version (CRuntime_Microsoft)
     {
+        version (MinGW)
+        {
+            ///
+            alias core.stdc.math.fabsf fabs;
+            ///
+            alias core.stdc.math.fabsl fabs;
+        }
     }
     else
     {
         ///
-        alias core.stdc.math.fabsf         fabs;
+        alias core.stdc.math.fabsf     fabs;
         ///
-        alias core.stdc.math.fabsl         fabs;
+        alias core.stdc.math.fabsl     fabs;
     }
 
     // @@@DEPRECATED_2.105@@@
diff --git a/libphobos/libdruntime/core/sys/windows/com.d b/libphobos/libdruntime/core/sys/windows/com.d
index 88007adb141..6935dd94f95 100644
--- a/libphobos/libdruntime/core/sys/windows/com.d
+++ b/libphobos/libdruntime/core/sys/windows/com.d
@@ -57,12 +57,12 @@ alias COINIT_SPEED_OVER_MEMORY   = COINIT.COINIT_SPEED_OVER_MEMORY;
 
 public import core.sys.windows.uuid;
 
-extern (System)
+extern (Windows)
 {
 
 class ComObject : IUnknown
 {
-extern (System):
+extern (Windows):
     HRESULT QueryInterface(const(IID)* riid, void** ppv)
     {
         if (*riid == IID_IUnknown)
diff --git a/libphobos/libdruntime/core/sys/windows/dbghelp.d b/libphobos/libdruntime/core/sys/windows/dbghelp.d
index 8c9827034e9..9848fb99115 100644
--- a/libphobos/libdruntime/core/sys/windows/dbghelp.d
+++ b/libphobos/libdruntime/core/sys/windows/dbghelp.d
@@ -18,7 +18,7 @@ import core.sys.windows.windef;
 
 public import core.sys.windows.dbghelp_types;
 
-extern(System)
+extern(Windows)
 {
     alias BOOL         function(HANDLE hProcess, DWORD64 lpBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) ReadProcessMemoryProc64;
     alias PVOID        function(HANDLE hProcess, DWORD64 AddrBase) FunctionTableAccessProc64;
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index defdc9586f1..638eada3e43 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -1539,9 +1539,9 @@ package extern(D) void* getStackBottom() nothrow @nogc
             void *bottom;
 
             version (X86)
-                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" (bottom); }
             else version (X86_64)
-                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" (bottom); }
             else
                 static assert(false, "Platform not supported.");
 
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 2e679320c38..5ce4869d096 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -805,7 +805,7 @@ version (GNU_SEH_Exceptions)
                                                            void* ms_orig_context, void* ms_disp)
     {
         return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context,
-                                     ms_disp, &__gdc_personality_imp);
+                                     ms_disp, &gdc_personality);
     }
 }
 else version (GNU_SjLj_Exceptions)
diff --git a/libphobos/libdruntime/gcc/gthread.d b/libphobos/libdruntime/gcc/gthread.d
index ef35a3c27ec..5003637b9ea 100644
--- a/libphobos/libdruntime/gcc/gthread.d
+++ b/libphobos/libdruntime/gcc/gthread.d
@@ -86,10 +86,12 @@ else static if (GNU_Thread_Model == ThreadModel.Single)
 }
 else static if (GNU_Thread_Model == ThreadModel.Win32)
 {
+    import core.stdc.config;
+
     struct __gthread_once_t
     {
-        INT done;
-        LONG started;
+        int done;
+        c_long started;
     }
 
     int __gthr_win32_key_create(__gthread_key_t* keyp, GthreadDestroyFn dtor);
diff --git a/libphobos/libdruntime/gcc/sections/package.d b/libphobos/libdruntime/gcc/sections/package.d
index fdaf039fcfa..5d76072af25 100644
--- a/libphobos/libdruntime/gcc/sections/package.d
+++ b/libphobos/libdruntime/gcc/sections/package.d
@@ -22,26 +22,20 @@
 
 module gcc.sections;
 
-version (CRuntime_Glibc)
-    public import gcc.sections.elf_shared;
-else version (CRuntime_Musl)
-    public import gcc.sections.elf_shared;
-else version (CRuntime_UClibc)
-    public import gcc.sections.elf_shared;
-else version (FreeBSD)
-    public import gcc.sections.elf_shared;
-else version (NetBSD)
-    public import gcc.sections.elf_shared;
-else version (DragonFlyBSD)
-    public import gcc.sections.elf_shared;
-else version (Solaris)
+version (CRuntime_Glibc)  version = ElfShared;
+version (CRuntime_Musl)   version = ElfShared;
+version (CRuntime_UClibc) version = ElfShared;
+version (FreeBSD)         version = ElfShared;
+version (NetBSD)          version = ElfShared;
+version (DragonFlyBSD)    version = ElfShared;
+version (Solaris)         version = ElfShared;
+
+version (ElfShared)
     public import gcc.sections.elf_shared;
 else version (OSX)
     public import gcc.sections.osx;
-else version (CRuntime_DigitalMars)
-    public import gcc.sections.win32;
-else version (CRuntime_Microsoft)
-    public import gcc.sections.win64;
+else version (Windows)
+    public import gcc.sections.pecoff;
 else version (CRuntime_Bionic)
     public import gcc.sections.android;
 else
diff --git a/libphobos/libdruntime/gcc/sections/pecoff.d b/libphobos/libdruntime/gcc/sections/pecoff.d
new file mode 100644
index 00000000000..5fa1df2ac54
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/pecoff.d
@@ -0,0 +1,830 @@
+// PE/COFF-specific support for sections.
+// Copyright (C) 2021 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.pecoff;
+
+version (Windows):
+
+import core.memory;
+import core.stdc.stdlib;
+import core.sys.windows.winbase;
+import core.sys.windows.windef;
+import core.sys.windows.winnt;
+import rt.minfo;
+import rt.util.container.array;
+import rt.util.container.hashtab;
+
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+/****
+ * Asserts the specified condition, independent from -release, by abort()ing.
+ * Regular assertions throw an AssertError and thus require an initialized
+ * GC, which isn't the case (yet or anymore) for the startup/shutdown code in
+ * this module (called by CRT ctors/dtors etc.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+alias DSO SectionGroup;
+struct DSO
+{
+    static int opApply(scope int delegate(ref DSO) dg)
+    {
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
+    {
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+
+    invariant()
+    {
+        safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO.");
+    }
+
+    void** _slot;
+    ModuleGroup _moduleGroup;
+    Array!(void[]) _gcRanges;
+
+    version (Shared)
+    {
+        Array!(void[]) _codeSegments; // array of code segments
+        Array!(DSO*) _deps; // D libraries needed by this DSO
+        void* _handle; // corresponding handle
+    }
+}
+
+/****
+ * Boolean flag set to true while the runtime is initialized.
+ */
+__gshared bool _isRuntimeInitialized;
+
+/****
+ * Gets called on program startup just before GC is initialized.
+ */
+void initSections() nothrow @nogc
+{
+    _isRuntimeInitialized = true;
+}
+
+/***
+ * Gets called on program shutdown just after GC is terminated.
+ */
+void finiSections() nothrow @nogc
+{
+    _isRuntimeInitialized = false;
+}
+
+alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
+
+version (Shared)
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(ThreadDSO)* initTLSRanges() @nogc nothrow
+    {
+        return &_loadedDSOs();
+    }
+
+    void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow
+    {
+        // Nothing to do here. tdsos used to point to the _loadedDSOs instance
+        // in the dying thread's TLS segment and as such is not valid anymore.
+        // The memory for the array contents was already reclaimed in
+        // cleanupLoadedLibraries().
+    }
+
+    void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
+
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof);
+        res.length = _loadedDSOs.length;
+        foreach (i, ref tdso; _loadedDSOs)
+        {
+            (*res)[i] = tdso;
+            if (tdso._addCnt)
+            {
+                // Increment the DLL ref for explicitly loaded libraries to pin them.
+                char[MAX_PATH] buf;
+                char[] buffer = buf[];
+                const success = .LoadLibraryA(nameForDSO(tdso._pdso, buffer)) !is null;
+                safeAssert(success, "Failed to increment DLL ref.");
+                (*res)[i]._addCnt = 1; // new array takes over the additional ref count
+            }
+        }
+        return res;
+    }
+
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+        auto pary = cast(Array!(ThreadDSO)*)p;
+        // In case something failed we need to undo the pinning.
+        foreach (ref tdso; *pary)
+        {
+            if (tdso._addCnt)
+            {
+                auto handle = tdso._pdso._handle;
+                safeAssert(handle !is null, "Invalid library handle.");
+                .FreeLibrary(handle);
+            }
+        }
+        pary.reset();
+        .free(pary);
+    }
+
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
+    {
+        safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread.");
+        _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p);
+        .free(p);
+    }
+
+    // Called after all TLS dtors ran, decrements all remaining DLL refs.
+    void cleanupLoadedLibraries() nothrow @nogc
+    {
+        foreach (ref tdso; _loadedDSOs)
+        {
+            if (tdso._addCnt == 0) continue;
+
+            auto handle = tdso._pdso._handle;
+            safeAssert(handle !is null, "Invalid DSO handle.");
+            for (; tdso._addCnt > 0; --tdso._addCnt)
+                .FreeLibrary(handle);
+        }
+
+        // Free the memory for the array contents.
+        _loadedDSOs.reset();
+    }
+}
+else
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(void[])* initTLSRanges() nothrow @nogc
+    {
+        return null;
+    }
+
+    void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc
+    {
+    }
+
+    void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
+}
+
+private:
+
+version (Shared)
+{
+    /*
+     * Array of thread local DSO metadata for all libraries loaded and
+     * initialized in this thread.
+     *
+     * Note:
+     *     A newly spawned thread will inherit these libraries.
+     * Note:
+     *     We use an array here to preserve the order of
+     *     initialization.  If that became a performance issue, we
+     *     could use a hash table and enumerate the DSOs during
+     *     loading so that the hash table values could be sorted when
+     *     necessary.
+     */
+    struct ThreadDSO
+    {
+        DSO* _pdso;
+        static if (_pdso.sizeof == 8) uint _refCnt, _addCnt;
+        else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt;
+        else static assert(0, "unimplemented");
+        alias _pdso this;
+    }
+
+    @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow
+    {
+        static Array!(ThreadDSO) x;
+        return x;
+    }
+
+    /*
+     * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+     */
+    bool _rtLoading;
+
+    /*
+     * Hash table to map the native handle (as returned by dlopen)
+     * to the corresponding DSO*, protected by a mutex.
+     */
+    __gshared CRITICAL_SECTION _handleToDSOMutex;
+    @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow
+    {
+        __gshared HashTab!(void*, DSO*) x;
+        return x;
+    }
+}
+else
+{
+    /*
+     * Static DSOs loaded by the runtime linker. This includes the
+     * executable. These can't be unloaded.
+     */
+    @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
+    {
+        __gshared Array!(DSO*) x;
+        return x;
+    }
+
+    enum _rtLoading = false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
+
+/****
+ * This data structure is generated by the compiler, and then passed to
+ * _d_dso_registry().
+ */
+struct CompilerDSOData
+{
+    size_t _version;                                       // currently 1
+    void** _slot;                                          // can be used to store runtime data
+    immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file
+}
+
+T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; }
+
+/* For each shared library and executable, the compiler generates code that
+ * sets up CompilerDSOData and calls _d_dso_registry().
+ * A pointer to that code is inserted into both the .ctors and .dtors
+ * segment so it gets called by the loader on startup and shutdown.
+ */
+extern(C) void _d_dso_registry(CompilerDSOData* data)
+{
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
+
+    // no backlink => register
+    if (*data._slot is null)
+    {
+        immutable firstDSO = _loadedDSOs.empty;
+        if (firstDSO) initLocks();
+
+        DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
+        assert(typeid(DSO).initializer().ptr is null);
+        pdso._slot = data._slot;
+        *data._slot = pdso; // store backlink in library record
+
+        pdso._moduleGroup = ModuleGroup(toRange(data._minfo_beg, data._minfo_end));
+
+        HMODULE handle = void;
+        const moduleFound = findModuleHandleForAddr(data._slot, handle);
+        safeAssert(moduleFound, "Failed to find image header.");
+
+        scanSegments(handle, pdso);
+
+        version (Shared)
+        {
+            getDependencies(handle, pdso._deps);
+            pdso._handle = handle;
+            setDSOForHandle(pdso, pdso._handle);
+
+            if (!_rtLoading)
+            {
+                /* This DSO was not loaded by rt_loadLibrary which
+                 * happens for all dependencies of an executable or
+                 * the first dlopen call from a C program.
+                 * In this case we add the DSO to the _loadedDSOs of this
+                 * thread with a refCnt of 1 and call the TlsCtors.
+                 */
+                immutable ushort refCnt = 1, addCnt = 0;
+                _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            }
+        }
+        else
+        {
+            foreach (p; _loadedDSOs)
+                safeAssert(p !is pdso, "DSO already registered.");
+            _loadedDSOs.insertBack(pdso);
+        }
+
+        // don't initialize modules before rt_init was called
+        if (_isRuntimeInitialized)
+        {
+            registerGCRanges(pdso);
+            // rt_loadLibrary will run tls ctors, so do this only for dlopen
+            immutable runTlsCtors = !_rtLoading;
+            runModuleConstructors(pdso, runTlsCtors);
+        }
+    }
+    // has backlink => unregister
+    else
+    {
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
+
+        // don't finalizes modules after rt_term was called (see Bugzilla 11378)
+        if (_isRuntimeInitialized)
+        {
+            // rt_unloadLibrary already ran tls dtors, so do this only for dlclose
+            immutable runTlsDtors = !_rtLoading;
+            runModuleDestructors(pdso, runTlsDtors);
+            unregisterGCRanges(pdso);
+            // run finalizers after module dtors (same order as in rt_term)
+            version (Shared) runFinalizers(pdso);
+        }
+
+        version (Shared)
+        {
+            if (!_rtLoading)
+            {
+                /* This DSO was not unloaded by rt_unloadLibrary so we
+                 * have to remove it from _loadedDSOs here.
+                 */
+                foreach (i, ref tdso; _loadedDSOs)
+                {
+                    if (tdso._pdso == pdso)
+                    {
+                        _loadedDSOs.remove(i);
+                        break;
+                    }
+                }
+            }
+
+            unsetDSOForHandle(pdso, pdso._handle);
+        }
+        else
+        {
+            // static DSOs are unloaded in reverse order
+            safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+            _loadedDSOs.popBack();
+        }
+
+        freeDSO(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+            version (Shared)
+            {
+                safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs.");
+                _handleToDSO.reset();
+            }
+            finiLocks();
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// dynamic loading
+///////////////////////////////////////////////////////////////////////////////
+
+// Shared D libraries are only supported when linking against a shared druntime library.
+
+version (Shared)
+{
+    ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc
+    {
+        foreach (ref tdata; _loadedDSOs)
+            if (tdata._pdso == pdso) return &tdata;
+        return null;
+    }
+
+    void incThreadRef(DSO* pdso, bool incAdd)
+    {
+        if (auto tdata = findThreadDSO(pdso)) // already initialized
+        {
+            if (incAdd && ++tdata._addCnt > 1) return;
+            ++tdata._refCnt;
+        }
+        else
+        {
+            foreach (dep; pdso._deps)
+                incThreadRef(dep, false);
+            immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
+            _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            pdso._moduleGroup.runTlsCtors();
+        }
+    }
+
+    void decThreadRef(DSO* pdso, bool decAdd)
+    {
+        auto tdata = findThreadDSO(pdso);
+        safeAssert(tdata !is null, "Failed to find thread DSO.");
+        safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call.");
+
+        if (decAdd && --tdata._addCnt > 0) return;
+        if (--tdata._refCnt > 0) return;
+
+        pdso._moduleGroup.runTlsDtors();
+        foreach (i, ref td; _loadedDSOs)
+            if (td._pdso == pdso) _loadedDSOs.remove(i);
+        foreach (dep; pdso._deps)
+            decThreadRef(dep, false);
+    }
+}
+
+/***********************************
+ * These are a temporary means of providing a GC hook for DLL use.  They may be
+ * replaced with some other similar functionality later.
+ */
+extern (C)
+{
+    void* gc_getProxy();
+    void  gc_setProxy(void* p);
+    void  gc_clrProxy();
+
+    alias void  function(void*) gcSetFn;
+    alias void  function()      gcClrFn;
+}
+
+/*******************************************
+ * Loads a DLL written in D with the name 'name'.
+ * Returns:
+ *      opaque handle to the DLL if successfully loaded
+ *      null if failure
+ */
+extern(C) void* rt_loadLibrary(const char* name)
+{
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+    }
+    return initLibrary(.LoadLibraryA(name));
+}
+
+extern (C) void* rt_loadLibraryW(const wchar_t* name)
+{
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+    }
+    return initLibrary(.LoadLibraryW(name));
+}
+
+void* initLibrary(void* handle)
+{
+    if (handle is null)
+        return null;
+
+    version (Shared)
+    {
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            incThreadRef(pdso, true);
+    }
+    gcSetFn gcSet = cast(gcSetFn) GetProcAddress(handle, "gc_setProxy");
+    if (gcSet !is null)
+    {
+        // BUG: Set proxy, but too late
+        gcSet(gc_getProxy());
+    }
+    return handle;
+}
+
+/*************************************
+ * Unloads DLL that was previously loaded by rt_loadLibrary().
+ * Input:
+ *      handle  the handle returned by rt_loadLibrary()
+ * Returns:
+ *      1   succeeded
+ *      0   some failure happened
+ */
+extern(C) int rt_unloadLibrary(void* handle)
+{
+    if (handle is null)
+        return false;
+
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            decThreadRef(pdso, true);
+    }
+    gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(handle, "gc_clrProxy");
+    if (gcClr !is null)
+        gcClr();
+    return .FreeLibrary(handle) != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// helper functions
+///////////////////////////////////////////////////////////////////////////////
+
+void initLocks() nothrow @nogc
+{
+    version (Shared)
+        InitializeCriticalSection(&_handleToDSOMutex);
+}
+
+void finiLocks() nothrow @nogc
+{
+    version (Shared)
+        DeleteCriticalSection(&_handleToDSOMutex);
+}
+
+void runModuleConstructors(DSO* pdso, bool runTlsCtors)
+{
+    pdso._moduleGroup.sortCtors();
+    pdso._moduleGroup.runCtors();
+    if (runTlsCtors) pdso._moduleGroup.runTlsCtors();
+}
+
+void runModuleDestructors(DSO* pdso, bool runTlsDtors)
+{
+    if (runTlsDtors) pdso._moduleGroup.runTlsDtors();
+    pdso._moduleGroup.runDtors();
+}
+
+void registerGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.addRange(rng.ptr, rng.length);
+}
+
+void unregisterGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.removeRange(rng.ptr);
+}
+
+version (Shared) void runFinalizers(DSO* pdso)
+{
+    foreach (seg; pdso._codeSegments)
+        GC.runFinalizers(seg);
+}
+
+void freeDSO(DSO* pdso) nothrow @nogc
+{
+    pdso._gcRanges.reset();
+    version (Shared)
+    {
+        pdso._codeSegments.reset();
+        pdso._deps.reset();
+        pdso._handle = null;
+    }
+    .free(pdso);
+}
+
+version (Shared)
+{
+@nogc nothrow:
+    const(char)* nameForDSO(DSO* pdso, ref char[] buffer)
+    {
+        const success = GetModuleFileNameA(pdso._handle, buffer.ptr, cast(DWORD)buffer.length) != 0;
+        safeAssert(success, "Failed to get DLL name.");
+        return buffer.ptr;
+    }
+
+    DSO* dsoForHandle(in void* handle)
+    {
+        DSO* pdso;
+        .EnterCriticalSection(&_handleToDSOMutex);
+        if (auto ppdso = handle in _handleToDSO)
+            pdso = *ppdso;
+        .LeaveCriticalSection(&_handleToDSOMutex);
+        return pdso;
+    }
+
+    void setDSOForHandle(DSO* pdso, void* handle)
+    {
+        .EnterCriticalSection(&_handleToDSOMutex);
+        safeAssert(handle !in _handleToDSO, "DSO already registered.");
+        _handleToDSO[handle] = pdso;
+        .LeaveCriticalSection(&_handleToDSOMutex);
+    }
+
+    void unsetDSOForHandle(DSO* pdso, void* handle)
+    {
+        .EnterCriticalSection(&_handleToDSOMutex);
+        safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO.");
+        _handleToDSO.remove(handle);
+        .LeaveCriticalSection(&_handleToDSOMutex);
+    }
+
+    void getDependencies(in HMODULE handle, ref Array!(DSO*) deps)
+    {
+        auto nthdr = getNTHeader(handle);
+        auto import_entry = nthdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+        auto addr = import_entry.VirtualAddress;
+        auto datasize = import_entry.Size;
+
+        if (addr == 0 && datasize == 0)
+        {
+            // Maybe the optional header isn't there, look for the section.
+            foreach (section; getSectionHeader(handle))
+            {
+                if (!compareSectionName(section, ".idata"))
+                    continue;
+                addr = section.VirtualAddress;
+                datasize = section.Misc.VirtualSize;
+                break;
+            }
+            if (datasize == 0)
+                return;
+        }
+        else
+        {
+            bool foundSection = false;
+            foreach (section; getSectionHeader(handle))
+            {
+                if (!compareSectionName(section, ".idata"))
+                    continue;
+                // Section containing import table has no contents.
+                if (section.Misc.VirtualSize == 0)
+                    return;
+                foundSection = true;
+                break;
+            }
+            // There is an import table, but the section containing it could not be found
+            if (!foundSection)
+                return;
+        }
+
+        // Get the names of each DLL
+        for (uint i = 0; i + IMAGE_IMPORT_DESCRIPTOR.sizeof <= datasize;
+             i += IMAGE_IMPORT_DESCRIPTOR.sizeof)
+        {
+            const data = cast(PIMAGE_IMPORT_DESCRIPTOR)(handle + addr + i);
+            if (data.Name == 0)
+                break;
+
+            // dll name of dependency
+            auto name = cast(char*)(handle + data.Name);
+            // get handle without loading the library
+            auto libhandle = handleForName(name);
+            // the runtime linker has already loaded all dependencies
+            safeAssert(handle !is null, "Failed to get library handle.");
+            // if it's a D library
+            if (auto pdso = dsoForHandle(handle))
+                deps.insertBack(pdso); // append it to the dependencies
+        }
+    }
+
+    void* handleForName(const char* name)
+    {
+        return GetModuleHandleA(name);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PE/COFF program header iteration
+///////////////////////////////////////////////////////////////////////////////
+
+bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc
+{
+    if (name[] != cast(char[])section.Name[0 .. name.length])
+        return false;
+    return name.length == 8 || section.Name[name.length] == 0;
+}
+
+/************
+ * Scan segments in the image header and store
+ * the writeable data segments in *pdso.
+ */
+
+void scanSegments(in HMODULE handle, DSO* pdso) nothrow @nogc
+{
+    foreach (section; getSectionHeader(handle))
+    {
+        // the ".data" image section includes both object file sections ".data" and ".bss"
+        if (compareSectionName(section, ".data"))
+        {
+            auto data = cast(void*)handle + section.VirtualAddress;
+            pdso._gcRanges.insertBack(data[0 .. section.Misc.VirtualSize]);
+            continue;
+        }
+
+        version (Shared)
+        {
+            if (compareSectionName(section, ".text"))
+            {
+                auto text = cast(void*)handle + section.VirtualAddress;
+                pdso._codeSegments.insertBack(text[0 .. section.Misc.VirtualSize]);
+                continue;
+            }
+        }
+    }
+}
+
+/**************************
+ * Input:
+ *      handle  where the output is to be written
+ * Returns:
+ *      true if found, and *handle is filled in
+ */
+
+bool findModuleHandleForAddr(in void* addr, out HMODULE handle) nothrow @nogc
+{
+    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+                           cast(const(wchar)*) addr, &handle))
+        return true;
+
+    return false;
+}
+
+/**
+ * Returns the image NT header for the HMODULE handle passed,
+ * or null if not found.
+ */
+PIMAGE_NT_HEADERS getNTHeader(in HMODULE handle) nothrow @nogc
+{
+    auto doshdr = cast(PIMAGE_DOS_HEADER)handle;
+    if (doshdr.e_magic != IMAGE_DOS_SIGNATURE)
+        return null;
+
+    return cast(typeof(return))(cast(void*)doshdr + doshdr.e_lfanew);
+}
+
+/**
+ * Returns the image section header for the HMODULE handle passed,
+ * or null if not found.
+ */
+IMAGE_SECTION_HEADER[] getSectionHeader(in HMODULE handle) nothrow @nogc
+{
+    if (auto nthdr = getNTHeader(handle))
+    {
+        const void* opthdr = &nthdr.OptionalHeader;
+        const offset = nthdr.FileHeader.SizeOfOptionalHeader;
+        const length = nthdr.FileHeader.NumberOfSections;
+        return (cast(PIMAGE_SECTION_HEADER)(opthdr + offset))[0 .. length];
+    }
+    return null;
+}
diff --git a/libphobos/libdruntime/gcc/sections/win32.d b/libphobos/libdruntime/gcc/sections/win32.d
deleted file mode 100644
index b355dfc5068..00000000000
--- a/libphobos/libdruntime/gcc/sections/win32.d
+++ /dev/null
@@ -1,183 +0,0 @@
-// Win32-specific support for sections.
-// Copyright (C) 2019-2021 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.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-module gcc.sections.win32;
-
-version (CRuntime_DigitalMars):
-
-// debug = PRINTF;
-debug(PRINTF) import core.stdc.stdio;
-import rt.minfo;
-import core.stdc.stdlib : malloc, free;
-
-struct SectionGroup
-{
-    static int opApply(scope int delegate(ref SectionGroup) dg)
-    {
-        return dg(_sections);
-    }
-
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
-    {
-        return dg(_sections);
-    }
-
-    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-    ModuleGroup _moduleGroup;
-    void[][] _gcRanges;
-}
-
-shared(bool) conservative;
-
-void initSections() nothrow @nogc
-{
-    _sections._moduleGroup = ModuleGroup(getModuleInfos());
-
-    import rt.sections;
-    conservative = !scanDataSegPrecisely();
-
-    if (conservative)
-    {
-        _sections._gcRanges = (cast(void[]*) malloc(2 * (void[]).sizeof))[0..2];
-
-        auto databeg = cast(void*)&_xi_a;
-        auto dataend = cast(void*)_moduleinfo_array.ptr;
-        _sections._gcRanges[0] = databeg[0 .. dataend - databeg];
-
-        // skip module info and CONST segment
-        auto bssbeg = cast(void*)&_edata;
-        auto bssend = cast(void*)&_end;
-        _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg];
-    }
-    else
-    {
-        size_t count = &_DPend - &_DPbegin;
-        auto ranges = cast(void[]*) malloc(count * (void[]).sizeof);
-        size_t r = 0;
-        void* prev = null;
-        for (size_t i = 0; i < count; i++)
-        {
-            void* addr = (&_DPbegin)[i];
-            if (prev + (void*).sizeof == addr)
-                ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof];
-            else
-                ranges[r++] = (cast(void**)addr)[0..1];
-            prev = addr;
-        }
-        _sections._gcRanges = ranges[0..r];
-    }
-}
-
-void finiSections() nothrow @nogc
-{
-    free(_sections._gcRanges.ptr);
-}
-
-void[] initTLSRanges() nothrow @nogc
-{
-    auto pbeg = cast(void*)&_tlsstart;
-    auto pend = cast(void*)&_tlsend;
-    return pbeg[0 .. pend - pbeg];
-}
-
-void finiTLSRanges(void[] rng) nothrow @nogc
-{
-}
-
-void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    if (conservative)
-    {
-        dg(rng.ptr, rng.ptr + rng.length);
-    }
-    else
-    {
-        for (auto p = &_TPbegin; p < &_TPend; )
-        {
-            uint beg = *p++;
-            uint end = beg + cast(uint)((void*).sizeof);
-            while (p < &_TPend && *p == end)
-            {
-                end += (void*).sizeof;
-                p++;
-            }
-            dg(rng.ptr + beg, rng.ptr + end);
-        }
-    }
-}
-
-private:
-
-__gshared SectionGroup _sections;
-
-// Windows: this gets initialized by minit.asm
-extern(C) __gshared immutable(ModuleInfo*)[] _moduleinfo_array;
-extern(C) void _minit() nothrow @nogc;
-
-immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc
-out (result)
-{
-    foreach (m; result)
-        assert(m !is null);
-}
-body
-{
-    // _minit directly alters the global _moduleinfo_array
-    _minit();
-    return _moduleinfo_array;
-}
-
-extern(C)
-{
-    extern __gshared
-    {
-        int _xi_a;      // &_xi_a just happens to be start of data segment
-        int _edata;     // &_edata is start of BSS segment
-        int _end;       // &_end is past end of BSS
-
-        void* _DPbegin; // first entry in the array of pointers addresses
-        void* _DPend;   // &_DPend points after last entry of array
-        uint _TPbegin;  // first entry in the array of TLS offsets of pointers
-        uint _TPend;    // &_DPend points after last entry of array
-    }
-
-    extern
-    {
-        int _tlsstart;
-        int _tlsend;
-    }
-}
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         return _moduleGroup;
     }
 
-    version (Win64)
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        auto pbeg = cast(immutable(FuncTable)*)&_deh_beg;
-        auto pend = cast(immutable(FuncTable)*)&_deh_end;
-        return pbeg[0 .. pend - pbeg];
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
diff --git a/libphobos/libdruntime/gcc/unwind/generic.d b/libphobos/libdruntime/gcc/unwind/generic.d
index 5315739f82f..592b3afcb71 100644
--- a/libphobos/libdruntime/gcc/unwind/generic.d
+++ b/libphobos/libdruntime/gcc/unwind/generic.d
@@ -269,6 +269,6 @@ version (GNU_SEH_Exceptions)
         ExceptionCollidedUnwind
     }
 
-    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*,
+    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, void*,
                                                           _Unwind_Personality_Fn);
 }
diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d
index 3d5ba299863..e4a2c6571d4 100644
--- a/libphobos/libdruntime/rt/dmain2.d
+++ b/libphobos/libdruntime/rt/dmain2.d
@@ -70,70 +70,6 @@ version (CRuntime_Microsoft)
     extern(C) void init_msvc();
 }
 
-/***********************************
- * These are a temporary means of providing a GC hook for DLL use.  They may be
- * replaced with some other similar functionality later.
- */
-extern (C)
-{
-    void* gc_getProxy();
-    void  gc_setProxy(void* p);
-    void  gc_clrProxy();
-
-    alias void* function()      gcGetFn;
-    alias void  function(void*) gcSetFn;
-    alias void  function()      gcClrFn;
-}
-
-version (Windows)
-{
-    /*******************************************
-     * Loads a DLL written in D with the name 'name'.
-     * Returns:
-     *      opaque handle to the DLL if successfully loaded
-     *      null if failure
-     */
-    extern (C) void* rt_loadLibrary(const char* name)
-    {
-        return initLibrary(.LoadLibraryA(name));
-    }
-
-    extern (C) void* rt_loadLibraryW(const wchar_t* name)
-    {
-        return initLibrary(.LoadLibraryW(name));
-    }
-
-    void* initLibrary(void* mod)
-    {
-        // BUG: LoadLibrary() call calls rt_init(), which fails if proxy is not set!
-        // (What? LoadLibrary() is a Windows API call, it shouldn't call rt_init().)
-        if (mod is null)
-            return mod;
-        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(mod, "gc_setProxy");
-        if (gcSet !is null)
-        {   // BUG: Set proxy, but too late
-            gcSet(gc_getProxy());
-        }
-        return mod;
-    }
-
-    /*************************************
-     * Unloads DLL that was previously loaded by rt_loadLibrary().
-     * Input:
-     *      ptr     the handle returned by rt_loadLibrary()
-     * Returns:
-     *      1   succeeded
-     *      0   some failure happened
-     */
-    extern (C) int rt_unloadLibrary(void* ptr)
-    {
-        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
-        if (gcClr !is null)
-            gcClr();
-        return FreeLibrary(ptr) != 0;
-    }
-}
-
 /* To get out-of-band access to the args[] passed to main().
  */


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [gcc(refs/users/ibuclaw/heads/mingw)] More MSVC support
@ 2021-03-24 16:10 Iain Buclaw
  0 siblings, 0 replies; 5+ messages in thread
From: Iain Buclaw @ 2021-03-24 16:10 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c8979afc92dfcdb4650900192a455d14618392df

commit c8979afc92dfcdb4650900192a455d14618392df
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Wed Mar 24 16:24:04 2021 +0100

    More MSVC support

Diff:
---
 gcc/config/aarch64/aarch64-d.c                     |   2 +
 gcc/config/arm/arm-d.c                             |   2 +
 gcc/config/i386/cygming.h                          |   2 +
 gcc/config/i386/i386-d.c                           |  13 +
 gcc/config/i386/i386-protos.h                      |   1 +
 gcc/config/i386/i386.h                             |   3 +-
 gcc/config/i386/winnt-d.c                          |   7 +
 gcc/config/mips/mips-d.c                           |   2 +
 gcc/config/pa/pa-d.c                               |   2 +
 gcc/config/riscv/riscv-d.c                         |   2 +
 gcc/config/rs6000/rs6000-d.c                       |   2 +
 gcc/config/s390/s390-d.c                           |   2 +
 gcc/config/sparc/sparc-d.c                         |   2 +
 gcc/d/d-target.cc                                  |   5 +-
 gcc/d/d-target.def                                 |  10 +
 gcc/doc/tm.texi                                    |   7 +
 gcc/doc/tm.texi.in                                 |   2 +
 libphobos/Makefile.in                              |   3 +
 libphobos/configure                                |  24 +-
 libphobos/configure.ac                             |  17 +-
 libphobos/libdruntime/Makefile.am                  |   7 +-
 libphobos/libdruntime/Makefile.in                  |  68 +-
 libphobos/libdruntime/config/mingw/msvc.c          |  54 ++
 libphobos/libdruntime/config/mingw/switchcontext.S |  12 +-
 libphobos/libdruntime/core/stdc/stdlib.d           |  27 +-
 libphobos/libdruntime/core/stdc/tgmath.d           |  11 +-
 libphobos/libdruntime/core/sys/windows/com.d       |   4 +-
 libphobos/libdruntime/core/sys/windows/dbghelp.d   |   2 +-
 libphobos/libdruntime/core/sys/windows/dll.d       |  12 +-
 libphobos/libdruntime/core/thread/osthread.d       |   4 +-
 libphobos/libdruntime/gcc/deh.d                    |   2 +-
 libphobos/libdruntime/gcc/gthread.d                |   6 +-
 libphobos/libdruntime/gcc/sections/package.d       |  28 +-
 libphobos/libdruntime/gcc/sections/pecoff.d        | 830 +++++++++++++++++++++
 libphobos/libdruntime/gcc/sections/win32.d         | 183 -----
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/libdruntime/gcc/unwind/generic.d         |   2 +-
 libphobos/libdruntime/rt/dmain2.d                  |  64 --
 libphobos/src/Makefile.am                          |   2 +-
 libphobos/src/Makefile.in                          |   5 +-
 libphobos/testsuite/Makefile.in                    |   3 +
 41 files changed, 1085 insertions(+), 359 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-d.c b/gcc/config/aarch64/aarch64-d.c
index 5c9b4fa6fb8..4fce593ac27 100644
--- a/gcc/config/aarch64/aarch64-d.c
+++ b/gcc/config/aarch64/aarch64-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c
index 76ede3b6d44..2cb9f4bd899 100644
--- a/gcc/config/arm/arm-d.c
+++ b/gcc/config/arm/arm-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index cfbca34f996..59eb812c1cf 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -209,6 +209,8 @@ along with GCC; see the file COPYING3.  If not see
 #define SUBTARGET_OVERRIDE_OPTIONS					\
 do {									\
   flag_pic = TARGET_64BIT ? 1 : 0;                                      \
+  if (!global_options_set.x_dwarf_version)				\
+    dwarf_version = 4;							\
 } while (0)
 
 /* Define this macro if references to a symbol must be treated
diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c
index cbd3ceb187d..34f53ba046d 100644
--- a/gcc/config/i386/i386-d.c
+++ b/gcc/config/i386/i386-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -42,3 +44,14 @@ ix86_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Implement TARGET_D_EXTERN_SYSTEM_LINKAGE for x86 targets.  */
+
+int
+ix86_d_extern_system_linkage (void)
+{
+  if (ix86_abi == MS_ABI)
+    return LINKwindows;
+
+  return LINKc;
+}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 9f8a69ea7dc..d07bf09bc65 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void);
 
 /* In i386-d.c  */
 extern void ix86_d_target_versions (void);
+extern int ix86_d_extern_system_linkage (void);
 
 /* In winnt.c  */
 extern void i386_pe_unique_section (tree, int);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 058c1cc25b2..10954fb0aab 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -799,8 +799,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 /* Target Pragmas.  */
 #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
 
-/* Target CPU versions for D.  */
+/* Target hooks for D language.  */
 #define TARGET_D_CPU_VERSIONS ix86_d_target_versions
+#define TARGET_D_EXTERN_SYSTEM_LINKAGE ix86_d_extern_system_linkage
 
 #ifndef CC1_SPEC
 #define CC1_SPEC "%(cc1_cpu) "
diff --git a/gcc/config/i386/winnt-d.c b/gcc/config/i386/winnt-d.c
index 3b5791a7bff..d05ea8a92bf 100644
--- a/gcc/config/i386/winnt-d.c
+++ b/gcc/config/i386/winnt-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -30,6 +32,11 @@ winnt_d_os_builtins (void)
 {
   d_add_builtin_version ("Windows");
 
+  if (ix86_abi == SYSV_ABI)
+    d_add_builtin_version ("SYSV_ABI");
+  else
+    d_add_builtin_version ("MS_ABI");
+
 #define builtin_version(TXT) d_add_builtin_version (TXT)
 
 #ifdef EXTRA_TARGET_D_OS_VERSIONS
diff --git a/gcc/config/mips/mips-d.c b/gcc/config/mips/mips-d.c
index dad101cf7eb..dc57127791c 100644
--- a/gcc/config/mips/mips-d.c
+++ b/gcc/config/mips/mips-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/pa/pa-d.c b/gcc/config/pa/pa-d.c
index 1de49df12cc..663e749995a 100644
--- a/gcc/config/pa/pa-d.c
+++ b/gcc/config/pa/pa-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/riscv/riscv-d.c b/gcc/config/riscv/riscv-d.c
index 2b690b18cfd..b20b778bd35 100644
--- a/gcc/config/riscv/riscv-d.c
+++ b/gcc/config/riscv/riscv-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/rs6000/rs6000-d.c b/gcc/config/rs6000/rs6000-d.c
index 14c4133f305..6bfe8130dd3 100644
--- a/gcc/config/rs6000/rs6000-d.c
+++ b/gcc/config/rs6000/rs6000-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/s390/s390-d.c b/gcc/config/s390/s390-d.c
index 155144ce7b8..2f945ebfa12 100644
--- a/gcc/config/s390/s390-d.c
+++ b/gcc/config/s390/s390-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/sparc/sparc-d.c b/gcc/config/sparc/sparc-d.c
index 186e965ae84..0eb663bb132 100644
--- a/gcc/config/sparc/sparc-d.c
+++ b/gcc/config/sparc/sparc-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index d50fcef22e2..e95dd01b0ee 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -417,11 +417,14 @@ TargetCPP::fundamentalType (const Type *, bool &)
   return false;
 }
 
-/* Return the default system linkage for the target.  */
+/* Return the default `extern (System)` linkage for the target.  */
 
 LINK
 Target::systemLinkage (void)
 {
+  if (targetdm.d_extern_system_linkage)
+    return (LINK) targetdm.d_extern_system_linkage ();
+
   return LINKc;
 }
 
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index d1426a17e99..9fb3c7d23d9 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -46,6 +46,16 @@ relating to the target operating system.",
  void, (void),
  hook_void_void)
 
+/* */
+DEFHOOK
+(d_extern_system_linkage,
+ "If defined, this hook returns the extern linkage which should be applied\n\
+ for all declarations annotated with @code{extern (System)}.  Typically,\n\
+ @code{extern (System)} is the same as @code{extern (Windows)} on Microsoft\n\
+ Windows platforms, and @code{extern (C)} on other platforms.",
+ int, (void),
+ NULL)
+
 /* ModuleInfo section name and brackets.  */
 DEFHOOKPOD
 (d_minfo_section,
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b272fa4806d..0265ef0df5c 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10808,6 +10808,13 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions
 relating to the target operating system.
 @end deftypefn
 
+@deftypefn {D Target Hook} int TARGET_D_EXTERN_SYSTEM_LINKAGE (void)
+If defined, this hook returns the extern linkage which should be applied
+ for all declarations annotated with @code{extern (System)}.  Typically,
+ @code{extern (System)} is the same as @code{extern (Windows)} on Microsoft
+ Windows platforms, and @code{extern (C)} on other platforms.
+@end deftypefn
+
 @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION
 Contains the name of the section in which module info references should be
 placed.  This section is expected to be bracketed by two symbols to indicate
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index bf724dc093c..ef15417a791 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7357,6 +7357,8 @@ floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_OS_VERSIONS
 
+@hook TARGET_D_EXTERN_SYSTEM_LINKAGE
+
 @hook TARGET_D_MINFO_SECTION
 
 @hook TARGET_D_MINFO_START_NAME
diff --git a/libphobos/Makefile.in b/libphobos/Makefile.in
index d42248405a2..eab12688867 100644
--- a/libphobos/Makefile.in
+++ b/libphobos/Makefile.in
@@ -298,6 +298,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -327,6 +329,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
diff --git a/libphobos/configure b/libphobos/configure
index c940a404be4..59ca64aa1e0 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -705,6 +705,9 @@ libphobos_builddir
 get_gcc_base_ver
 phobos_compiler_shared_flag
 phobos_compiler_pic_flag
+phobos_lt_pic_flag
+enable_static
+enable_shared
 OTOOL64
 OTOOL
 LIPO
@@ -11746,7 +11749,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11749 "configure"
+#line 11752 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11852,7 +11855,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11855 "configure"
+#line 11858 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13997,8 +14000,14 @@ CFLAGS=$lt_save_CFLAGS
   GDCFLAGS=$gdc_save_DFLAGS
 
 
+
+
 # libtool variables for Phobos shared and position-independent compiles.
 #
+# Use phobos_lt_pic_flag to designate the automake variable
+# used to encapsulate the default libtool approach to creating objects
+# with position-independent code. Default: -prefer-pic.
+#
 # Use phobos_compiler_shared_flag to designate the compile-time flags for
 # creating shared objects. Default: -fversion=Shared.
 #
@@ -14010,26 +14019,23 @@ CFLAGS=$lt_save_CFLAGS
 # libtool, and so we make it here.  How it is handled is that in shared
 # compilations the `lt_prog_compiler_pic_D' variable is used to instead
 # ensure that conditional compilation of shared runtime code is compiled in.
-# The original PIC flags are then used in the compilation of every object.
-#
-# Why are objects destined for libgphobos.a compiled with -fPIC?
-# Because -fPIC is not harmful to use for objects destined for static
-# libraries. In addition, using -fPIC will allow the use of static
-# libgphobos.a in the creation of other D shared libraries.
 if test "$enable_shared" = yes; then
+  phobos_lt_pic_flag="-prefer-pic"
   phobos_compiler_pic_flag="$lt_prog_compiler_pic_D"
   phobos_compiler_shared_flag="-fversion=Shared"
 else
+  phobos_lt_pic_flag=
   phobos_compiler_pic_flag=
   phobos_compiler_shared_flag=
 fi
 
 
 
+
 # Override the libtool's pic_flag and pic_mode.
 # Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT.
 # NB: this impacts --with-pic and --without-pic.
-lt_prog_compiler_pic_D="$phobos_compiler_shared_flag"
+lt_prog_compiler_pic_D="$phobos_compiler_pic_flag $phobos_compiler_shared_flag"
 pic_mode='default'
 
 # Determine what GCC version number to use in filesystem paths.
diff --git a/libphobos/configure.ac b/libphobos/configure.ac
index cc9af29754f..248d0ebbc19 100644
--- a/libphobos/configure.ac
+++ b/libphobos/configure.ac
@@ -91,9 +91,15 @@ AC_SUBST(CFLAGS_FOR_BUILD)
 LT_INIT(dlopen)
 AM_PROG_LIBTOOL
 WITH_LOCAL_DRUNTIME([LT_LANG([D])], [])
+AC_SUBST(enable_shared)
+AC_SUBST(enable_static)
 
 # libtool variables for Phobos shared and position-independent compiles.
 #
+# Use phobos_lt_pic_flag to designate the automake variable
+# used to encapsulate the default libtool approach to creating objects
+# with position-independent code. Default: -prefer-pic.
+#
 # Use phobos_compiler_shared_flag to designate the compile-time flags for
 # creating shared objects. Default: -fversion=Shared.
 #
@@ -105,26 +111,23 @@ WITH_LOCAL_DRUNTIME([LT_LANG([D])], [])
 # libtool, and so we make it here.  How it is handled is that in shared
 # compilations the `lt_prog_compiler_pic_D' variable is used to instead
 # ensure that conditional compilation of shared runtime code is compiled in.
-# The original PIC flags are then used in the compilation of every object.
-#
-# Why are objects destined for libgphobos.a compiled with -fPIC?
-# Because -fPIC is not harmful to use for objects destined for static
-# libraries. In addition, using -fPIC will allow the use of static
-# libgphobos.a in the creation of other D shared libraries.
 if test "$enable_shared" = yes; then
+  phobos_lt_pic_flag="-prefer-pic"
   phobos_compiler_pic_flag="$lt_prog_compiler_pic_D"
   phobos_compiler_shared_flag="-fversion=Shared"
 else
+  phobos_lt_pic_flag=
   phobos_compiler_pic_flag=
   phobos_compiler_shared_flag=
 fi
+AC_SUBST(phobos_lt_pic_flag)
 AC_SUBST(phobos_compiler_pic_flag)
 AC_SUBST(phobos_compiler_shared_flag)
 
 # Override the libtool's pic_flag and pic_mode.
 # Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT.
 # NB: this impacts --with-pic and --without-pic.
-lt_prog_compiler_pic_D="$phobos_compiler_shared_flag"
+lt_prog_compiler_pic_D="$phobos_compiler_pic_flag $phobos_compiler_shared_flag"
 pic_mode='default'
 
 # Determine what GCC version number to use in filesystem paths.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 945271e028f..bedd7a325ec 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -23,7 +23,7 @@ D_EXTRA_DFLAGS=-nostdinc -I $(srcdir) -I .
 
 # D flags for compilation
 AM_DFLAGS= \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 # Flags for other kinds of sources
@@ -69,7 +69,8 @@ if DRUNTIME_OS_LINUX
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_LINUX)
 endif
 if DRUNTIME_OS_MINGW
-    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS)
+    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS) \
+				   config/mingw/msvc.c
 endif
 if DRUNTIME_OS_SOLARIS
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_SOLARIS)
@@ -187,7 +188,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
 	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \
+	gcc/sections/package.d gcc/sections/pecoff.d \
 	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 06c02961c86..665af30e09d 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -117,7 +117,9 @@ target_triplet = @target@
 @DRUNTIME_OS_NETBSD_TRUE@am__append_6 = $(DRUNTIME_DSOURCES_NETBSD)
 @DRUNTIME_OS_OPENBSD_TRUE@am__append_7 = $(DRUNTIME_DSOURCES_OPENBSD)
 @DRUNTIME_OS_LINUX_TRUE@am__append_8 = $(DRUNTIME_DSOURCES_LINUX)
-@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS)
+@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS) \
+@DRUNTIME_OS_MINGW_TRUE@				   config/mingw/msvc.c
+
 @DRUNTIME_OS_SOLARIS_TRUE@am__append_10 = $(DRUNTIME_DSOURCES_SOLARIS)
 # CPU specific sources
 @DRUNTIME_CPU_AARCH64_TRUE@am__append_11 = config/aarch64/switchcontext.S
@@ -213,7 +215,7 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
 	gcc/sections/android.lo gcc/sections/elf_shared.lo \
 	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/pecoff.lo gcc/unwind/arm.lo \
 	gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
 	gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
 	object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
@@ -425,7 +427,8 @@ am__objects_19 = core/sys/windows/accctrl.lo \
 	core/sys/windows/winspool.lo core/sys/windows/winsvc.lo \
 	core/sys/windows/winuser.lo core/sys/windows/winver.lo \
 	core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo
-@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19)
+@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_la-msvc.lo
 am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
 	core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \
 	core/sys/solaris/libelf.lo core/sys/solaris/link.lo \
@@ -460,24 +463,26 @@ am_libgdruntime_la_OBJECTS = $(am__objects_33)
 libgdruntime_la_OBJECTS = $(am_libgdruntime_la_OBJECTS)
 am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_34 = core/stdc/libgdruntime_convenience_la-errno_.lo
-@DRUNTIME_CPU_AARCH64_TRUE@am__objects_35 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_ARM_TRUE@am__objects_36 = config/arm/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_MIPS_TRUE@am__objects_37 = config/mips/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_POWERPC_TRUE@am__objects_38 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_39 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_40 = config/x86/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_41 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
-@DRUNTIME_CPU_S390_TRUE@am__objects_42 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
-am__objects_43 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
+@DRUNTIME_OS_MINGW_TRUE@am__objects_35 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_convenience_la-msvc.lo
+@DRUNTIME_CPU_AARCH64_TRUE@am__objects_36 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_ARM_TRUE@am__objects_37 = config/arm/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_MIPS_TRUE@am__objects_38 = config/mips/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_POWERPC_TRUE@am__objects_39 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_40 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_41 = config/x86/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_42 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
+@DRUNTIME_CPU_S390_TRUE@am__objects_43 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
+am__objects_44 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
 	$(am__objects_10) $(am__objects_12) $(am__objects_14) \
-	$(am__objects_16) $(am__objects_18) $(am__objects_20) \
-	$(am__objects_22) $(am__objects_35) $(am__objects_36) \
-	$(am__objects_37) $(am__objects_38) $(am__objects_39) \
-	$(am__objects_40) $(am__objects_41) $(am__objects_42)
-am__objects_44 = $(am__objects_1) $(am__objects_34) $(am__objects_43) \
+	$(am__objects_16) $(am__objects_18) $(am__objects_35) \
+	$(am__objects_22) $(am__objects_36) $(am__objects_37) \
+	$(am__objects_38) $(am__objects_39) $(am__objects_40) \
+	$(am__objects_41) $(am__objects_42) $(am__objects_43)
+am__objects_45 = $(am__objects_1) $(am__objects_34) $(am__objects_44) \
 	$(am__objects_32)
-am__objects_45 = $(am__objects_44)
-am_libgdruntime_convenience_la_OBJECTS = $(am__objects_45)
+am__objects_46 = $(am__objects_45)
+am_libgdruntime_convenience_la_OBJECTS = $(am__objects_46)
 libgdruntime_convenience_la_OBJECTS =  \
 	$(am_libgdruntime_convenience_la_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
@@ -659,6 +664,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -688,6 +695,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
@@ -720,7 +728,7 @@ D_EXTRA_DFLAGS = -nostdinc -I $(srcdir) -I .
 
 # D flags for compilation
 AM_DFLAGS = \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 
@@ -813,7 +821,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
 	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \
+	gcc/sections/package.d gcc/sections/pecoff.d \
 	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
@@ -1213,8 +1221,7 @@ gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/elf_shared.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/osx.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/package.lo: gcc/sections/$(am__dirstamp)
-gcc/sections/win32.lo: gcc/sections/$(am__dirstamp)
-gcc/sections/win64.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/pecoff.lo: gcc/sections/$(am__dirstamp)
 gcc/unwind/$(am__dirstamp):
 	@$(MKDIR_P) gcc/unwind
 	@: > gcc/unwind/$(am__dirstamp)
@@ -1720,6 +1727,10 @@ core/sys/windows/winuser.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/winver.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtsapi32.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtypes.lo: core/sys/windows/$(am__dirstamp)
+config/mingw/$(am__dirstamp):
+	@$(MKDIR_P) config/mingw
+	@: > config/mingw/$(am__dirstamp)
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/$(am__dirstamp)
 core/sys/solaris/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/solaris
 	@: > core/sys/solaris/$(am__dirstamp)
@@ -1769,9 +1780,6 @@ config/powerpc/$(am__dirstamp):
 	@: > config/powerpc/$(am__dirstamp)
 config/powerpc/libgdruntime_la-switchcontext.lo:  \
 	config/powerpc/$(am__dirstamp)
-config/mingw/$(am__dirstamp):
-	@$(MKDIR_P) config/mingw
-	@: > config/mingw/$(am__dirstamp)
 config/mingw/libgdruntime_la-switchcontext.lo:  \
 	config/mingw/$(am__dirstamp)
 config/x86/$(am__dirstamp):
@@ -1796,6 +1804,8 @@ libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EX
 	$(AM_V_GEN)$(libgdruntime_la_LINK) -rpath $(toolexeclibdir) $(libgdruntime_la_OBJECTS) $(libgdruntime_la_LIBADD) $(LIBS)
 core/stdc/libgdruntime_convenience_la-errno_.lo:  \
 	core/stdc/$(am__dirstamp)
+config/mingw/libgdruntime_convenience_la-msvc.lo:  \
+	config/mingw/$(am__dirstamp)
 config/aarch64/libgdruntime_convenience_la-switchcontext.lo:  \
 	config/aarch64/$(am__dirstamp)
 config/arm/libgdruntime_convenience_la-switchcontext.lo:  \
@@ -1991,9 +2001,15 @@ config/s390/libgdruntime_convenience_la-get_tls_offset.lo: config/s390/get_tls_o
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 core/stdc/libgdruntime_convenience_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_convenience_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_convenience_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_convenience_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/libphobos/libdruntime/config/mingw/msvc.c b/libphobos/libdruntime/config/mingw/msvc.c
new file mode 100644
index 00000000000..25b15a06950
--- /dev/null
+++ b/libphobos/libdruntime/config/mingw/msvc.c
@@ -0,0 +1,54 @@
+/* Windows support code to wrap differences between different
+   versions of the Microsoft C libaries.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+
+/* The symbols for stdin, stdout, and stderr are defined for D in the
+   core.stdc.stdio module.  Save the macros and redeclare them here.  */
+#define c_stdin stdin
+#undef stdin
+extern FILE *stdin;
+
+#define c_stdout stdout
+#undef stdout
+extern FILE *stdout;
+
+#define c_stderr stderr
+#undef stderr
+extern FILE *stderr;
+
+/* Set to 1 if run-time is using ucrtbase.dll.  */
+unsigned char msvcUsesUCRT;
+
+void init_msvc()
+{
+#if __MSVCRT_VERSION__ >= 0x1400
+  msvcUsedUCRT = 1;
+#endif
+
+  stdin = c_stdin;
+  stdout = c_stdout;
+  stderr = c_stderr;
+}
diff --git a/libphobos/libdruntime/config/mingw/switchcontext.S b/libphobos/libdruntime/config/mingw/switchcontext.S
index 6592ff604bc..0cb8b015bfc 100644
--- a/libphobos/libdruntime/config/mingw/switchcontext.S
+++ b/libphobos/libdruntime/config/mingw/switchcontext.S
@@ -28,7 +28,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -63,13 +66,15 @@ CSYM(fiber_switchContext):
     popq %RCX;
     jmp *%RCX;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #elif defined(_X86_)
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -104,6 +109,5 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #endif
diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d
index 7caef4c1339..b048a944a88 100644
--- a/libphobos/libdruntime/core/stdc/stdlib.d
+++ b/libphobos/libdruntime/core/stdc/stdlib.d
@@ -121,19 +121,22 @@ ulong   strtoull(scope inout(char)* nptr, scope inout(char)** endptr, int base);
 
 version (CRuntime_Microsoft)
 {
-    // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
-    ///
-    extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
-    {   // Fake it 'till we make it
-        return strtod(nptr, endptr);
+    version (MinGW)
+    {
+        ///
+        real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
+        ///
+        alias __mingw_strtold strtold;
+    }
+    else
+    {
+        // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
+        ///
+        extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
+        {   // Fake it 'till we make it
+            return strtod(nptr, endptr);
+        }
     }
-}
-else version (MinGW)
-{
-    ///
-    real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
-    ///
-    alias __mingw_strtold strtold;
 }
 else
 {
diff --git a/libphobos/libdruntime/core/stdc/tgmath.d b/libphobos/libdruntime/core/stdc/tgmath.d
index 4dd1b3ccc66..9a351db3861 100644
--- a/libphobos/libdruntime/core/stdc/tgmath.d
+++ b/libphobos/libdruntime/core/stdc/tgmath.d
@@ -1409,13 +1409,20 @@ else
     alias core.stdc.math.fabs          fabs;
     version (CRuntime_Microsoft)
     {
+        version (MinGW)
+        {
+            ///
+            alias core.stdc.math.fabsf fabs;
+            ///
+            alias core.stdc.math.fabsl fabs;
+        }
     }
     else
     {
         ///
-        alias core.stdc.math.fabsf         fabs;
+        alias core.stdc.math.fabsf     fabs;
         ///
-        alias core.stdc.math.fabsl         fabs;
+        alias core.stdc.math.fabsl     fabs;
     }
 
     ///
diff --git a/libphobos/libdruntime/core/sys/windows/com.d b/libphobos/libdruntime/core/sys/windows/com.d
index 90a294343fc..2808a6c59fc 100644
--- a/libphobos/libdruntime/core/sys/windows/com.d
+++ b/libphobos/libdruntime/core/sys/windows/com.d
@@ -57,12 +57,12 @@ alias COINIT_SPEED_OVER_MEMORY   = COINIT.COINIT_SPEED_OVER_MEMORY;
 
 public import core.sys.windows.uuid;
 
-extern (System)
+extern (Windows)
 {
 
 class ComObject : IUnknown
 {
-extern (System):
+extern (Windows):
     HRESULT QueryInterface(const(IID)* riid, void** ppv)
     {
         if (*riid == IID_IUnknown)
diff --git a/libphobos/libdruntime/core/sys/windows/dbghelp.d b/libphobos/libdruntime/core/sys/windows/dbghelp.d
index 8c9827034e9..9848fb99115 100644
--- a/libphobos/libdruntime/core/sys/windows/dbghelp.d
+++ b/libphobos/libdruntime/core/sys/windows/dbghelp.d
@@ -18,7 +18,7 @@ import core.sys.windows.windef;
 
 public import core.sys.windows.dbghelp_types;
 
-extern(System)
+extern(Windows)
 {
     alias BOOL         function(HANDLE hProcess, DWORD64 lpBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) ReadProcessMemoryProc64;
     alias PVOID        function(HANDLE hProcess, DWORD64 AddrBase) FunctionTableAccessProc64;
diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d
index 9f36ac389a6..3df0d7fd41b 100644
--- a/libphobos/libdruntime/core/sys/windows/dll.d
+++ b/libphobos/libdruntime/core/sys/windows/dll.d
@@ -31,17 +31,7 @@ public import core.sys.windows.threadaux;
 //  not access tls_array[tls_index] as needed for thread local _tlsstart and _tlsend
 extern (C)
 {
-        version (MinGW)
-        {
-            extern __gshared void* _tls_start;
-            extern __gshared void* _tls_end;
-            extern __gshared void* __xl_a;
-
-            alias _tls_start _tlsstart;
-            alias _tls_end   _tlsend;
-            alias __xl_a     _tls_callbacks_a;
-        }
-        else version (Win32)
+    version (Win32)
     {
         version (CRuntime_DigitalMars)
         {
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index defdc9586f1..638eada3e43 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -1539,9 +1539,9 @@ package extern(D) void* getStackBottom() nothrow @nogc
             void *bottom;
 
             version (X86)
-                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" (bottom); }
             else version (X86_64)
-                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" (bottom); }
             else
                 static assert(false, "Platform not supported.");
 
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index c747b5132d1..7e02dabd221 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -805,7 +805,7 @@ version (GNU_SEH_Exceptions)
                                                            void* ms_orig_context, void* ms_disp)
     {
         return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context,
-                                     ms_disp, &__gdc_personality_imp);
+                                     ms_disp, &gdc_personality);
     }
 }
 else version (GNU_SjLj_Exceptions)
diff --git a/libphobos/libdruntime/gcc/gthread.d b/libphobos/libdruntime/gcc/gthread.d
index ef35a3c27ec..5003637b9ea 100644
--- a/libphobos/libdruntime/gcc/gthread.d
+++ b/libphobos/libdruntime/gcc/gthread.d
@@ -86,10 +86,12 @@ else static if (GNU_Thread_Model == ThreadModel.Single)
 }
 else static if (GNU_Thread_Model == ThreadModel.Win32)
 {
+    import core.stdc.config;
+
     struct __gthread_once_t
     {
-        INT done;
-        LONG started;
+        int done;
+        c_long started;
     }
 
     int __gthr_win32_key_create(__gthread_key_t* keyp, GthreadDestroyFn dtor);
diff --git a/libphobos/libdruntime/gcc/sections/package.d b/libphobos/libdruntime/gcc/sections/package.d
index fdaf039fcfa..5d76072af25 100644
--- a/libphobos/libdruntime/gcc/sections/package.d
+++ b/libphobos/libdruntime/gcc/sections/package.d
@@ -22,26 +22,20 @@
 
 module gcc.sections;
 
-version (CRuntime_Glibc)
-    public import gcc.sections.elf_shared;
-else version (CRuntime_Musl)
-    public import gcc.sections.elf_shared;
-else version (CRuntime_UClibc)
-    public import gcc.sections.elf_shared;
-else version (FreeBSD)
-    public import gcc.sections.elf_shared;
-else version (NetBSD)
-    public import gcc.sections.elf_shared;
-else version (DragonFlyBSD)
-    public import gcc.sections.elf_shared;
-else version (Solaris)
+version (CRuntime_Glibc)  version = ElfShared;
+version (CRuntime_Musl)   version = ElfShared;
+version (CRuntime_UClibc) version = ElfShared;
+version (FreeBSD)         version = ElfShared;
+version (NetBSD)          version = ElfShared;
+version (DragonFlyBSD)    version = ElfShared;
+version (Solaris)         version = ElfShared;
+
+version (ElfShared)
     public import gcc.sections.elf_shared;
 else version (OSX)
     public import gcc.sections.osx;
-else version (CRuntime_DigitalMars)
-    public import gcc.sections.win32;
-else version (CRuntime_Microsoft)
-    public import gcc.sections.win64;
+else version (Windows)
+    public import gcc.sections.pecoff;
 else version (CRuntime_Bionic)
     public import gcc.sections.android;
 else
diff --git a/libphobos/libdruntime/gcc/sections/pecoff.d b/libphobos/libdruntime/gcc/sections/pecoff.d
new file mode 100644
index 00000000000..5fa1df2ac54
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/pecoff.d
@@ -0,0 +1,830 @@
+// PE/COFF-specific support for sections.
+// Copyright (C) 2021 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.pecoff;
+
+version (Windows):
+
+import core.memory;
+import core.stdc.stdlib;
+import core.sys.windows.winbase;
+import core.sys.windows.windef;
+import core.sys.windows.winnt;
+import rt.minfo;
+import rt.util.container.array;
+import rt.util.container.hashtab;
+
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+/****
+ * Asserts the specified condition, independent from -release, by abort()ing.
+ * Regular assertions throw an AssertError and thus require an initialized
+ * GC, which isn't the case (yet or anymore) for the startup/shutdown code in
+ * this module (called by CRT ctors/dtors etc.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+alias DSO SectionGroup;
+struct DSO
+{
+    static int opApply(scope int delegate(ref DSO) dg)
+    {
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
+    {
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+
+    invariant()
+    {
+        safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO.");
+    }
+
+    void** _slot;
+    ModuleGroup _moduleGroup;
+    Array!(void[]) _gcRanges;
+
+    version (Shared)
+    {
+        Array!(void[]) _codeSegments; // array of code segments
+        Array!(DSO*) _deps; // D libraries needed by this DSO
+        void* _handle; // corresponding handle
+    }
+}
+
+/****
+ * Boolean flag set to true while the runtime is initialized.
+ */
+__gshared bool _isRuntimeInitialized;
+
+/****
+ * Gets called on program startup just before GC is initialized.
+ */
+void initSections() nothrow @nogc
+{
+    _isRuntimeInitialized = true;
+}
+
+/***
+ * Gets called on program shutdown just after GC is terminated.
+ */
+void finiSections() nothrow @nogc
+{
+    _isRuntimeInitialized = false;
+}
+
+alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
+
+version (Shared)
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(ThreadDSO)* initTLSRanges() @nogc nothrow
+    {
+        return &_loadedDSOs();
+    }
+
+    void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow
+    {
+        // Nothing to do here. tdsos used to point to the _loadedDSOs instance
+        // in the dying thread's TLS segment and as such is not valid anymore.
+        // The memory for the array contents was already reclaimed in
+        // cleanupLoadedLibraries().
+    }
+
+    void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
+
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof);
+        res.length = _loadedDSOs.length;
+        foreach (i, ref tdso; _loadedDSOs)
+        {
+            (*res)[i] = tdso;
+            if (tdso._addCnt)
+            {
+                // Increment the DLL ref for explicitly loaded libraries to pin them.
+                char[MAX_PATH] buf;
+                char[] buffer = buf[];
+                const success = .LoadLibraryA(nameForDSO(tdso._pdso, buffer)) !is null;
+                safeAssert(success, "Failed to increment DLL ref.");
+                (*res)[i]._addCnt = 1; // new array takes over the additional ref count
+            }
+        }
+        return res;
+    }
+
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+        auto pary = cast(Array!(ThreadDSO)*)p;
+        // In case something failed we need to undo the pinning.
+        foreach (ref tdso; *pary)
+        {
+            if (tdso._addCnt)
+            {
+                auto handle = tdso._pdso._handle;
+                safeAssert(handle !is null, "Invalid library handle.");
+                .FreeLibrary(handle);
+            }
+        }
+        pary.reset();
+        .free(pary);
+    }
+
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
+    {
+        safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread.");
+        _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p);
+        .free(p);
+    }
+
+    // Called after all TLS dtors ran, decrements all remaining DLL refs.
+    void cleanupLoadedLibraries() nothrow @nogc
+    {
+        foreach (ref tdso; _loadedDSOs)
+        {
+            if (tdso._addCnt == 0) continue;
+
+            auto handle = tdso._pdso._handle;
+            safeAssert(handle !is null, "Invalid DSO handle.");
+            for (; tdso._addCnt > 0; --tdso._addCnt)
+                .FreeLibrary(handle);
+        }
+
+        // Free the memory for the array contents.
+        _loadedDSOs.reset();
+    }
+}
+else
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(void[])* initTLSRanges() nothrow @nogc
+    {
+        return null;
+    }
+
+    void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc
+    {
+    }
+
+    void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
+}
+
+private:
+
+version (Shared)
+{
+    /*
+     * Array of thread local DSO metadata for all libraries loaded and
+     * initialized in this thread.
+     *
+     * Note:
+     *     A newly spawned thread will inherit these libraries.
+     * Note:
+     *     We use an array here to preserve the order of
+     *     initialization.  If that became a performance issue, we
+     *     could use a hash table and enumerate the DSOs during
+     *     loading so that the hash table values could be sorted when
+     *     necessary.
+     */
+    struct ThreadDSO
+    {
+        DSO* _pdso;
+        static if (_pdso.sizeof == 8) uint _refCnt, _addCnt;
+        else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt;
+        else static assert(0, "unimplemented");
+        alias _pdso this;
+    }
+
+    @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow
+    {
+        static Array!(ThreadDSO) x;
+        return x;
+    }
+
+    /*
+     * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+     */
+    bool _rtLoading;
+
+    /*
+     * Hash table to map the native handle (as returned by dlopen)
+     * to the corresponding DSO*, protected by a mutex.
+     */
+    __gshared CRITICAL_SECTION _handleToDSOMutex;
+    @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow
+    {
+        __gshared HashTab!(void*, DSO*) x;
+        return x;
+    }
+}
+else
+{
+    /*
+     * Static DSOs loaded by the runtime linker. This includes the
+     * executable. These can't be unloaded.
+     */
+    @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
+    {
+        __gshared Array!(DSO*) x;
+        return x;
+    }
+
+    enum _rtLoading = false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
+
+/****
+ * This data structure is generated by the compiler, and then passed to
+ * _d_dso_registry().
+ */
+struct CompilerDSOData
+{
+    size_t _version;                                       // currently 1
+    void** _slot;                                          // can be used to store runtime data
+    immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file
+}
+
+T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; }
+
+/* For each shared library and executable, the compiler generates code that
+ * sets up CompilerDSOData and calls _d_dso_registry().
+ * A pointer to that code is inserted into both the .ctors and .dtors
+ * segment so it gets called by the loader on startup and shutdown.
+ */
+extern(C) void _d_dso_registry(CompilerDSOData* data)
+{
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
+
+    // no backlink => register
+    if (*data._slot is null)
+    {
+        immutable firstDSO = _loadedDSOs.empty;
+        if (firstDSO) initLocks();
+
+        DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
+        assert(typeid(DSO).initializer().ptr is null);
+        pdso._slot = data._slot;
+        *data._slot = pdso; // store backlink in library record
+
+        pdso._moduleGroup = ModuleGroup(toRange(data._minfo_beg, data._minfo_end));
+
+        HMODULE handle = void;
+        const moduleFound = findModuleHandleForAddr(data._slot, handle);
+        safeAssert(moduleFound, "Failed to find image header.");
+
+        scanSegments(handle, pdso);
+
+        version (Shared)
+        {
+            getDependencies(handle, pdso._deps);
+            pdso._handle = handle;
+            setDSOForHandle(pdso, pdso._handle);
+
+            if (!_rtLoading)
+            {
+                /* This DSO was not loaded by rt_loadLibrary which
+                 * happens for all dependencies of an executable or
+                 * the first dlopen call from a C program.
+                 * In this case we add the DSO to the _loadedDSOs of this
+                 * thread with a refCnt of 1 and call the TlsCtors.
+                 */
+                immutable ushort refCnt = 1, addCnt = 0;
+                _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            }
+        }
+        else
+        {
+            foreach (p; _loadedDSOs)
+                safeAssert(p !is pdso, "DSO already registered.");
+            _loadedDSOs.insertBack(pdso);
+        }
+
+        // don't initialize modules before rt_init was called
+        if (_isRuntimeInitialized)
+        {
+            registerGCRanges(pdso);
+            // rt_loadLibrary will run tls ctors, so do this only for dlopen
+            immutable runTlsCtors = !_rtLoading;
+            runModuleConstructors(pdso, runTlsCtors);
+        }
+    }
+    // has backlink => unregister
+    else
+    {
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
+
+        // don't finalizes modules after rt_term was called (see Bugzilla 11378)
+        if (_isRuntimeInitialized)
+        {
+            // rt_unloadLibrary already ran tls dtors, so do this only for dlclose
+            immutable runTlsDtors = !_rtLoading;
+            runModuleDestructors(pdso, runTlsDtors);
+            unregisterGCRanges(pdso);
+            // run finalizers after module dtors (same order as in rt_term)
+            version (Shared) runFinalizers(pdso);
+        }
+
+        version (Shared)
+        {
+            if (!_rtLoading)
+            {
+                /* This DSO was not unloaded by rt_unloadLibrary so we
+                 * have to remove it from _loadedDSOs here.
+                 */
+                foreach (i, ref tdso; _loadedDSOs)
+                {
+                    if (tdso._pdso == pdso)
+                    {
+                        _loadedDSOs.remove(i);
+                        break;
+                    }
+                }
+            }
+
+            unsetDSOForHandle(pdso, pdso._handle);
+        }
+        else
+        {
+            // static DSOs are unloaded in reverse order
+            safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+            _loadedDSOs.popBack();
+        }
+
+        freeDSO(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+            version (Shared)
+            {
+                safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs.");
+                _handleToDSO.reset();
+            }
+            finiLocks();
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// dynamic loading
+///////////////////////////////////////////////////////////////////////////////
+
+// Shared D libraries are only supported when linking against a shared druntime library.
+
+version (Shared)
+{
+    ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc
+    {
+        foreach (ref tdata; _loadedDSOs)
+            if (tdata._pdso == pdso) return &tdata;
+        return null;
+    }
+
+    void incThreadRef(DSO* pdso, bool incAdd)
+    {
+        if (auto tdata = findThreadDSO(pdso)) // already initialized
+        {
+            if (incAdd && ++tdata._addCnt > 1) return;
+            ++tdata._refCnt;
+        }
+        else
+        {
+            foreach (dep; pdso._deps)
+                incThreadRef(dep, false);
+            immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
+            _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            pdso._moduleGroup.runTlsCtors();
+        }
+    }
+
+    void decThreadRef(DSO* pdso, bool decAdd)
+    {
+        auto tdata = findThreadDSO(pdso);
+        safeAssert(tdata !is null, "Failed to find thread DSO.");
+        safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call.");
+
+        if (decAdd && --tdata._addCnt > 0) return;
+        if (--tdata._refCnt > 0) return;
+
+        pdso._moduleGroup.runTlsDtors();
+        foreach (i, ref td; _loadedDSOs)
+            if (td._pdso == pdso) _loadedDSOs.remove(i);
+        foreach (dep; pdso._deps)
+            decThreadRef(dep, false);
+    }
+}
+
+/***********************************
+ * These are a temporary means of providing a GC hook for DLL use.  They may be
+ * replaced with some other similar functionality later.
+ */
+extern (C)
+{
+    void* gc_getProxy();
+    void  gc_setProxy(void* p);
+    void  gc_clrProxy();
+
+    alias void  function(void*) gcSetFn;
+    alias void  function()      gcClrFn;
+}
+
+/*******************************************
+ * Loads a DLL written in D with the name 'name'.
+ * Returns:
+ *      opaque handle to the DLL if successfully loaded
+ *      null if failure
+ */
+extern(C) void* rt_loadLibrary(const char* name)
+{
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+    }
+    return initLibrary(.LoadLibraryA(name));
+}
+
+extern (C) void* rt_loadLibraryW(const wchar_t* name)
+{
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+    }
+    return initLibrary(.LoadLibraryW(name));
+}
+
+void* initLibrary(void* handle)
+{
+    if (handle is null)
+        return null;
+
+    version (Shared)
+    {
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            incThreadRef(pdso, true);
+    }
+    gcSetFn gcSet = cast(gcSetFn) GetProcAddress(handle, "gc_setProxy");
+    if (gcSet !is null)
+    {
+        // BUG: Set proxy, but too late
+        gcSet(gc_getProxy());
+    }
+    return handle;
+}
+
+/*************************************
+ * Unloads DLL that was previously loaded by rt_loadLibrary().
+ * Input:
+ *      handle  the handle returned by rt_loadLibrary()
+ * Returns:
+ *      1   succeeded
+ *      0   some failure happened
+ */
+extern(C) int rt_unloadLibrary(void* handle)
+{
+    if (handle is null)
+        return false;
+
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            decThreadRef(pdso, true);
+    }
+    gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(handle, "gc_clrProxy");
+    if (gcClr !is null)
+        gcClr();
+    return .FreeLibrary(handle) != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// helper functions
+///////////////////////////////////////////////////////////////////////////////
+
+void initLocks() nothrow @nogc
+{
+    version (Shared)
+        InitializeCriticalSection(&_handleToDSOMutex);
+}
+
+void finiLocks() nothrow @nogc
+{
+    version (Shared)
+        DeleteCriticalSection(&_handleToDSOMutex);
+}
+
+void runModuleConstructors(DSO* pdso, bool runTlsCtors)
+{
+    pdso._moduleGroup.sortCtors();
+    pdso._moduleGroup.runCtors();
+    if (runTlsCtors) pdso._moduleGroup.runTlsCtors();
+}
+
+void runModuleDestructors(DSO* pdso, bool runTlsDtors)
+{
+    if (runTlsDtors) pdso._moduleGroup.runTlsDtors();
+    pdso._moduleGroup.runDtors();
+}
+
+void registerGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.addRange(rng.ptr, rng.length);
+}
+
+void unregisterGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.removeRange(rng.ptr);
+}
+
+version (Shared) void runFinalizers(DSO* pdso)
+{
+    foreach (seg; pdso._codeSegments)
+        GC.runFinalizers(seg);
+}
+
+void freeDSO(DSO* pdso) nothrow @nogc
+{
+    pdso._gcRanges.reset();
+    version (Shared)
+    {
+        pdso._codeSegments.reset();
+        pdso._deps.reset();
+        pdso._handle = null;
+    }
+    .free(pdso);
+}
+
+version (Shared)
+{
+@nogc nothrow:
+    const(char)* nameForDSO(DSO* pdso, ref char[] buffer)
+    {
+        const success = GetModuleFileNameA(pdso._handle, buffer.ptr, cast(DWORD)buffer.length) != 0;
+        safeAssert(success, "Failed to get DLL name.");
+        return buffer.ptr;
+    }
+
+    DSO* dsoForHandle(in void* handle)
+    {
+        DSO* pdso;
+        .EnterCriticalSection(&_handleToDSOMutex);
+        if (auto ppdso = handle in _handleToDSO)
+            pdso = *ppdso;
+        .LeaveCriticalSection(&_handleToDSOMutex);
+        return pdso;
+    }
+
+    void setDSOForHandle(DSO* pdso, void* handle)
+    {
+        .EnterCriticalSection(&_handleToDSOMutex);
+        safeAssert(handle !in _handleToDSO, "DSO already registered.");
+        _handleToDSO[handle] = pdso;
+        .LeaveCriticalSection(&_handleToDSOMutex);
+    }
+
+    void unsetDSOForHandle(DSO* pdso, void* handle)
+    {
+        .EnterCriticalSection(&_handleToDSOMutex);
+        safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO.");
+        _handleToDSO.remove(handle);
+        .LeaveCriticalSection(&_handleToDSOMutex);
+    }
+
+    void getDependencies(in HMODULE handle, ref Array!(DSO*) deps)
+    {
+        auto nthdr = getNTHeader(handle);
+        auto import_entry = nthdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+        auto addr = import_entry.VirtualAddress;
+        auto datasize = import_entry.Size;
+
+        if (addr == 0 && datasize == 0)
+        {
+            // Maybe the optional header isn't there, look for the section.
+            foreach (section; getSectionHeader(handle))
+            {
+                if (!compareSectionName(section, ".idata"))
+                    continue;
+                addr = section.VirtualAddress;
+                datasize = section.Misc.VirtualSize;
+                break;
+            }
+            if (datasize == 0)
+                return;
+        }
+        else
+        {
+            bool foundSection = false;
+            foreach (section; getSectionHeader(handle))
+            {
+                if (!compareSectionName(section, ".idata"))
+                    continue;
+                // Section containing import table has no contents.
+                if (section.Misc.VirtualSize == 0)
+                    return;
+                foundSection = true;
+                break;
+            }
+            // There is an import table, but the section containing it could not be found
+            if (!foundSection)
+                return;
+        }
+
+        // Get the names of each DLL
+        for (uint i = 0; i + IMAGE_IMPORT_DESCRIPTOR.sizeof <= datasize;
+             i += IMAGE_IMPORT_DESCRIPTOR.sizeof)
+        {
+            const data = cast(PIMAGE_IMPORT_DESCRIPTOR)(handle + addr + i);
+            if (data.Name == 0)
+                break;
+
+            // dll name of dependency
+            auto name = cast(char*)(handle + data.Name);
+            // get handle without loading the library
+            auto libhandle = handleForName(name);
+            // the runtime linker has already loaded all dependencies
+            safeAssert(handle !is null, "Failed to get library handle.");
+            // if it's a D library
+            if (auto pdso = dsoForHandle(handle))
+                deps.insertBack(pdso); // append it to the dependencies
+        }
+    }
+
+    void* handleForName(const char* name)
+    {
+        return GetModuleHandleA(name);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PE/COFF program header iteration
+///////////////////////////////////////////////////////////////////////////////
+
+bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc
+{
+    if (name[] != cast(char[])section.Name[0 .. name.length])
+        return false;
+    return name.length == 8 || section.Name[name.length] == 0;
+}
+
+/************
+ * Scan segments in the image header and store
+ * the writeable data segments in *pdso.
+ */
+
+void scanSegments(in HMODULE handle, DSO* pdso) nothrow @nogc
+{
+    foreach (section; getSectionHeader(handle))
+    {
+        // the ".data" image section includes both object file sections ".data" and ".bss"
+        if (compareSectionName(section, ".data"))
+        {
+            auto data = cast(void*)handle + section.VirtualAddress;
+            pdso._gcRanges.insertBack(data[0 .. section.Misc.VirtualSize]);
+            continue;
+        }
+
+        version (Shared)
+        {
+            if (compareSectionName(section, ".text"))
+            {
+                auto text = cast(void*)handle + section.VirtualAddress;
+                pdso._codeSegments.insertBack(text[0 .. section.Misc.VirtualSize]);
+                continue;
+            }
+        }
+    }
+}
+
+/**************************
+ * Input:
+ *      handle  where the output is to be written
+ * Returns:
+ *      true if found, and *handle is filled in
+ */
+
+bool findModuleHandleForAddr(in void* addr, out HMODULE handle) nothrow @nogc
+{
+    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+                           cast(const(wchar)*) addr, &handle))
+        return true;
+
+    return false;
+}
+
+/**
+ * Returns the image NT header for the HMODULE handle passed,
+ * or null if not found.
+ */
+PIMAGE_NT_HEADERS getNTHeader(in HMODULE handle) nothrow @nogc
+{
+    auto doshdr = cast(PIMAGE_DOS_HEADER)handle;
+    if (doshdr.e_magic != IMAGE_DOS_SIGNATURE)
+        return null;
+
+    return cast(typeof(return))(cast(void*)doshdr + doshdr.e_lfanew);
+}
+
+/**
+ * Returns the image section header for the HMODULE handle passed,
+ * or null if not found.
+ */
+IMAGE_SECTION_HEADER[] getSectionHeader(in HMODULE handle) nothrow @nogc
+{
+    if (auto nthdr = getNTHeader(handle))
+    {
+        const void* opthdr = &nthdr.OptionalHeader;
+        const offset = nthdr.FileHeader.SizeOfOptionalHeader;
+        const length = nthdr.FileHeader.NumberOfSections;
+        return (cast(PIMAGE_SECTION_HEADER)(opthdr + offset))[0 .. length];
+    }
+    return null;
+}
diff --git a/libphobos/libdruntime/gcc/sections/win32.d b/libphobos/libdruntime/gcc/sections/win32.d
deleted file mode 100644
index b355dfc5068..00000000000
--- a/libphobos/libdruntime/gcc/sections/win32.d
+++ /dev/null
@@ -1,183 +0,0 @@
-// Win32-specific support for sections.
-// Copyright (C) 2019-2021 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.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-module gcc.sections.win32;
-
-version (CRuntime_DigitalMars):
-
-// debug = PRINTF;
-debug(PRINTF) import core.stdc.stdio;
-import rt.minfo;
-import core.stdc.stdlib : malloc, free;
-
-struct SectionGroup
-{
-    static int opApply(scope int delegate(ref SectionGroup) dg)
-    {
-        return dg(_sections);
-    }
-
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
-    {
-        return dg(_sections);
-    }
-
-    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-    ModuleGroup _moduleGroup;
-    void[][] _gcRanges;
-}
-
-shared(bool) conservative;
-
-void initSections() nothrow @nogc
-{
-    _sections._moduleGroup = ModuleGroup(getModuleInfos());
-
-    import rt.sections;
-    conservative = !scanDataSegPrecisely();
-
-    if (conservative)
-    {
-        _sections._gcRanges = (cast(void[]*) malloc(2 * (void[]).sizeof))[0..2];
-
-        auto databeg = cast(void*)&_xi_a;
-        auto dataend = cast(void*)_moduleinfo_array.ptr;
-        _sections._gcRanges[0] = databeg[0 .. dataend - databeg];
-
-        // skip module info and CONST segment
-        auto bssbeg = cast(void*)&_edata;
-        auto bssend = cast(void*)&_end;
-        _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg];
-    }
-    else
-    {
-        size_t count = &_DPend - &_DPbegin;
-        auto ranges = cast(void[]*) malloc(count * (void[]).sizeof);
-        size_t r = 0;
-        void* prev = null;
-        for (size_t i = 0; i < count; i++)
-        {
-            void* addr = (&_DPbegin)[i];
-            if (prev + (void*).sizeof == addr)
-                ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof];
-            else
-                ranges[r++] = (cast(void**)addr)[0..1];
-            prev = addr;
-        }
-        _sections._gcRanges = ranges[0..r];
-    }
-}
-
-void finiSections() nothrow @nogc
-{
-    free(_sections._gcRanges.ptr);
-}
-
-void[] initTLSRanges() nothrow @nogc
-{
-    auto pbeg = cast(void*)&_tlsstart;
-    auto pend = cast(void*)&_tlsend;
-    return pbeg[0 .. pend - pbeg];
-}
-
-void finiTLSRanges(void[] rng) nothrow @nogc
-{
-}
-
-void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    if (conservative)
-    {
-        dg(rng.ptr, rng.ptr + rng.length);
-    }
-    else
-    {
-        for (auto p = &_TPbegin; p < &_TPend; )
-        {
-            uint beg = *p++;
-            uint end = beg + cast(uint)((void*).sizeof);
-            while (p < &_TPend && *p == end)
-            {
-                end += (void*).sizeof;
-                p++;
-            }
-            dg(rng.ptr + beg, rng.ptr + end);
-        }
-    }
-}
-
-private:
-
-__gshared SectionGroup _sections;
-
-// Windows: this gets initialized by minit.asm
-extern(C) __gshared immutable(ModuleInfo*)[] _moduleinfo_array;
-extern(C) void _minit() nothrow @nogc;
-
-immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc
-out (result)
-{
-    foreach (m; result)
-        assert(m !is null);
-}
-body
-{
-    // _minit directly alters the global _moduleinfo_array
-    _minit();
-    return _moduleinfo_array;
-}
-
-extern(C)
-{
-    extern __gshared
-    {
-        int _xi_a;      // &_xi_a just happens to be start of data segment
-        int _edata;     // &_edata is start of BSS segment
-        int _end;       // &_end is past end of BSS
-
-        void* _DPbegin; // first entry in the array of pointers addresses
-        void* _DPend;   // &_DPend points after last entry of array
-        uint _TPbegin;  // first entry in the array of TLS offsets of pointers
-        uint _TPend;    // &_DPend points after last entry of array
-    }
-
-    extern
-    {
-        int _tlsstart;
-        int _tlsend;
-    }
-}
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         return _moduleGroup;
     }
 
-    version (Win64)
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        auto pbeg = cast(immutable(FuncTable)*)&_deh_beg;
-        auto pend = cast(immutable(FuncTable)*)&_deh_end;
-        return pbeg[0 .. pend - pbeg];
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
diff --git a/libphobos/libdruntime/gcc/unwind/generic.d b/libphobos/libdruntime/gcc/unwind/generic.d
index 5315739f82f..592b3afcb71 100644
--- a/libphobos/libdruntime/gcc/unwind/generic.d
+++ b/libphobos/libdruntime/gcc/unwind/generic.d
@@ -269,6 +269,6 @@ version (GNU_SEH_Exceptions)
         ExceptionCollidedUnwind
     }
 
-    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*,
+    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, void*,
                                                           _Unwind_Personality_Fn);
 }
diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d
index 3d5ba299863..e4a2c6571d4 100644
--- a/libphobos/libdruntime/rt/dmain2.d
+++ b/libphobos/libdruntime/rt/dmain2.d
@@ -70,70 +70,6 @@ version (CRuntime_Microsoft)
     extern(C) void init_msvc();
 }
 
-/***********************************
- * These are a temporary means of providing a GC hook for DLL use.  They may be
- * replaced with some other similar functionality later.
- */
-extern (C)
-{
-    void* gc_getProxy();
-    void  gc_setProxy(void* p);
-    void  gc_clrProxy();
-
-    alias void* function()      gcGetFn;
-    alias void  function(void*) gcSetFn;
-    alias void  function()      gcClrFn;
-}
-
-version (Windows)
-{
-    /*******************************************
-     * Loads a DLL written in D with the name 'name'.
-     * Returns:
-     *      opaque handle to the DLL if successfully loaded
-     *      null if failure
-     */
-    extern (C) void* rt_loadLibrary(const char* name)
-    {
-        return initLibrary(.LoadLibraryA(name));
-    }
-
-    extern (C) void* rt_loadLibraryW(const wchar_t* name)
-    {
-        return initLibrary(.LoadLibraryW(name));
-    }
-
-    void* initLibrary(void* mod)
-    {
-        // BUG: LoadLibrary() call calls rt_init(), which fails if proxy is not set!
-        // (What? LoadLibrary() is a Windows API call, it shouldn't call rt_init().)
-        if (mod is null)
-            return mod;
-        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(mod, "gc_setProxy");
-        if (gcSet !is null)
-        {   // BUG: Set proxy, but too late
-            gcSet(gc_getProxy());
-        }
-        return mod;
-    }
-
-    /*************************************
-     * Unloads DLL that was previously loaded by rt_loadLibrary().
-     * Input:
-     *      ptr     the handle returned by rt_loadLibrary()
-     * Returns:
-     *      1   succeeded
-     *      0   some failure happened
-     */
-    extern (C) int rt_unloadLibrary(void* ptr)
-    {
-        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
-        if (gcClr !is null)
-            gcClr();
-        return FreeLibrary(ptr) != 0;
-    }
-}
-
 /* To get out-of-band access to the args[] passed to main().
  */
 
diff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am
index 2de8ab951b4..0dc2a2625a9 100644
--- a/libphobos/src/Makefile.am
+++ b/libphobos/src/Makefile.am
@@ -24,7 +24,7 @@ D_EXTRA_DFLAGS=-nostdinc -I $(srcdir) \
 
 # D flags for compilation
 AM_DFLAGS= \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 # Flags for other kinds of sources
diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in
index 2e721783d06..33453517153 100644
--- a/libphobos/src/Makefile.in
+++ b/libphobos/src/Makefile.in
@@ -414,6 +414,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -443,6 +445,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
@@ -477,7 +480,7 @@ D_EXTRA_DFLAGS = -nostdinc -I $(srcdir) \
 
 # D flags for compilation
 AM_DFLAGS = \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 
diff --git a/libphobos/testsuite/Makefile.in b/libphobos/testsuite/Makefile.in
index c38a4688258..51eb4efc79d 100644
--- a/libphobos/testsuite/Makefile.in
+++ b/libphobos/testsuite/Makefile.in
@@ -242,6 +242,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -271,6 +273,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [gcc(refs/users/ibuclaw/heads/mingw)] More MSVC support
@ 2021-03-24 16:06 Iain Buclaw
  0 siblings, 0 replies; 5+ messages in thread
From: Iain Buclaw @ 2021-03-24 16:06 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:867af327bc497d39e3b26f19685ee7cf7a669d25

commit 867af327bc497d39e3b26f19685ee7cf7a669d25
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Wed Mar 24 16:24:04 2021 +0100

    More MSVC support

Diff:
---
 gcc/config/aarch64/aarch64-d.c                     |   2 +
 gcc/config/arm/arm-d.c                             |   2 +
 gcc/config/i386/cygming.h                          |   2 +
 gcc/config/i386/i386-d.c                           |  13 +
 gcc/config/i386/i386-protos.h                      |   1 +
 gcc/config/i386/i386.h                             |   3 +-
 gcc/config/i386/winnt-d.c                          |   7 +
 gcc/config/mips/mips-d.c                           |   2 +
 gcc/config/pa/pa-d.c                               |   2 +
 gcc/config/riscv/riscv-d.c                         |   2 +
 gcc/config/rs6000/rs6000-d.c                       |   2 +
 gcc/config/s390/s390-d.c                           |   2 +
 gcc/config/sparc/sparc-d.c                         |   2 +
 gcc/d/d-target.cc                                  |   5 +-
 gcc/d/d-target.def                                 |  10 +
 gcc/doc/tm.texi                                    |   7 +
 gcc/doc/tm.texi.in                                 |   2 +
 libphobos/Makefile.in                              |   3 +
 libphobos/configure                                |  24 +-
 libphobos/configure.ac                             |  17 +-
 libphobos/libdruntime/Makefile.am                  |   7 +-
 libphobos/libdruntime/Makefile.in                  |  68 +-
 libphobos/libdruntime/config/mingw/msvc.c          |  54 ++
 libphobos/libdruntime/config/mingw/switchcontext.S |  12 +-
 libphobos/libdruntime/core/stdc/stdlib.d           |  27 +-
 libphobos/libdruntime/core/stdc/tgmath.d           |  11 +-
 libphobos/libdruntime/core/sys/windows/com.d       |   4 +-
 libphobos/libdruntime/core/sys/windows/dbghelp.d   |   2 +-
 libphobos/libdruntime/core/sys/windows/dll.d       |  12 +-
 libphobos/libdruntime/core/thread/osthread.d       |   4 +-
 libphobos/libdruntime/gcc/deh.d                    |   2 +-
 libphobos/libdruntime/gcc/gthread.d                |   6 +-
 libphobos/libdruntime/gcc/sections/package.d       |  28 +-
 libphobos/libdruntime/gcc/sections/pecoff.d        | 830 +++++++++++++++++++++
 libphobos/libdruntime/gcc/sections/win32.d         | 183 -----
 libphobos/libdruntime/gcc/sections/win64.d         |   8 -
 libphobos/libdruntime/gcc/unwind/generic.d         |   2 +-
 libphobos/libdruntime/rt/dmain2.d                  |  64 --
 libphobos/src/Makefile.am                          |   2 +-
 libphobos/src/Makefile.in                          |   5 +-
 libphobos/testsuite/Makefile.in                    |   3 +
 41 files changed, 1085 insertions(+), 359 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-d.c b/gcc/config/aarch64/aarch64-d.c
index 5c9b4fa6fb8..4fce593ac27 100644
--- a/gcc/config/aarch64/aarch64-d.c
+++ b/gcc/config/aarch64/aarch64-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c
index 76ede3b6d44..2cb9f4bd899 100644
--- a/gcc/config/arm/arm-d.c
+++ b/gcc/config/arm/arm-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index cfbca34f996..59eb812c1cf 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -209,6 +209,8 @@ along with GCC; see the file COPYING3.  If not see
 #define SUBTARGET_OVERRIDE_OPTIONS					\
 do {									\
   flag_pic = TARGET_64BIT ? 1 : 0;                                      \
+  if (!global_options_set.x_dwarf_version)				\
+    dwarf_version = 4;							\
 } while (0)
 
 /* Define this macro if references to a symbol must be treated
diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c
index cbd3ceb187d..34f53ba046d 100644
--- a/gcc/config/i386/i386-d.c
+++ b/gcc/config/i386/i386-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -42,3 +44,14 @@ ix86_d_target_versions (void)
   else
     d_add_builtin_version ("D_SoftFloat");
 }
+
+/* Implement TARGET_D_EXTERN_SYSTEM_LINKAGE for x86 targets.  */
+
+int
+ix86_d_extern_system_linkage (void)
+{
+  if (ix86_abi == MS_ABI)
+    return LINKwindows;
+
+  return LINKc;
+}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 9f8a69ea7dc..d07bf09bc65 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void);
 
 /* In i386-d.c  */
 extern void ix86_d_target_versions (void);
+extern int ix86_d_extern_system_linkage (void);
 
 /* In winnt.c  */
 extern void i386_pe_unique_section (tree, int);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 058c1cc25b2..10954fb0aab 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -799,8 +799,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 /* Target Pragmas.  */
 #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas ()
 
-/* Target CPU versions for D.  */
+/* Target hooks for D language.  */
 #define TARGET_D_CPU_VERSIONS ix86_d_target_versions
+#define TARGET_D_EXTERN_SYSTEM_LINKAGE ix86_d_extern_system_linkage
 
 #ifndef CC1_SPEC
 #define CC1_SPEC "%(cc1_cpu) "
diff --git a/gcc/config/i386/winnt-d.c b/gcc/config/i386/winnt-d.c
index 3b5791a7bff..d05ea8a92bf 100644
--- a/gcc/config/i386/winnt-d.c
+++ b/gcc/config/i386/winnt-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -30,6 +32,11 @@ winnt_d_os_builtins (void)
 {
   d_add_builtin_version ("Windows");
 
+  if (ix86_abi == SYSV_ABI)
+    d_add_builtin_version ("SYSV_ABI");
+  else
+    d_add_builtin_version ("MS_ABI");
+
 #define builtin_version(TXT) d_add_builtin_version (TXT)
 
 #ifdef EXTRA_TARGET_D_OS_VERSIONS
diff --git a/gcc/config/mips/mips-d.c b/gcc/config/mips/mips-d.c
index dad101cf7eb..dc57127791c 100644
--- a/gcc/config/mips/mips-d.c
+++ b/gcc/config/mips/mips-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/pa/pa-d.c b/gcc/config/pa/pa-d.c
index 1de49df12cc..663e749995a 100644
--- a/gcc/config/pa/pa-d.c
+++ b/gcc/config/pa/pa-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/riscv/riscv-d.c b/gcc/config/riscv/riscv-d.c
index 2b690b18cfd..b20b778bd35 100644
--- a/gcc/config/riscv/riscv-d.c
+++ b/gcc/config/riscv/riscv-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/rs6000/rs6000-d.c b/gcc/config/rs6000/rs6000-d.c
index 14c4133f305..6bfe8130dd3 100644
--- a/gcc/config/rs6000/rs6000-d.c
+++ b/gcc/config/rs6000/rs6000-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/s390/s390-d.c b/gcc/config/s390/s390-d.c
index 155144ce7b8..2f945ebfa12 100644
--- a/gcc/config/s390/s390-d.c
+++ b/gcc/config/s390/s390-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/config/sparc/sparc-d.c b/gcc/config/sparc/sparc-d.c
index 186e965ae84..0eb663bb132 100644
--- a/gcc/config/sparc/sparc-d.c
+++ b/gcc/config/sparc/sparc-d.c
@@ -15,6 +15,8 @@ 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/>.  */
 
+#define IN_TARGET_CODE 1
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index d50fcef22e2..e95dd01b0ee 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -417,11 +417,14 @@ TargetCPP::fundamentalType (const Type *, bool &)
   return false;
 }
 
-/* Return the default system linkage for the target.  */
+/* Return the default `extern (System)` linkage for the target.  */
 
 LINK
 Target::systemLinkage (void)
 {
+  if (targetdm.d_extern_system_linkage)
+    return (LINK) targetdm.d_extern_system_linkage ();
+
   return LINKc;
 }
 
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index d1426a17e99..889299fffe4 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -46,6 +46,16 @@ relating to the target operating system.",
  void, (void),
  hook_void_void)
 
+/* */
+DEFHOOK
+(d_extern_system_linkage,
+ "If defined, this hook returns the extern linkage which should be applied\n\
+ for all declarations annotated with @code{extern(System)}.  Typically,\n\
+ @code{extern(System)} is the same as @code{extern(Windows)} on Microsoft\n\
+ Windows platforms, and @code{extern(C)} on other platforms.",
+ int, (void),
+ NULL)
+
 /* ModuleInfo section name and brackets.  */
 DEFHOOKPOD
 (d_minfo_section,
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b272fa4806d..76c9fe0d173 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10808,6 +10808,13 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions
 relating to the target operating system.
 @end deftypefn
 
+@deftypefn {D Target Hook} int TARGET_D_EXTERN_SYSTEM_LINKAGE (void)
+If defined, this hook returns the extern linkage which should be applied
+ for all declarations annotated with @code{extern(System)}.  Typically,
+ @code{extern(System)} is the same as @code{extern(Windows)} on Microsoft
+ Windows platforms, and @code{extern(C)} on other platforms.
+@end deftypefn
+
 @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION
 Contains the name of the section in which module info references should be
 placed.  This section is expected to be bracketed by two symbols to indicate
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index bf724dc093c..ef15417a791 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7357,6 +7357,8 @@ floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_OS_VERSIONS
 
+@hook TARGET_D_EXTERN_SYSTEM_LINKAGE
+
 @hook TARGET_D_MINFO_SECTION
 
 @hook TARGET_D_MINFO_START_NAME
diff --git a/libphobos/Makefile.in b/libphobos/Makefile.in
index d42248405a2..eab12688867 100644
--- a/libphobos/Makefile.in
+++ b/libphobos/Makefile.in
@@ -298,6 +298,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -327,6 +329,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
diff --git a/libphobos/configure b/libphobos/configure
index c940a404be4..59ca64aa1e0 100755
--- a/libphobos/configure
+++ b/libphobos/configure
@@ -705,6 +705,9 @@ libphobos_builddir
 get_gcc_base_ver
 phobos_compiler_shared_flag
 phobos_compiler_pic_flag
+phobos_lt_pic_flag
+enable_static
+enable_shared
 OTOOL64
 OTOOL
 LIPO
@@ -11746,7 +11749,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11749 "configure"
+#line 11752 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11852,7 +11855,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11855 "configure"
+#line 11858 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13997,8 +14000,14 @@ CFLAGS=$lt_save_CFLAGS
   GDCFLAGS=$gdc_save_DFLAGS
 
 
+
+
 # libtool variables for Phobos shared and position-independent compiles.
 #
+# Use phobos_lt_pic_flag to designate the automake variable
+# used to encapsulate the default libtool approach to creating objects
+# with position-independent code. Default: -prefer-pic.
+#
 # Use phobos_compiler_shared_flag to designate the compile-time flags for
 # creating shared objects. Default: -fversion=Shared.
 #
@@ -14010,26 +14019,23 @@ CFLAGS=$lt_save_CFLAGS
 # libtool, and so we make it here.  How it is handled is that in shared
 # compilations the `lt_prog_compiler_pic_D' variable is used to instead
 # ensure that conditional compilation of shared runtime code is compiled in.
-# The original PIC flags are then used in the compilation of every object.
-#
-# Why are objects destined for libgphobos.a compiled with -fPIC?
-# Because -fPIC is not harmful to use for objects destined for static
-# libraries. In addition, using -fPIC will allow the use of static
-# libgphobos.a in the creation of other D shared libraries.
 if test "$enable_shared" = yes; then
+  phobos_lt_pic_flag="-prefer-pic"
   phobos_compiler_pic_flag="$lt_prog_compiler_pic_D"
   phobos_compiler_shared_flag="-fversion=Shared"
 else
+  phobos_lt_pic_flag=
   phobos_compiler_pic_flag=
   phobos_compiler_shared_flag=
 fi
 
 
 
+
 # Override the libtool's pic_flag and pic_mode.
 # Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT.
 # NB: this impacts --with-pic and --without-pic.
-lt_prog_compiler_pic_D="$phobos_compiler_shared_flag"
+lt_prog_compiler_pic_D="$phobos_compiler_pic_flag $phobos_compiler_shared_flag"
 pic_mode='default'
 
 # Determine what GCC version number to use in filesystem paths.
diff --git a/libphobos/configure.ac b/libphobos/configure.ac
index cc9af29754f..248d0ebbc19 100644
--- a/libphobos/configure.ac
+++ b/libphobos/configure.ac
@@ -91,9 +91,15 @@ AC_SUBST(CFLAGS_FOR_BUILD)
 LT_INIT(dlopen)
 AM_PROG_LIBTOOL
 WITH_LOCAL_DRUNTIME([LT_LANG([D])], [])
+AC_SUBST(enable_shared)
+AC_SUBST(enable_static)
 
 # libtool variables for Phobos shared and position-independent compiles.
 #
+# Use phobos_lt_pic_flag to designate the automake variable
+# used to encapsulate the default libtool approach to creating objects
+# with position-independent code. Default: -prefer-pic.
+#
 # Use phobos_compiler_shared_flag to designate the compile-time flags for
 # creating shared objects. Default: -fversion=Shared.
 #
@@ -105,26 +111,23 @@ WITH_LOCAL_DRUNTIME([LT_LANG([D])], [])
 # libtool, and so we make it here.  How it is handled is that in shared
 # compilations the `lt_prog_compiler_pic_D' variable is used to instead
 # ensure that conditional compilation of shared runtime code is compiled in.
-# The original PIC flags are then used in the compilation of every object.
-#
-# Why are objects destined for libgphobos.a compiled with -fPIC?
-# Because -fPIC is not harmful to use for objects destined for static
-# libraries. In addition, using -fPIC will allow the use of static
-# libgphobos.a in the creation of other D shared libraries.
 if test "$enable_shared" = yes; then
+  phobos_lt_pic_flag="-prefer-pic"
   phobos_compiler_pic_flag="$lt_prog_compiler_pic_D"
   phobos_compiler_shared_flag="-fversion=Shared"
 else
+  phobos_lt_pic_flag=
   phobos_compiler_pic_flag=
   phobos_compiler_shared_flag=
 fi
+AC_SUBST(phobos_lt_pic_flag)
 AC_SUBST(phobos_compiler_pic_flag)
 AC_SUBST(phobos_compiler_shared_flag)
 
 # Override the libtool's pic_flag and pic_mode.
 # Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT.
 # NB: this impacts --with-pic and --without-pic.
-lt_prog_compiler_pic_D="$phobos_compiler_shared_flag"
+lt_prog_compiler_pic_D="$phobos_compiler_pic_flag $phobos_compiler_shared_flag"
 pic_mode='default'
 
 # Determine what GCC version number to use in filesystem paths.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 945271e028f..bedd7a325ec 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -23,7 +23,7 @@ D_EXTRA_DFLAGS=-nostdinc -I $(srcdir) -I .
 
 # D flags for compilation
 AM_DFLAGS= \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 # Flags for other kinds of sources
@@ -69,7 +69,8 @@ if DRUNTIME_OS_LINUX
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_LINUX)
 endif
 if DRUNTIME_OS_MINGW
-    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS)
+    DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS) \
+				   config/mingw/msvc.c
 endif
 if DRUNTIME_OS_SOLARIS
     DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_SOLARIS)
@@ -187,7 +188,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
 	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \
+	gcc/sections/package.d gcc/sections/pecoff.d \
 	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index 06c02961c86..665af30e09d 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -117,7 +117,9 @@ target_triplet = @target@
 @DRUNTIME_OS_NETBSD_TRUE@am__append_6 = $(DRUNTIME_DSOURCES_NETBSD)
 @DRUNTIME_OS_OPENBSD_TRUE@am__append_7 = $(DRUNTIME_DSOURCES_OPENBSD)
 @DRUNTIME_OS_LINUX_TRUE@am__append_8 = $(DRUNTIME_DSOURCES_LINUX)
-@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS)
+@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS) \
+@DRUNTIME_OS_MINGW_TRUE@				   config/mingw/msvc.c
+
 @DRUNTIME_OS_SOLARIS_TRUE@am__append_10 = $(DRUNTIME_DSOURCES_SOLARIS)
 # CPU specific sources
 @DRUNTIME_CPU_AARCH64_TRUE@am__append_11 = config/aarch64/switchcontext.S
@@ -213,7 +215,7 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
 	gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
 	gcc/sections/android.lo gcc/sections/elf_shared.lo \
 	gcc/sections/osx.lo gcc/sections/package.lo \
-	gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \
+	gcc/sections/pecoff.lo gcc/unwind/arm.lo \
 	gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
 	gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
 	object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
@@ -425,7 +427,8 @@ am__objects_19 = core/sys/windows/accctrl.lo \
 	core/sys/windows/winspool.lo core/sys/windows/winsvc.lo \
 	core/sys/windows/winuser.lo core/sys/windows/winver.lo \
 	core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo
-@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19)
+@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_la-msvc.lo
 am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
 	core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \
 	core/sys/solaris/libelf.lo core/sys/solaris/link.lo \
@@ -460,24 +463,26 @@ am_libgdruntime_la_OBJECTS = $(am__objects_33)
 libgdruntime_la_OBJECTS = $(am_libgdruntime_la_OBJECTS)
 am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_34 = core/stdc/libgdruntime_convenience_la-errno_.lo
-@DRUNTIME_CPU_AARCH64_TRUE@am__objects_35 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_ARM_TRUE@am__objects_36 = config/arm/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_MIPS_TRUE@am__objects_37 = config/mips/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_POWERPC_TRUE@am__objects_38 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_39 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_40 = config/x86/libgdruntime_convenience_la-switchcontext.lo
-@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_41 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
-@DRUNTIME_CPU_S390_TRUE@am__objects_42 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
-am__objects_43 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
+@DRUNTIME_OS_MINGW_TRUE@am__objects_35 = $(am__objects_19) \
+@DRUNTIME_OS_MINGW_TRUE@	config/mingw/libgdruntime_convenience_la-msvc.lo
+@DRUNTIME_CPU_AARCH64_TRUE@am__objects_36 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_ARM_TRUE@am__objects_37 = config/arm/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_MIPS_TRUE@am__objects_38 = config/mips/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_POWERPC_TRUE@am__objects_39 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_40 = config/mingw/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_41 = config/x86/libgdruntime_convenience_la-switchcontext.lo
+@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_42 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo
+@DRUNTIME_CPU_S390_TRUE@am__objects_43 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo
+am__objects_44 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \
 	$(am__objects_10) $(am__objects_12) $(am__objects_14) \
-	$(am__objects_16) $(am__objects_18) $(am__objects_20) \
-	$(am__objects_22) $(am__objects_35) $(am__objects_36) \
-	$(am__objects_37) $(am__objects_38) $(am__objects_39) \
-	$(am__objects_40) $(am__objects_41) $(am__objects_42)
-am__objects_44 = $(am__objects_1) $(am__objects_34) $(am__objects_43) \
+	$(am__objects_16) $(am__objects_18) $(am__objects_35) \
+	$(am__objects_22) $(am__objects_36) $(am__objects_37) \
+	$(am__objects_38) $(am__objects_39) $(am__objects_40) \
+	$(am__objects_41) $(am__objects_42) $(am__objects_43)
+am__objects_45 = $(am__objects_1) $(am__objects_34) $(am__objects_44) \
 	$(am__objects_32)
-am__objects_45 = $(am__objects_44)
-am_libgdruntime_convenience_la_OBJECTS = $(am__objects_45)
+am__objects_46 = $(am__objects_45)
+am_libgdruntime_convenience_la_OBJECTS = $(am__objects_46)
 libgdruntime_convenience_la_OBJECTS =  \
 	$(am_libgdruntime_convenience_la_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
@@ -659,6 +664,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -688,6 +695,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
@@ -720,7 +728,7 @@ D_EXTRA_DFLAGS = -nostdinc -I $(srcdir) -I .
 
 # D flags for compilation
 AM_DFLAGS = \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 
@@ -813,7 +821,7 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
 	gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \
 	gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \
 	gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \
-	gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \
+	gcc/sections/package.d gcc/sections/pecoff.d \
 	gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \
 	gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \
 	rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \
@@ -1213,8 +1221,7 @@ gcc/sections/android.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/elf_shared.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/osx.lo: gcc/sections/$(am__dirstamp)
 gcc/sections/package.lo: gcc/sections/$(am__dirstamp)
-gcc/sections/win32.lo: gcc/sections/$(am__dirstamp)
-gcc/sections/win64.lo: gcc/sections/$(am__dirstamp)
+gcc/sections/pecoff.lo: gcc/sections/$(am__dirstamp)
 gcc/unwind/$(am__dirstamp):
 	@$(MKDIR_P) gcc/unwind
 	@: > gcc/unwind/$(am__dirstamp)
@@ -1720,6 +1727,10 @@ core/sys/windows/winuser.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/winver.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtsapi32.lo: core/sys/windows/$(am__dirstamp)
 core/sys/windows/wtypes.lo: core/sys/windows/$(am__dirstamp)
+config/mingw/$(am__dirstamp):
+	@$(MKDIR_P) config/mingw
+	@: > config/mingw/$(am__dirstamp)
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/$(am__dirstamp)
 core/sys/solaris/$(am__dirstamp):
 	@$(MKDIR_P) core/sys/solaris
 	@: > core/sys/solaris/$(am__dirstamp)
@@ -1769,9 +1780,6 @@ config/powerpc/$(am__dirstamp):
 	@: > config/powerpc/$(am__dirstamp)
 config/powerpc/libgdruntime_la-switchcontext.lo:  \
 	config/powerpc/$(am__dirstamp)
-config/mingw/$(am__dirstamp):
-	@$(MKDIR_P) config/mingw
-	@: > config/mingw/$(am__dirstamp)
 config/mingw/libgdruntime_la-switchcontext.lo:  \
 	config/mingw/$(am__dirstamp)
 config/x86/$(am__dirstamp):
@@ -1796,6 +1804,8 @@ libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EX
 	$(AM_V_GEN)$(libgdruntime_la_LINK) -rpath $(toolexeclibdir) $(libgdruntime_la_OBJECTS) $(libgdruntime_la_LIBADD) $(LIBS)
 core/stdc/libgdruntime_convenience_la-errno_.lo:  \
 	core/stdc/$(am__dirstamp)
+config/mingw/libgdruntime_convenience_la-msvc.lo:  \
+	config/mingw/$(am__dirstamp)
 config/aarch64/libgdruntime_convenience_la-switchcontext.lo:  \
 	config/aarch64/$(am__dirstamp)
 config/arm/libgdruntime_convenience_la-switchcontext.lo:  \
@@ -1991,9 +2001,15 @@ config/s390/libgdruntime_convenience_la-get_tls_offset.lo: config/s390/get_tls_o
 core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 core/stdc/libgdruntime_convenience_la-errno_.lo: core/stdc/errno_.c
 	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_convenience_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c
 
+config/mingw/libgdruntime_convenience_la-msvc.lo: config/mingw/msvc.c
+	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_convenience_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/libphobos/libdruntime/config/mingw/msvc.c b/libphobos/libdruntime/config/mingw/msvc.c
new file mode 100644
index 00000000000..25b15a06950
--- /dev/null
+++ b/libphobos/libdruntime/config/mingw/msvc.c
@@ -0,0 +1,54 @@
+/* Windows support code to wrap differences between different
+   versions of the Microsoft C libaries.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+
+/* The symbols for stdin, stdout, and stderr are defined for D in the
+   core.stdc.stdio module.  Save the macros and redeclare them here.  */
+#define c_stdin stdin
+#undef stdin
+extern FILE *stdin;
+
+#define c_stdout stdout
+#undef stdout
+extern FILE *stdout;
+
+#define c_stderr stderr
+#undef stderr
+extern FILE *stderr;
+
+/* Set to 1 if run-time is using ucrtbase.dll.  */
+unsigned char msvcUsesUCRT;
+
+void init_msvc()
+{
+#if __MSVCRT_VERSION__ >= 0x1400
+  msvcUsedUCRT = 1;
+#endif
+
+  stdin = c_stdin;
+  stdout = c_stdout;
+  stderr = c_stderr;
+}
diff --git a/libphobos/libdruntime/config/mingw/switchcontext.S b/libphobos/libdruntime/config/mingw/switchcontext.S
index 6592ff604bc..0cb8b015bfc 100644
--- a/libphobos/libdruntime/config/mingw/switchcontext.S
+++ b/libphobos/libdruntime/config/mingw/switchcontext.S
@@ -28,7 +28,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -63,13 +66,15 @@ CSYM(fiber_switchContext):
     popq %RCX;
     jmp *%RCX;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #elif defined(_X86_)
 
     .text
     .globl CSYM(fiber_switchContext)
-    .type CSYM(fiber_switchContext), @function
+    .def CSYM(fiber_switchContext)
+    .scl 2
+    .type 32
+    .endef
     .align 16
 CSYM(fiber_switchContext):
     .cfi_startproc
@@ -104,6 +109,5 @@ CSYM(fiber_switchContext):
     // 'return' to complete switch
     ret;
     .cfi_endproc
-    .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
 
 #endif
diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d
index 7caef4c1339..b048a944a88 100644
--- a/libphobos/libdruntime/core/stdc/stdlib.d
+++ b/libphobos/libdruntime/core/stdc/stdlib.d
@@ -121,19 +121,22 @@ ulong   strtoull(scope inout(char)* nptr, scope inout(char)** endptr, int base);
 
 version (CRuntime_Microsoft)
 {
-    // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
-    ///
-    extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
-    {   // Fake it 'till we make it
-        return strtod(nptr, endptr);
+    version (MinGW)
+    {
+        ///
+        real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
+        ///
+        alias __mingw_strtold strtold;
+    }
+    else
+    {
+        // strtold exists starting from VS2013, so we give it D linkage to avoid link errors
+        ///
+        extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr)
+        {   // Fake it 'till we make it
+            return strtod(nptr, endptr);
+        }
     }
-}
-else version (MinGW)
-{
-    ///
-    real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr);
-    ///
-    alias __mingw_strtold strtold;
 }
 else
 {
diff --git a/libphobos/libdruntime/core/stdc/tgmath.d b/libphobos/libdruntime/core/stdc/tgmath.d
index 4dd1b3ccc66..9a351db3861 100644
--- a/libphobos/libdruntime/core/stdc/tgmath.d
+++ b/libphobos/libdruntime/core/stdc/tgmath.d
@@ -1409,13 +1409,20 @@ else
     alias core.stdc.math.fabs          fabs;
     version (CRuntime_Microsoft)
     {
+        version (MinGW)
+        {
+            ///
+            alias core.stdc.math.fabsf fabs;
+            ///
+            alias core.stdc.math.fabsl fabs;
+        }
     }
     else
     {
         ///
-        alias core.stdc.math.fabsf         fabs;
+        alias core.stdc.math.fabsf     fabs;
         ///
-        alias core.stdc.math.fabsl         fabs;
+        alias core.stdc.math.fabsl     fabs;
     }
 
     ///
diff --git a/libphobos/libdruntime/core/sys/windows/com.d b/libphobos/libdruntime/core/sys/windows/com.d
index 90a294343fc..2808a6c59fc 100644
--- a/libphobos/libdruntime/core/sys/windows/com.d
+++ b/libphobos/libdruntime/core/sys/windows/com.d
@@ -57,12 +57,12 @@ alias COINIT_SPEED_OVER_MEMORY   = COINIT.COINIT_SPEED_OVER_MEMORY;
 
 public import core.sys.windows.uuid;
 
-extern (System)
+extern (Windows)
 {
 
 class ComObject : IUnknown
 {
-extern (System):
+extern (Windows):
     HRESULT QueryInterface(const(IID)* riid, void** ppv)
     {
         if (*riid == IID_IUnknown)
diff --git a/libphobos/libdruntime/core/sys/windows/dbghelp.d b/libphobos/libdruntime/core/sys/windows/dbghelp.d
index 8c9827034e9..9848fb99115 100644
--- a/libphobos/libdruntime/core/sys/windows/dbghelp.d
+++ b/libphobos/libdruntime/core/sys/windows/dbghelp.d
@@ -18,7 +18,7 @@ import core.sys.windows.windef;
 
 public import core.sys.windows.dbghelp_types;
 
-extern(System)
+extern(Windows)
 {
     alias BOOL         function(HANDLE hProcess, DWORD64 lpBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) ReadProcessMemoryProc64;
     alias PVOID        function(HANDLE hProcess, DWORD64 AddrBase) FunctionTableAccessProc64;
diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d
index 9f36ac389a6..3df0d7fd41b 100644
--- a/libphobos/libdruntime/core/sys/windows/dll.d
+++ b/libphobos/libdruntime/core/sys/windows/dll.d
@@ -31,17 +31,7 @@ public import core.sys.windows.threadaux;
 //  not access tls_array[tls_index] as needed for thread local _tlsstart and _tlsend
 extern (C)
 {
-        version (MinGW)
-        {
-            extern __gshared void* _tls_start;
-            extern __gshared void* _tls_end;
-            extern __gshared void* __xl_a;
-
-            alias _tls_start _tlsstart;
-            alias _tls_end   _tlsend;
-            alias __xl_a     _tls_callbacks_a;
-        }
-        else version (Win32)
+    version (Win32)
     {
         version (CRuntime_DigitalMars)
         {
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index defdc9586f1..638eada3e43 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -1539,9 +1539,9 @@ package extern(D) void* getStackBottom() nothrow @nogc
             void *bottom;
 
             version (X86)
-                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" (bottom); }
             else version (X86_64)
-                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" bottom; }
+                asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" (bottom); }
             else
                 static assert(false, "Platform not supported.");
 
diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index c747b5132d1..7e02dabd221 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -805,7 +805,7 @@ version (GNU_SEH_Exceptions)
                                                            void* ms_orig_context, void* ms_disp)
     {
         return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context,
-                                     ms_disp, &__gdc_personality_imp);
+                                     ms_disp, &gdc_personality);
     }
 }
 else version (GNU_SjLj_Exceptions)
diff --git a/libphobos/libdruntime/gcc/gthread.d b/libphobos/libdruntime/gcc/gthread.d
index ef35a3c27ec..5003637b9ea 100644
--- a/libphobos/libdruntime/gcc/gthread.d
+++ b/libphobos/libdruntime/gcc/gthread.d
@@ -86,10 +86,12 @@ else static if (GNU_Thread_Model == ThreadModel.Single)
 }
 else static if (GNU_Thread_Model == ThreadModel.Win32)
 {
+    import core.stdc.config;
+
     struct __gthread_once_t
     {
-        INT done;
-        LONG started;
+        int done;
+        c_long started;
     }
 
     int __gthr_win32_key_create(__gthread_key_t* keyp, GthreadDestroyFn dtor);
diff --git a/libphobos/libdruntime/gcc/sections/package.d b/libphobos/libdruntime/gcc/sections/package.d
index fdaf039fcfa..5d76072af25 100644
--- a/libphobos/libdruntime/gcc/sections/package.d
+++ b/libphobos/libdruntime/gcc/sections/package.d
@@ -22,26 +22,20 @@
 
 module gcc.sections;
 
-version (CRuntime_Glibc)
-    public import gcc.sections.elf_shared;
-else version (CRuntime_Musl)
-    public import gcc.sections.elf_shared;
-else version (CRuntime_UClibc)
-    public import gcc.sections.elf_shared;
-else version (FreeBSD)
-    public import gcc.sections.elf_shared;
-else version (NetBSD)
-    public import gcc.sections.elf_shared;
-else version (DragonFlyBSD)
-    public import gcc.sections.elf_shared;
-else version (Solaris)
+version (CRuntime_Glibc)  version = ElfShared;
+version (CRuntime_Musl)   version = ElfShared;
+version (CRuntime_UClibc) version = ElfShared;
+version (FreeBSD)         version = ElfShared;
+version (NetBSD)          version = ElfShared;
+version (DragonFlyBSD)    version = ElfShared;
+version (Solaris)         version = ElfShared;
+
+version (ElfShared)
     public import gcc.sections.elf_shared;
 else version (OSX)
     public import gcc.sections.osx;
-else version (CRuntime_DigitalMars)
-    public import gcc.sections.win32;
-else version (CRuntime_Microsoft)
-    public import gcc.sections.win64;
+else version (Windows)
+    public import gcc.sections.pecoff;
 else version (CRuntime_Bionic)
     public import gcc.sections.android;
 else
diff --git a/libphobos/libdruntime/gcc/sections/pecoff.d b/libphobos/libdruntime/gcc/sections/pecoff.d
new file mode 100644
index 00000000000..5fa1df2ac54
--- /dev/null
+++ b/libphobos/libdruntime/gcc/sections/pecoff.d
@@ -0,0 +1,830 @@
+// PE/COFF-specific support for sections.
+// Copyright (C) 2021 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+module gcc.sections.pecoff;
+
+version (Windows):
+
+import core.memory;
+import core.stdc.stdlib;
+import core.sys.windows.winbase;
+import core.sys.windows.windef;
+import core.sys.windows.winnt;
+import rt.minfo;
+import rt.util.container.array;
+import rt.util.container.hashtab;
+
+version (GNU_EMUTLS)
+    import gcc.emutls;
+
+/****
+ * Asserts the specified condition, independent from -release, by abort()ing.
+ * Regular assertions throw an AssertError and thus require an initialized
+ * GC, which isn't the case (yet or anymore) for the startup/shutdown code in
+ * this module (called by CRT ctors/dtors etc.).
+ */
+void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe
+{
+    import core.internal.abort;
+    condition || abort(msg, __FILE__, line);
+}
+
+alias DSO SectionGroup;
+struct DSO
+{
+    static int opApply(scope int delegate(ref DSO) dg)
+    {
+        foreach (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    static int opApplyReverse(scope int delegate(ref DSO) dg)
+    {
+        foreach_reverse (dso; _loadedDSOs)
+        {
+            if (auto res = dg(*dso))
+                return res;
+        }
+        return 0;
+    }
+
+    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
+    {
+        return _moduleGroup.modules;
+    }
+
+    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
+    {
+        return _moduleGroup;
+    }
+
+    @property inout(void[])[] gcRanges() inout nothrow @nogc
+    {
+        return _gcRanges[];
+    }
+
+private:
+
+    invariant()
+    {
+        safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO.");
+    }
+
+    void** _slot;
+    ModuleGroup _moduleGroup;
+    Array!(void[]) _gcRanges;
+
+    version (Shared)
+    {
+        Array!(void[]) _codeSegments; // array of code segments
+        Array!(DSO*) _deps; // D libraries needed by this DSO
+        void* _handle; // corresponding handle
+    }
+}
+
+/****
+ * Boolean flag set to true while the runtime is initialized.
+ */
+__gshared bool _isRuntimeInitialized;
+
+/****
+ * Gets called on program startup just before GC is initialized.
+ */
+void initSections() nothrow @nogc
+{
+    _isRuntimeInitialized = true;
+}
+
+/***
+ * Gets called on program shutdown just after GC is terminated.
+ */
+void finiSections() nothrow @nogc
+{
+    _isRuntimeInitialized = false;
+}
+
+alias ScanDG = void delegate(void* pbeg, void* pend) nothrow;
+
+version (Shared)
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(ThreadDSO)* initTLSRanges() @nogc nothrow
+    {
+        return &_loadedDSOs();
+    }
+
+    void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow
+    {
+        // Nothing to do here. tdsos used to point to the _loadedDSOs instance
+        // in the dying thread's TLS segment and as such is not valid anymore.
+        // The memory for the array contents was already reclaimed in
+        // cleanupLoadedLibraries().
+    }
+
+    void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
+
+    // interface for core.thread to inherit loaded libraries
+    void* pinLoadedLibraries() nothrow @nogc
+    {
+        auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof);
+        res.length = _loadedDSOs.length;
+        foreach (i, ref tdso; _loadedDSOs)
+        {
+            (*res)[i] = tdso;
+            if (tdso._addCnt)
+            {
+                // Increment the DLL ref for explicitly loaded libraries to pin them.
+                char[MAX_PATH] buf;
+                char[] buffer = buf[];
+                const success = .LoadLibraryA(nameForDSO(tdso._pdso, buffer)) !is null;
+                safeAssert(success, "Failed to increment DLL ref.");
+                (*res)[i]._addCnt = 1; // new array takes over the additional ref count
+            }
+        }
+        return res;
+    }
+
+    void unpinLoadedLibraries(void* p) nothrow @nogc
+    {
+        auto pary = cast(Array!(ThreadDSO)*)p;
+        // In case something failed we need to undo the pinning.
+        foreach (ref tdso; *pary)
+        {
+            if (tdso._addCnt)
+            {
+                auto handle = tdso._pdso._handle;
+                safeAssert(handle !is null, "Invalid library handle.");
+                .FreeLibrary(handle);
+            }
+        }
+        pary.reset();
+        .free(pary);
+    }
+
+    // Called before TLS ctors are ran, copy over the loaded libraries
+    // of the parent thread.
+    void inheritLoadedLibraries(void* p) nothrow @nogc
+    {
+        safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread.");
+        _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p);
+        .free(p);
+    }
+
+    // Called after all TLS dtors ran, decrements all remaining DLL refs.
+    void cleanupLoadedLibraries() nothrow @nogc
+    {
+        foreach (ref tdso; _loadedDSOs)
+        {
+            if (tdso._addCnt == 0) continue;
+
+            auto handle = tdso._pdso._handle;
+            safeAssert(handle !is null, "Invalid DSO handle.");
+            for (; tdso._addCnt > 0; --tdso._addCnt)
+                .FreeLibrary(handle);
+        }
+
+        // Free the memory for the array contents.
+        _loadedDSOs.reset();
+    }
+}
+else
+{
+    /***
+     * Called once per thread; returns array of thread local storage ranges
+     */
+    Array!(void[])* initTLSRanges() nothrow @nogc
+    {
+        return null;
+    }
+
+    void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc
+    {
+    }
+
+    void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow
+    {
+        version (GNU_EMUTLS)
+            _d_emutls_scan(dg);
+        else
+            static assert(0, "Native TLS unimplemented");
+    }
+}
+
+private:
+
+version (Shared)
+{
+    /*
+     * Array of thread local DSO metadata for all libraries loaded and
+     * initialized in this thread.
+     *
+     * Note:
+     *     A newly spawned thread will inherit these libraries.
+     * Note:
+     *     We use an array here to preserve the order of
+     *     initialization.  If that became a performance issue, we
+     *     could use a hash table and enumerate the DSOs during
+     *     loading so that the hash table values could be sorted when
+     *     necessary.
+     */
+    struct ThreadDSO
+    {
+        DSO* _pdso;
+        static if (_pdso.sizeof == 8) uint _refCnt, _addCnt;
+        else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt;
+        else static assert(0, "unimplemented");
+        alias _pdso this;
+    }
+
+    @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow
+    {
+        static Array!(ThreadDSO) x;
+        return x;
+    }
+
+    /*
+     * Set to true during rt_loadLibrary/rt_unloadLibrary calls.
+     */
+    bool _rtLoading;
+
+    /*
+     * Hash table to map the native handle (as returned by dlopen)
+     * to the corresponding DSO*, protected by a mutex.
+     */
+    __gshared CRITICAL_SECTION _handleToDSOMutex;
+    @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow
+    {
+        __gshared HashTab!(void*, DSO*) x;
+        return x;
+    }
+}
+else
+{
+    /*
+     * Static DSOs loaded by the runtime linker. This includes the
+     * executable. These can't be unloaded.
+     */
+    @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow
+    {
+        __gshared Array!(DSO*) x;
+        return x;
+    }
+
+    enum _rtLoading = false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Compiler to runtime interface.
+///////////////////////////////////////////////////////////////////////////////
+
+/****
+ * This data structure is generated by the compiler, and then passed to
+ * _d_dso_registry().
+ */
+struct CompilerDSOData
+{
+    size_t _version;                                       // currently 1
+    void** _slot;                                          // can be used to store runtime data
+    immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file
+}
+
+T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; }
+
+/* For each shared library and executable, the compiler generates code that
+ * sets up CompilerDSOData and calls _d_dso_registry().
+ * A pointer to that code is inserted into both the .ctors and .dtors
+ * segment so it gets called by the loader on startup and shutdown.
+ */
+extern(C) void _d_dso_registry(CompilerDSOData* data)
+{
+    // only one supported currently
+    safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version.");
+
+    // no backlink => register
+    if (*data._slot is null)
+    {
+        immutable firstDSO = _loadedDSOs.empty;
+        if (firstDSO) initLocks();
+
+        DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
+        assert(typeid(DSO).initializer().ptr is null);
+        pdso._slot = data._slot;
+        *data._slot = pdso; // store backlink in library record
+
+        pdso._moduleGroup = ModuleGroup(toRange(data._minfo_beg, data._minfo_end));
+
+        HMODULE handle = void;
+        const moduleFound = findModuleHandleForAddr(data._slot, handle);
+        safeAssert(moduleFound, "Failed to find image header.");
+
+        scanSegments(handle, pdso);
+
+        version (Shared)
+        {
+            getDependencies(handle, pdso._deps);
+            pdso._handle = handle;
+            setDSOForHandle(pdso, pdso._handle);
+
+            if (!_rtLoading)
+            {
+                /* This DSO was not loaded by rt_loadLibrary which
+                 * happens for all dependencies of an executable or
+                 * the first dlopen call from a C program.
+                 * In this case we add the DSO to the _loadedDSOs of this
+                 * thread with a refCnt of 1 and call the TlsCtors.
+                 */
+                immutable ushort refCnt = 1, addCnt = 0;
+                _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            }
+        }
+        else
+        {
+            foreach (p; _loadedDSOs)
+                safeAssert(p !is pdso, "DSO already registered.");
+            _loadedDSOs.insertBack(pdso);
+        }
+
+        // don't initialize modules before rt_init was called
+        if (_isRuntimeInitialized)
+        {
+            registerGCRanges(pdso);
+            // rt_loadLibrary will run tls ctors, so do this only for dlopen
+            immutable runTlsCtors = !_rtLoading;
+            runModuleConstructors(pdso, runTlsCtors);
+        }
+    }
+    // has backlink => unregister
+    else
+    {
+        DSO* pdso = cast(DSO*)*data._slot;
+        *data._slot = null;
+
+        // don't finalizes modules after rt_term was called (see Bugzilla 11378)
+        if (_isRuntimeInitialized)
+        {
+            // rt_unloadLibrary already ran tls dtors, so do this only for dlclose
+            immutable runTlsDtors = !_rtLoading;
+            runModuleDestructors(pdso, runTlsDtors);
+            unregisterGCRanges(pdso);
+            // run finalizers after module dtors (same order as in rt_term)
+            version (Shared) runFinalizers(pdso);
+        }
+
+        version (Shared)
+        {
+            if (!_rtLoading)
+            {
+                /* This DSO was not unloaded by rt_unloadLibrary so we
+                 * have to remove it from _loadedDSOs here.
+                 */
+                foreach (i, ref tdso; _loadedDSOs)
+                {
+                    if (tdso._pdso == pdso)
+                    {
+                        _loadedDSOs.remove(i);
+                        break;
+                    }
+                }
+            }
+
+            unsetDSOForHandle(pdso, pdso._handle);
+        }
+        else
+        {
+            // static DSOs are unloaded in reverse order
+            safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one.");
+            _loadedDSOs.popBack();
+        }
+
+        freeDSO(pdso);
+
+        // last DSO being unloaded => shutdown registry
+        if (_loadedDSOs.empty)
+        {
+            version (GNU_EMUTLS)
+                _d_emutls_destroy();
+            version (Shared)
+            {
+                safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs.");
+                _handleToDSO.reset();
+            }
+            finiLocks();
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// dynamic loading
+///////////////////////////////////////////////////////////////////////////////
+
+// Shared D libraries are only supported when linking against a shared druntime library.
+
+version (Shared)
+{
+    ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc
+    {
+        foreach (ref tdata; _loadedDSOs)
+            if (tdata._pdso == pdso) return &tdata;
+        return null;
+    }
+
+    void incThreadRef(DSO* pdso, bool incAdd)
+    {
+        if (auto tdata = findThreadDSO(pdso)) // already initialized
+        {
+            if (incAdd && ++tdata._addCnt > 1) return;
+            ++tdata._refCnt;
+        }
+        else
+        {
+            foreach (dep; pdso._deps)
+                incThreadRef(dep, false);
+            immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0;
+            _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt));
+            pdso._moduleGroup.runTlsCtors();
+        }
+    }
+
+    void decThreadRef(DSO* pdso, bool decAdd)
+    {
+        auto tdata = findThreadDSO(pdso);
+        safeAssert(tdata !is null, "Failed to find thread DSO.");
+        safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call.");
+
+        if (decAdd && --tdata._addCnt > 0) return;
+        if (--tdata._refCnt > 0) return;
+
+        pdso._moduleGroup.runTlsDtors();
+        foreach (i, ref td; _loadedDSOs)
+            if (td._pdso == pdso) _loadedDSOs.remove(i);
+        foreach (dep; pdso._deps)
+            decThreadRef(dep, false);
+    }
+}
+
+/***********************************
+ * These are a temporary means of providing a GC hook for DLL use.  They may be
+ * replaced with some other similar functionality later.
+ */
+extern (C)
+{
+    void* gc_getProxy();
+    void  gc_setProxy(void* p);
+    void  gc_clrProxy();
+
+    alias void  function(void*) gcSetFn;
+    alias void  function()      gcClrFn;
+}
+
+/*******************************************
+ * Loads a DLL written in D with the name 'name'.
+ * Returns:
+ *      opaque handle to the DLL if successfully loaded
+ *      null if failure
+ */
+extern(C) void* rt_loadLibrary(const char* name)
+{
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+    }
+    return initLibrary(.LoadLibraryA(name));
+}
+
+extern (C) void* rt_loadLibraryW(const wchar_t* name)
+{
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+    }
+    return initLibrary(.LoadLibraryW(name));
+}
+
+void* initLibrary(void* handle)
+{
+    if (handle is null)
+        return null;
+
+    version (Shared)
+    {
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            incThreadRef(pdso, true);
+    }
+    gcSetFn gcSet = cast(gcSetFn) GetProcAddress(handle, "gc_setProxy");
+    if (gcSet !is null)
+    {
+        // BUG: Set proxy, but too late
+        gcSet(gc_getProxy());
+    }
+    return handle;
+}
+
+/*************************************
+ * Unloads DLL that was previously loaded by rt_loadLibrary().
+ * Input:
+ *      handle  the handle returned by rt_loadLibrary()
+ * Returns:
+ *      1   succeeded
+ *      0   some failure happened
+ */
+extern(C) int rt_unloadLibrary(void* handle)
+{
+    if (handle is null)
+        return false;
+
+    version (Shared)
+    {
+        immutable save = _rtLoading;
+        _rtLoading = true;
+        scope (exit) _rtLoading = save;
+
+        // if it's a D library
+        if (auto pdso = dsoForHandle(handle))
+            decThreadRef(pdso, true);
+    }
+    gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(handle, "gc_clrProxy");
+    if (gcClr !is null)
+        gcClr();
+    return .FreeLibrary(handle) != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// helper functions
+///////////////////////////////////////////////////////////////////////////////
+
+void initLocks() nothrow @nogc
+{
+    version (Shared)
+        InitializeCriticalSection(&_handleToDSOMutex);
+}
+
+void finiLocks() nothrow @nogc
+{
+    version (Shared)
+        DeleteCriticalSection(&_handleToDSOMutex);
+}
+
+void runModuleConstructors(DSO* pdso, bool runTlsCtors)
+{
+    pdso._moduleGroup.sortCtors();
+    pdso._moduleGroup.runCtors();
+    if (runTlsCtors) pdso._moduleGroup.runTlsCtors();
+}
+
+void runModuleDestructors(DSO* pdso, bool runTlsDtors)
+{
+    if (runTlsDtors) pdso._moduleGroup.runTlsDtors();
+    pdso._moduleGroup.runDtors();
+}
+
+void registerGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.addRange(rng.ptr, rng.length);
+}
+
+void unregisterGCRanges(DSO* pdso) nothrow @nogc
+{
+    foreach (rng; pdso._gcRanges)
+        GC.removeRange(rng.ptr);
+}
+
+version (Shared) void runFinalizers(DSO* pdso)
+{
+    foreach (seg; pdso._codeSegments)
+        GC.runFinalizers(seg);
+}
+
+void freeDSO(DSO* pdso) nothrow @nogc
+{
+    pdso._gcRanges.reset();
+    version (Shared)
+    {
+        pdso._codeSegments.reset();
+        pdso._deps.reset();
+        pdso._handle = null;
+    }
+    .free(pdso);
+}
+
+version (Shared)
+{
+@nogc nothrow:
+    const(char)* nameForDSO(DSO* pdso, ref char[] buffer)
+    {
+        const success = GetModuleFileNameA(pdso._handle, buffer.ptr, cast(DWORD)buffer.length) != 0;
+        safeAssert(success, "Failed to get DLL name.");
+        return buffer.ptr;
+    }
+
+    DSO* dsoForHandle(in void* handle)
+    {
+        DSO* pdso;
+        .EnterCriticalSection(&_handleToDSOMutex);
+        if (auto ppdso = handle in _handleToDSO)
+            pdso = *ppdso;
+        .LeaveCriticalSection(&_handleToDSOMutex);
+        return pdso;
+    }
+
+    void setDSOForHandle(DSO* pdso, void* handle)
+    {
+        .EnterCriticalSection(&_handleToDSOMutex);
+        safeAssert(handle !in _handleToDSO, "DSO already registered.");
+        _handleToDSO[handle] = pdso;
+        .LeaveCriticalSection(&_handleToDSOMutex);
+    }
+
+    void unsetDSOForHandle(DSO* pdso, void* handle)
+    {
+        .EnterCriticalSection(&_handleToDSOMutex);
+        safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO.");
+        _handleToDSO.remove(handle);
+        .LeaveCriticalSection(&_handleToDSOMutex);
+    }
+
+    void getDependencies(in HMODULE handle, ref Array!(DSO*) deps)
+    {
+        auto nthdr = getNTHeader(handle);
+        auto import_entry = nthdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+        auto addr = import_entry.VirtualAddress;
+        auto datasize = import_entry.Size;
+
+        if (addr == 0 && datasize == 0)
+        {
+            // Maybe the optional header isn't there, look for the section.
+            foreach (section; getSectionHeader(handle))
+            {
+                if (!compareSectionName(section, ".idata"))
+                    continue;
+                addr = section.VirtualAddress;
+                datasize = section.Misc.VirtualSize;
+                break;
+            }
+            if (datasize == 0)
+                return;
+        }
+        else
+        {
+            bool foundSection = false;
+            foreach (section; getSectionHeader(handle))
+            {
+                if (!compareSectionName(section, ".idata"))
+                    continue;
+                // Section containing import table has no contents.
+                if (section.Misc.VirtualSize == 0)
+                    return;
+                foundSection = true;
+                break;
+            }
+            // There is an import table, but the section containing it could not be found
+            if (!foundSection)
+                return;
+        }
+
+        // Get the names of each DLL
+        for (uint i = 0; i + IMAGE_IMPORT_DESCRIPTOR.sizeof <= datasize;
+             i += IMAGE_IMPORT_DESCRIPTOR.sizeof)
+        {
+            const data = cast(PIMAGE_IMPORT_DESCRIPTOR)(handle + addr + i);
+            if (data.Name == 0)
+                break;
+
+            // dll name of dependency
+            auto name = cast(char*)(handle + data.Name);
+            // get handle without loading the library
+            auto libhandle = handleForName(name);
+            // the runtime linker has already loaded all dependencies
+            safeAssert(handle !is null, "Failed to get library handle.");
+            // if it's a D library
+            if (auto pdso = dsoForHandle(handle))
+                deps.insertBack(pdso); // append it to the dependencies
+        }
+    }
+
+    void* handleForName(const char* name)
+    {
+        return GetModuleHandleA(name);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PE/COFF program header iteration
+///////////////////////////////////////////////////////////////////////////////
+
+bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc
+{
+    if (name[] != cast(char[])section.Name[0 .. name.length])
+        return false;
+    return name.length == 8 || section.Name[name.length] == 0;
+}
+
+/************
+ * Scan segments in the image header and store
+ * the writeable data segments in *pdso.
+ */
+
+void scanSegments(in HMODULE handle, DSO* pdso) nothrow @nogc
+{
+    foreach (section; getSectionHeader(handle))
+    {
+        // the ".data" image section includes both object file sections ".data" and ".bss"
+        if (compareSectionName(section, ".data"))
+        {
+            auto data = cast(void*)handle + section.VirtualAddress;
+            pdso._gcRanges.insertBack(data[0 .. section.Misc.VirtualSize]);
+            continue;
+        }
+
+        version (Shared)
+        {
+            if (compareSectionName(section, ".text"))
+            {
+                auto text = cast(void*)handle + section.VirtualAddress;
+                pdso._codeSegments.insertBack(text[0 .. section.Misc.VirtualSize]);
+                continue;
+            }
+        }
+    }
+}
+
+/**************************
+ * Input:
+ *      handle  where the output is to be written
+ * Returns:
+ *      true if found, and *handle is filled in
+ */
+
+bool findModuleHandleForAddr(in void* addr, out HMODULE handle) nothrow @nogc
+{
+    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+                           cast(const(wchar)*) addr, &handle))
+        return true;
+
+    return false;
+}
+
+/**
+ * Returns the image NT header for the HMODULE handle passed,
+ * or null if not found.
+ */
+PIMAGE_NT_HEADERS getNTHeader(in HMODULE handle) nothrow @nogc
+{
+    auto doshdr = cast(PIMAGE_DOS_HEADER)handle;
+    if (doshdr.e_magic != IMAGE_DOS_SIGNATURE)
+        return null;
+
+    return cast(typeof(return))(cast(void*)doshdr + doshdr.e_lfanew);
+}
+
+/**
+ * Returns the image section header for the HMODULE handle passed,
+ * or null if not found.
+ */
+IMAGE_SECTION_HEADER[] getSectionHeader(in HMODULE handle) nothrow @nogc
+{
+    if (auto nthdr = getNTHeader(handle))
+    {
+        const void* opthdr = &nthdr.OptionalHeader;
+        const offset = nthdr.FileHeader.SizeOfOptionalHeader;
+        const length = nthdr.FileHeader.NumberOfSections;
+        return (cast(PIMAGE_SECTION_HEADER)(opthdr + offset))[0 .. length];
+    }
+    return null;
+}
diff --git a/libphobos/libdruntime/gcc/sections/win32.d b/libphobos/libdruntime/gcc/sections/win32.d
deleted file mode 100644
index b355dfc5068..00000000000
--- a/libphobos/libdruntime/gcc/sections/win32.d
+++ /dev/null
@@ -1,183 +0,0 @@
-// Win32-specific support for sections.
-// Copyright (C) 2019-2021 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.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-module gcc.sections.win32;
-
-version (CRuntime_DigitalMars):
-
-// debug = PRINTF;
-debug(PRINTF) import core.stdc.stdio;
-import rt.minfo;
-import core.stdc.stdlib : malloc, free;
-
-struct SectionGroup
-{
-    static int opApply(scope int delegate(ref SectionGroup) dg)
-    {
-        return dg(_sections);
-    }
-
-    static int opApplyReverse(scope int delegate(ref SectionGroup) dg)
-    {
-        return dg(_sections);
-    }
-
-    @property immutable(ModuleInfo*)[] modules() const nothrow @nogc
-    {
-        return _moduleGroup.modules;
-    }
-
-    @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc
-    {
-        return _moduleGroup;
-    }
-
-    @property inout(void[])[] gcRanges() inout nothrow @nogc
-    {
-        return _gcRanges[];
-    }
-
-private:
-    ModuleGroup _moduleGroup;
-    void[][] _gcRanges;
-}
-
-shared(bool) conservative;
-
-void initSections() nothrow @nogc
-{
-    _sections._moduleGroup = ModuleGroup(getModuleInfos());
-
-    import rt.sections;
-    conservative = !scanDataSegPrecisely();
-
-    if (conservative)
-    {
-        _sections._gcRanges = (cast(void[]*) malloc(2 * (void[]).sizeof))[0..2];
-
-        auto databeg = cast(void*)&_xi_a;
-        auto dataend = cast(void*)_moduleinfo_array.ptr;
-        _sections._gcRanges[0] = databeg[0 .. dataend - databeg];
-
-        // skip module info and CONST segment
-        auto bssbeg = cast(void*)&_edata;
-        auto bssend = cast(void*)&_end;
-        _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg];
-    }
-    else
-    {
-        size_t count = &_DPend - &_DPbegin;
-        auto ranges = cast(void[]*) malloc(count * (void[]).sizeof);
-        size_t r = 0;
-        void* prev = null;
-        for (size_t i = 0; i < count; i++)
-        {
-            void* addr = (&_DPbegin)[i];
-            if (prev + (void*).sizeof == addr)
-                ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof];
-            else
-                ranges[r++] = (cast(void**)addr)[0..1];
-            prev = addr;
-        }
-        _sections._gcRanges = ranges[0..r];
-    }
-}
-
-void finiSections() nothrow @nogc
-{
-    free(_sections._gcRanges.ptr);
-}
-
-void[] initTLSRanges() nothrow @nogc
-{
-    auto pbeg = cast(void*)&_tlsstart;
-    auto pend = cast(void*)&_tlsend;
-    return pbeg[0 .. pend - pbeg];
-}
-
-void finiTLSRanges(void[] rng) nothrow @nogc
-{
-}
-
-void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow
-{
-    if (conservative)
-    {
-        dg(rng.ptr, rng.ptr + rng.length);
-    }
-    else
-    {
-        for (auto p = &_TPbegin; p < &_TPend; )
-        {
-            uint beg = *p++;
-            uint end = beg + cast(uint)((void*).sizeof);
-            while (p < &_TPend && *p == end)
-            {
-                end += (void*).sizeof;
-                p++;
-            }
-            dg(rng.ptr + beg, rng.ptr + end);
-        }
-    }
-}
-
-private:
-
-__gshared SectionGroup _sections;
-
-// Windows: this gets initialized by minit.asm
-extern(C) __gshared immutable(ModuleInfo*)[] _moduleinfo_array;
-extern(C) void _minit() nothrow @nogc;
-
-immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc
-out (result)
-{
-    foreach (m; result)
-        assert(m !is null);
-}
-body
-{
-    // _minit directly alters the global _moduleinfo_array
-    _minit();
-    return _moduleinfo_array;
-}
-
-extern(C)
-{
-    extern __gshared
-    {
-        int _xi_a;      // &_xi_a just happens to be start of data segment
-        int _edata;     // &_edata is start of BSS segment
-        int _end;       // &_end is past end of BSS
-
-        void* _DPbegin; // first entry in the array of pointers addresses
-        void* _DPend;   // &_DPend points after last entry of array
-        uint _TPbegin;  // first entry in the array of TLS offsets of pointers
-        uint _TPend;    // &_DPend points after last entry of array
-    }
-
-    extern
-    {
-        int _tlsstart;
-        int _tlsend;
-    }
-}
diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d
index 357940ba821..512693c071d 100644
--- a/libphobos/libdruntime/gcc/sections/win64.d
+++ b/libphobos/libdruntime/gcc/sections/win64.d
@@ -51,14 +51,6 @@ struct SectionGroup
         return _moduleGroup;
     }
 
-    version (Win64)
-    @property immutable(FuncTable)[] ehTables() const nothrow @nogc
-    {
-        auto pbeg = cast(immutable(FuncTable)*)&_deh_beg;
-        auto pend = cast(immutable(FuncTable)*)&_deh_end;
-        return pbeg[0 .. pend - pbeg];
-    }
-
     @property inout(void[])[] gcRanges() inout nothrow @nogc
     {
         return _gcRanges[];
diff --git a/libphobos/libdruntime/gcc/unwind/generic.d b/libphobos/libdruntime/gcc/unwind/generic.d
index 5315739f82f..592b3afcb71 100644
--- a/libphobos/libdruntime/gcc/unwind/generic.d
+++ b/libphobos/libdruntime/gcc/unwind/generic.d
@@ -269,6 +269,6 @@ version (GNU_SEH_Exceptions)
         ExceptionCollidedUnwind
     }
 
-    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*,
+    extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, void*,
                                                           _Unwind_Personality_Fn);
 }
diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d
index 3d5ba299863..e4a2c6571d4 100644
--- a/libphobos/libdruntime/rt/dmain2.d
+++ b/libphobos/libdruntime/rt/dmain2.d
@@ -70,70 +70,6 @@ version (CRuntime_Microsoft)
     extern(C) void init_msvc();
 }
 
-/***********************************
- * These are a temporary means of providing a GC hook for DLL use.  They may be
- * replaced with some other similar functionality later.
- */
-extern (C)
-{
-    void* gc_getProxy();
-    void  gc_setProxy(void* p);
-    void  gc_clrProxy();
-
-    alias void* function()      gcGetFn;
-    alias void  function(void*) gcSetFn;
-    alias void  function()      gcClrFn;
-}
-
-version (Windows)
-{
-    /*******************************************
-     * Loads a DLL written in D with the name 'name'.
-     * Returns:
-     *      opaque handle to the DLL if successfully loaded
-     *      null if failure
-     */
-    extern (C) void* rt_loadLibrary(const char* name)
-    {
-        return initLibrary(.LoadLibraryA(name));
-    }
-
-    extern (C) void* rt_loadLibraryW(const wchar_t* name)
-    {
-        return initLibrary(.LoadLibraryW(name));
-    }
-
-    void* initLibrary(void* mod)
-    {
-        // BUG: LoadLibrary() call calls rt_init(), which fails if proxy is not set!
-        // (What? LoadLibrary() is a Windows API call, it shouldn't call rt_init().)
-        if (mod is null)
-            return mod;
-        gcSetFn gcSet = cast(gcSetFn) GetProcAddress(mod, "gc_setProxy");
-        if (gcSet !is null)
-        {   // BUG: Set proxy, but too late
-            gcSet(gc_getProxy());
-        }
-        return mod;
-    }
-
-    /*************************************
-     * Unloads DLL that was previously loaded by rt_loadLibrary().
-     * Input:
-     *      ptr     the handle returned by rt_loadLibrary()
-     * Returns:
-     *      1   succeeded
-     *      0   some failure happened
-     */
-    extern (C) int rt_unloadLibrary(void* ptr)
-    {
-        gcClrFn gcClr  = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
-        if (gcClr !is null)
-            gcClr();
-        return FreeLibrary(ptr) != 0;
-    }
-}
-
 /* To get out-of-band access to the args[] passed to main().
  */
 
diff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am
index 2de8ab951b4..0dc2a2625a9 100644
--- a/libphobos/src/Makefile.am
+++ b/libphobos/src/Makefile.am
@@ -24,7 +24,7 @@ D_EXTRA_DFLAGS=-nostdinc -I $(srcdir) \
 
 # D flags for compilation
 AM_DFLAGS= \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 # Flags for other kinds of sources
diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in
index 2e721783d06..33453517153 100644
--- a/libphobos/src/Makefile.in
+++ b/libphobos/src/Makefile.in
@@ -414,6 +414,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -443,6 +445,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
@@ -477,7 +480,7 @@ D_EXTRA_DFLAGS = -nostdinc -I $(srcdir) \
 
 # D flags for compilation
 AM_DFLAGS = \
-	$(phobos_compiler_pic_flag) \
+	$(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \
 	$(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS)
 
 
diff --git a/libphobos/testsuite/Makefile.in b/libphobos/testsuite/Makefile.in
index c38a4688258..51eb4efc79d 100644
--- a/libphobos/testsuite/Makefile.in
+++ b/libphobos/testsuite/Makefile.in
@@ -242,6 +242,8 @@ datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
 exec_prefix = @exec_prefix@
 gcc_version = @gcc_version@
 gdc_include_dir = @gdc_include_dir@
@@ -271,6 +273,7 @@ oldincludedir = @oldincludedir@
 pdfdir = @pdfdir@
 phobos_compiler_pic_flag = @phobos_compiler_pic_flag@
 phobos_compiler_shared_flag = @phobos_compiler_shared_flag@
+phobos_lt_pic_flag = @phobos_lt_pic_flag@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-04-10 15:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-24 15:25 [gcc(refs/users/ibuclaw/heads/mingw)] More MSVC support Iain Buclaw
2021-03-24 16:06 Iain Buclaw
2021-03-24 16:10 Iain Buclaw
2021-04-08 13:35 Iain Buclaw
2021-04-10 15:22 Iain Buclaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).