Upgrade GCC to 5.2.0 for Windows x86 and x86_64
authorTamar Christina <tamar@zhox.com>
Wed, 12 Aug 2015 11:33:13 +0000 (13:33 +0200)
committerBen Gamari <ben@smart-cactus.org>
Wed, 12 Aug 2015 15:37:46 +0000 (17:37 +0200)
This patch does a few things

- Moved GHC x86 to MinGW-w64 (Using Awson's patch)
- Moves Both GHCs to MSYS2 toolchains
- Completely removes the dependencies on the git tarball repo
  - Downloads only the required tarball for the architecture for
    which we are building
  - Downloads the perl tarball is missing as well
  - Fixed a few bugs in the linker to fix tests on Windows

The links currently point to repo.msys2.org and GitHub, it might be
more desirable to mirror them on
http://downloads.haskell.org/~ghc/mingw/ as with the previous patch
attempt.

For more details on what the MSYS2 packages I include see #10726
(Awson's comment). but it should contain all we need
and no python or fortran, which makes the uncompressed tar a 1-2
hundreds mb smaller.

The `GCC 5.2.0` in the package supports `libgcc` as a shared library,
this is a problem since
when compiling with -shared the produced dll now has a dependency on
`libgcc_s_sjlj-1.dll`.
To solve this the flag `-static-libgcc` is now being used for all GCC
calls on windows.

Test Plan:
./validate was ran both on x86 and x86_64 windows and compared against
the baseline.

A few test were failing due to Ld no longer being noisy. These were
updated.

The changes to the configure script *should* be validated by the build
bots for the other platforms before landing

Reviewers: simonmar, awson, bgamari, austin, thomie

Reviewed By: thomie

Subscribers: #ghc_windows_task_force, thomie, awson

Differential Revision: https://phabricator.haskell.org/D1123

GHC Trac Issues: #10726, #9014, #9218, #10435

compiler/main/SysTools.hs
configure.ac
driver/gcc/gcc.c
rts/Linker.c
tarballs [deleted file]
testsuite/tests/driver/shared001.stderr
testsuite/tests/ghci/linking/ghcilink002.stderr-mingw32
testsuite/tests/ghci/linking/ghcilink005.stderr-mingw32
testsuite/tests/rts/T5435_dyn_asm.stderr-mingw32
testsuite/tests/rts/T5435_dyn_gcc.stderr-mingw32

index 8ff0d9b..080cc0b 100644 (file)
@@ -738,6 +738,30 @@ The flag is only needed on ELF systems. On Windows (PE) and Mac OS X
 
 -}
 
+{- Note [Windows static libGCC]
+
+The GCC versions being upgraded to in #10726 are configured with
+dynamic linking of libgcc supported. This results in libgcc being
+linked dynamically when a shared library is created.
+
+This introduces thus an extra dependency on GCC dll that was not
+needed before by shared libraries created with GHC. This is a particular
+issue on Windows because you get a non-obvious error due to this missing
+dependency. This dependent dll is also not commonly on your path.
+
+For this reason using the static libgcc is preferred as it preserves
+the same behaviour that existed before. There are however some very good
+reasons to have the shared version as well as described on page 181 of
+https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc.pdf :
+
+"There are several situations in which an application should use the
+ shared ‘libgcc’ instead of the static version. The most common of these
+ is when the application wishes to throw and catch exceptions across different
+ shared libraries. In that case, each of the libraries as well as the application
+ itself should use the shared ‘libgcc’. "
+
+-}
+
 neededLinkArgs :: LinkerInfo -> [Option]
 neededLinkArgs (GnuLD o)     = o
 neededLinkArgs (GnuGold o)   = o
@@ -815,7 +839,9 @@ getLinkerInfo' dflags = do
                    , "-Wl,--reduce-memory-overheads"
                      -- Increase default stack, see
                      -- Note [Windows stack usage]
-                   , "-Xlinker", "--stack=0x800000,0x800000" ]
+                     -- Force static linking of libGCC
+                     -- Note [Windows static libGCC]
+                   , "-Xlinker", "--stack=0x800000,0x800000", "-static-libgcc" ]
                _ -> do
                  -- In practice, we use the compiler as the linker here. Pass
                  -- -Wl,--version to get linker version info.
index 9b21d07..a46110b 100644 (file)
@@ -286,96 +286,135 @@ fail() {
     exit 1
 }
 
-set_up_tarballs() {
-    local tarball_repo_url="$1"
-    local tarball_dir="$2"
-
-    if ! test -d "${tarball_dir}"
+download_file() {
+    local file_url="$1"
+    local file_md5="$2"
+    local dest_file="$3"
+    local description="$4"
+    local extra_curl_opts="$5"
+    local dest_dir="$(dirname $dest_file)"
+
+    if ! test -f "${dest_file}"
     then
-        local git_cmd="git clone ${tarball_repo_url} ${tarball_dir}"
+        local curl_cmd="curl -L ${file_url} -o ${dest_file} --create-dirs -# ${extra_curl_opts}"
         if test "$TarballsAutodownload" = "NO"
         then
             echo >&2
-            echo "ERROR: Windows tarball binary distributions not found." >&2
-            echo "Please rerun configure with --enable-tarballs-autodownload, or clone the repository manually:" >&2
-            echo "  $git_cmd" >&2
+            echo "ERROR: ${description} not found." >&2
+            echo "Please rerun configure with --enable-tarballs-autodownload, or perform the download manually:" >&2
+            echo "  $curl_cmd" >&2
             exit 1
         fi
-        AC_MSG_NOTICE([Downloading Windows tarball distributions to ${tarball_dir}...])
-        $git_cmd || {
-            rm -f "${tarball_dir}"
-            fail "ERROR: Git clone failed."
+        AC_MSG_NOTICE([Downloading ${description} to ${dest_dir}...])
+        $curl_cmd || {
+            rm -f "${dest_file}"
+            fail "ERROR: Download failed."
         }
     else
-        AC_MSG_NOTICE([Using Windows tarball distributions found in ${tarball_dir}...])
+        AC_MSG_NOTICE([Using ${description} found in ${dest_dir}...])
     fi
+
+    echo "${file_md5} *${dest_file}" | md5sum --quiet -c - ||
+        fail "ERROR: ${description} appears to be corrupted, please delete it and try again."
 }
 
+
 if test "$HostOS" = "mingw32"
 then
-    test -d inplace || mkdir inplace
+    # Find the mingw-w64 7z file to extract.
+    # NB. If you update the tarballs to a new version of gcc, don't
+    # forget to tweak the paths in driver/gcc/gcc.c.
+    if test "$HostArch" = "i386"
+    then
+        mingw_arch="i686"
+        tarball_dest_dir="mingw-w64/x86"
+        tarball_mingw_dir="mingw32"
+    else
+        mingw_arch="x86_64"
+        tarball_dest_dir="mingw-w64/x86_64"
+        tarball_mingw_dir="mingw64"
+    fi
 
-    # NB. For now just run git clone on the tarball repo
-    ghc_tarball_repo='git://git.haskell.org/ghc-tarballs.git'
-    ghc_tarball_dir='ghc-tarballs'
-    set_up_tarballs "${ghc_tarball_repo}" "${ghc_tarball_dir}"
+    tarball_dir='ghc-tarballs'
+fi
+
+download_and_extract() {
+    local mingw_url="$1"
+    local file_md5sum_x86="$2"
+    local file_md5sum_x64="$3"
 
     if test "$HostArch" = "i386"
     then
-
-        # NB. If you update the tarballs to a new version of gcc, don't
-        # forget to tweak the paths in driver/gcc/gcc.c.
-        if ! test -d inplace/mingw ||
-             test inplace/mingw -ot ghc-tarballs/mingw/binutils*.tar.lzma  ||
-             test inplace/mingw -ot ghc-tarballs/mingw/gcc-core*.tar.lzma  ||
-             test inplace/mingw -ot ghc-tarballs/mingw/gcc-c++*.tar.lzma   ||
-             test inplace/mingw -ot ghc-tarballs/mingw/libgcc*.tar.gz      ||
-             test inplace/mingw -ot ghc-tarballs/mingw/libgmp*.tar.gz      ||
-             test inplace/mingw -ot ghc-tarballs/mingw/libmpc*.tar.gz      ||
-             test inplace/mingw -ot ghc-tarballs/mingw/libmpfr*.tar.gz     ||
-             test inplace/mingw -ot ghc-tarballs/mingw/libstdc*.tar.lzma   ||
-             test inplace/mingw -ot ghc-tarballs/mingw/mingwrt*-dev.tar.gz ||
-             test inplace/mingw -ot ghc-tarballs/mingw/mingwrt*-dll.tar.gz ||
-             test inplace/mingw -ot ghc-tarballs/mingw/w32api*.tar.lzma
-        then
-            AC_MSG_NOTICE([Making in-tree mingw tree])
-            rm -rf inplace/mingw
-            mkdir inplace/mingw
-            (
-                cd inplace/mingw &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/binutils*.tar.lzma  &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/gcc-core*.tar.lzma  &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/gcc-c++*.tar.lzma   &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/libgcc*.tar.lzma    &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/libgmp*.tar.lzma    &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/libmpc*.tar.lzma    &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/libmpfr*.tar.lzma   &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/libstdc*.tar.lzma   &&
-                tar -z     -xf ../../ghc-tarballs/mingw/mingwrt*-dev.tar.gz &&
-                tar -z     -xf ../../ghc-tarballs/mingw/mingwrt*-dll.tar.gz &&
-                tar --lzma -xf ../../ghc-tarballs/mingw/w32api*.tar.lzma    &&
-                mv bin/gcc.exe bin/realgcc.exe
-            )
-            PATH=`pwd`/inplace/mingw/bin:$PATH inplace/mingw/bin/realgcc.exe driver/gcc/gcc.c driver/utils/cwrapper.c driver/utils/getLocation.c -Idriver/utils -o inplace/mingw/bin/gcc.exe
-            AC_MSG_NOTICE([In-tree mingw tree created])
-        fi
+        local file_md5sum="${file_md5sum_x86}"
     else
-        # NB. If you update the tarballs to a new version of gcc, don't
-        # forget to tweak the paths in driver/gcc/gcc.c.
-        if ! test -d inplace/mingw ||
-             test inplace/mingw -ot ghc-tarballs/mingw64/*.tar.bz2
-        then
-            AC_MSG_NOTICE([Making in-tree mingw tree])
-            rm -rf inplace/mingw
-            mkdir inplace/mingw
-            (
-                cd inplace/mingw &&
-                tar -jxf ../../ghc-tarballs/mingw64/*.tar.bz2
-            )
-            AC_MSG_NOTICE([In-tree mingw tree created])
-        fi
+        local file_md5sum="${file_md5sum_x64}"
     fi
 
+    local mingw_toolchain="$(basename $mingw_url)"
+    local mingw_w64="${tarball_dir}/${tarball_dest_dir}/${mingw_toolchain}"
+
+    download_file "${mingw_url}" "${file_md5sum}" "${mingw_w64}" "${mingw_toolchain}"
+
+    # Mark the tree as needing updates by deleting the folder
+    if test -d inplace/mingw && test inplace/mingw -ot "$mingw_w64"
+    then
+        AC_MSG_NOTICE([In-tree MinGW-w64 tree requires updates...])
+        rm -rf inplace/mingw
+    fi
+}
+
+set_up_tarballs() {
+    local mingw_base_url="http://repo.msys2.org/mingw"
+    local package_prefix="mingw-w64"
+
+    local format_url="${mingw_base_url}/${mingw_arch}/${package_prefix}-${mingw_arch}"
+
+    download_and_extract "${format_url}-crt-git-5.0.0.4531.49c7046-1-any.pkg.tar.xz"           "dd39323140c0c1b3e065e9edb1a66779" "ac22cedd38229bcd57f5999e4734054f"
+    download_and_extract "${format_url}-winpthreads-git-5.0.0.4538.78dca70-1-any.pkg.tar.xz"   "0b14fe27790e94db454fbb3564e79a73" "65cf07b6f42a1a62d1844e08190cab0d"
+    download_and_extract "${format_url}-headers-git-5.0.0.4531.49c7046-1-any.pkg.tar.xz"       "6ee9e3c2f9d3e507f60ee33d19417dc2" "f49a19cdea93998c33ac90ceb9570350"
+    download_and_extract "${format_url}-libwinpthread-git-5.0.0.4538.78dca70-1-any.pkg.tar.xz" "fbb2114aa7fbb5507e21d8a2ea265cfd" "31ed10e2d8891f6251d968f81bfdd274"
+    download_and_extract "${format_url}-zlib-1.2.8-8-any.pkg.tar.xz"                           "7f519cb6defa27a90c5353160cf088d4" "6a2f4a70ccb24acca70a01da331699a6"
+    download_and_extract "${format_url}-isl-0.14.1-2-any.pkg.tar.xz"                           "4cd20fe75ed9ef03e260d529042cb742" "dc0e0a7fd23a8193cccb0bf8d7267685"
+    download_and_extract "${format_url}-mpc-1.0.3-2-any.pkg.tar.xz"                            "719e76fa7a54a8676d2e60af3bb13c45" "df1a7d4050568d83c265ae78c32ef30b"
+    download_and_extract "${format_url}-mpfr-3.1.3.p0-2-any.pkg.tar.xz"                        "e9cbd2402ac1afe6e86c102223b90dcb" "6e3b9ec27edab394aa41536839afdafe"
+    download_and_extract "${format_url}-gmp-6.0.0-3-any.pkg.tar.xz"                            "c02f9759cd0140a6d8ea69ef5a88e167" "2970d4d8b176f8f36ae2d39269b25cce"
+    download_and_extract "${format_url}-gcc-libs-5.2.0-3-any.pkg.tar.xz"                       "a9bd2e65cb350cc8f8a6deb6d3b346a8" "9c2ed24989e14fdf0c548a5215374660"
+    download_and_extract "${format_url}-binutils-2.25.1-1-any.pkg.tar.xz"                      "997e9c2166fb851916cd8ac1bc9c6180" "7cb9f5f50a7103da41f7ec7547c09707"
+    download_and_extract "${format_url}-libiconv-1.14-5-any.pkg.tar.xz"                        "2c99a163689ba8257627bb07274b3f86" "37418c6be92ef20be17cdc9fe844af35"
+    download_and_extract "${format_url}-gcc-5.2.0-3-any.pkg.tar.xz"                            "efe6d6afc18aab89dc01e7ddcd2523a6" "0b697ce61112ba6e5a3c4d565957ea4e"
+
+    # Extract all the tarballs in one go
+    if ! test -d inplace/mingw
+    then
+        AC_MSG_NOTICE([Extracting Windows toolchain from archives (may take a while)...])
+        rm -rf inplace/mingw
+        local base_dir="../${tarball_dir}/${tarball_dest_dir}"
+        ( cd inplace &&
+        find "${base_dir}" -name "*.tar.xz" -exec tar xfJ {} \; &&
+        rm ".MTREE" &&
+        rm ".PKGINFO" &&
+        cd .. ) || fail "Error: Could not extract Windows toolchains."
+
+        mv "inplace/${tarball_mingw_dir}" inplace/mingw &&
+        touch inplace/mingw
+
+        # NB. Now since the GCC is hardcoded to use /mingw32 we need to
+        # make a wrapper around it to give it the proper paths
+        mv inplace/mingw/bin/gcc.exe inplace/mingw/bin/realgcc.exe
+        PATH=`pwd`/inplace/mingw/bin:$PATH
+        inplace/mingw/bin/realgcc.exe driver/gcc/gcc.c driver/utils/cwrapper.c driver/utils/getLocation.c -Idriver/utils -o inplace/mingw/bin/gcc.exe
+
+        AC_MSG_NOTICE([In-tree MingW-w64 tree created])
+    fi
+}
+
+if test "$HostOS" = "mingw32"
+then
+    test -d inplace || mkdir inplace
+
+    # NB. Download and extract the MingW-w64 distribution if required
+    set_up_tarballs
+
     mingwbin="$hardtop/inplace/mingw/bin/"
     CC="${mingwbin}gcc.exe"
     LD="${mingwbin}ld.exe"
@@ -384,6 +423,9 @@ then
     OBJDUMP="${mingwbin}objdump.exe"
     fp_prog_ar="${mingwbin}ar.exe"
 
+    # NB. Download the perl binaries if required
+    download_file "https://github.com/ghc/ghc-tarballs/blob/master/perl/ghc-perl-1.tar.gz?raw=true" "b21d1681b61cf7a024e854096285b02e" "ghc-tarballs/perl/ghc-perl-1.tar.gz" "Windows Perl binary distributions" "--insecure"
+
     if ! test -d inplace/perl ||
          test inplace/perl -ot ghc-tarballs/perl/ghc-perl*.tar.gz
     then
index ea1f480..517b008 100644 (file)
@@ -47,9 +47,13 @@ int main(int argc, char** argv) {
        from that in preference to the in-tree files. */
     preArgv[0] = mkString("-B%s", binDir);
     preArgv[1] = mkString("-B%s/../lib", binDir);
-    preArgv[2] = mkString("-B%s/../lib/gcc/mingw32/4.5.2", binDir);
-    preArgv[3] = mkString("-B%s/../libexec/gcc/mingw32/4.5.2", binDir);
-
+#ifdef __MINGW64__
+    preArgv[2] = mkString("-B%s/../lib/gcc/x86_64-w64-mingw32/5.2.0", binDir);
+    preArgv[3] = mkString("-B%s/../libexec/gcc/x86_64-w64-mingw32/5.2.0", binDir);
+#else
+    preArgv[2] = mkString("-B%s/../lib/gcc/i686-w64-mingw32/5.2.0", binDir);
+    preArgv[3] = mkString("-B%s/../libexec/gcc/i686-w64-mingw32/5.2.0", binDir);
+#endif
     run(exePath, 4, preArgv, argc - 1, argv + 1);
 }
 
index 1b91e2f..682e5db 100644 (file)
 #elif defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS)
 #  define OBJFORMAT_PEi386
 #  include <windows.h>
+#  include <shfolder.h> /* SHGetFolderPathW */
 #  include <math.h>
 #elif defined(darwin_HOST_OS)
 #  define OBJFORMAT_MACHO
@@ -162,7 +163,7 @@ Mutex linker_mutex;
  * This protects unloaded_objects.  We have a separate mutex for this, because
  * the GC needs to access unloaded_objects in checkUnload, while the linker only
  * needs to access unloaded_objects in unloadObj(), so this allows most linker
- * operations proceed concurrently with the GC. 
+ * operations proceed concurrently with the GC.
  */
 Mutex linker_unloaded_mutex;
 #endif
@@ -227,7 +228,10 @@ static int ocGetNames_PEi386    ( ObjectCode* oc );
 static int ocResolve_PEi386     ( ObjectCode* oc );
 static int ocRunInit_PEi386     ( ObjectCode* oc );
 static void *lookupSymbolInDLLs ( unsigned char *lbl );
-static void zapTrailingAtSign   ( unsigned char *sym );
+/* See Note [mingw-w64 name decoration scheme] */
+#ifndef x86_64_HOST_ARCH
+ static void zapTrailingAtSign   ( unsigned char *sym );
+#endif
 static char *allocateImageAndTrampolines (
    pathchar* arch_name, char* member_name,
 #if defined(x86_64_HOST_ARCH)
@@ -509,7 +513,6 @@ typedef struct _RtsSymbolVal {
       SymI_HasProto(strcpy)                              \
       SymI_HasProto(strncpy)                             \
       SymI_HasProto(abort)                               \
-      RTS_WIN32_ONLY(SymI_NeedsProto(_alloca))           \
       SymI_HasProto(isxdigit)                            \
       SymI_HasProto(isupper)                             \
       SymI_HasProto(ispunct)                             \
@@ -560,251 +563,239 @@ typedef struct _RtsSymbolVal {
       SymI_HasProto(rts_InstallConsoleEvent)             \
       SymI_HasProto(rts_ConsoleHandlerDone)              \
       SymI_NeedsProto(mktime)                            \
-      RTS_WIN32_ONLY(SymI_NeedsProto(_imp___timezone))   \
-      RTS_WIN32_ONLY(SymI_NeedsProto(_imp___tzname))     \
-      RTS_WIN32_ONLY(SymI_NeedsProto(_imp__tzname))      \
-      RTS_WIN32_ONLY(SymI_NeedsProto(_imp___iob))        \
-      RTS_WIN32_ONLY(SymI_NeedsProto(_imp___osver))      \
       SymI_NeedsProto(localtime)                         \
       SymI_NeedsProto(gmtime)                            \
       SymI_NeedsProto(opendir)                           \
       SymI_NeedsProto(readdir)                           \
       SymI_NeedsProto(rewinddir)                         \
-      RTS_WIN32_ONLY(SymI_NeedsProto(_imp____mb_cur_max)) \
-      RTS_WIN32_ONLY(SymI_NeedsProto(_imp___pctype))     \
-      RTS_WIN32_ONLY(SymI_NeedsProto(__chkstk))          \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp___iob_func))  \
+      RTS_WIN32_ONLY(SymI_NeedsProto(__chkstk_ms))       \
       RTS_WIN64_ONLY(SymI_NeedsProto(___chkstk_ms))      \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_localeconv))  \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_islower))     \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_isspace))     \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_isxdigit))    \
-      RTS_WIN64_ONLY(SymI_HasProto(close))               \
-      RTS_WIN64_ONLY(SymI_HasProto(read))                \
-      RTS_WIN64_ONLY(SymI_HasProto(dup))                 \
-      RTS_WIN64_ONLY(SymI_HasProto(dup2))                \
-      RTS_WIN64_ONLY(SymI_HasProto(write))               \
+      SymI_NeedsProto(localeconv)                        \
+      SymI_HasProto(close)                               \
+      SymI_HasProto(read)                                \
+      SymI_HasProto(dup)                                 \
+      SymI_HasProto(dup2)                                \
+      SymI_HasProto(write)                               \
       SymI_NeedsProto(getpid)                            \
-      RTS_WIN64_ONLY(SymI_HasProto(access))              \
+      SymI_HasProto(access)                              \
       SymI_HasProto(chmod)                               \
-      RTS_WIN64_ONLY(SymI_HasProto(creat))               \
-      RTS_WIN64_ONLY(SymI_HasProto(umask))               \
+      SymI_HasProto(creat)                               \
+      SymI_HasProto(umask)                               \
       SymI_HasProto(unlink)                              \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__errno))      \
-      RTS_WIN64_ONLY(SymI_NeedsProto(ftruncate64))       \
-      RTS_WIN64_ONLY(SymI_HasProto(setmode))             \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__wstat64))    \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__fstat64))    \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__wsopen))     \
+      SymI_HasProto(_errno)                              \
+      SymI_NeedsProto(ftruncate64)                       \
+      SymI_HasProto(setmode)                             \
+      SymI_HasProto(_wstat64)                            \
+      SymI_HasProto(_fstat64)                            \
+      SymI_HasProto(_wsopen)                             \
+      RTS_WIN32_ONLY(SymI_HasProto(_imp___environ))      \
       RTS_WIN64_ONLY(SymI_HasProto(__imp__environ))      \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetFileAttributesA))          \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetFileInformationByHandle))  \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetFileType))                 \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetLastError))                \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_QueryPerformanceFrequency))   \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_QueryPerformanceCounter))     \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetTickCount))                \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_WaitForSingleObject))         \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_PeekConsoleInputA))           \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_ReadConsoleInputA))           \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_PeekNamedPipe))               \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__isatty))                     \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_select))                      \
-      RTS_WIN64_ONLY(SymI_HasProto(isatty))                              \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__get_osfhandle))              \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetConsoleMode))              \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_SetConsoleMode))              \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_FlushConsoleInputBuffer))     \
-      RTS_WIN64_ONLY(SymI_HasProto(free))                                \
-      RTS_WIN64_ONLY(SymI_NeedsProto(raise))                             \
-      RTS_WIN64_ONLY(SymI_NeedsProto(_getpid))                           \
-      RTS_WIN64_ONLY(SymI_HasProto(getc))                                \
-      RTS_WIN64_ONLY(SymI_HasProto(ungetc))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(puts))                                \
-      RTS_WIN64_ONLY(SymI_HasProto(putc))                                \
-      RTS_WIN64_ONLY(SymI_HasProto(putchar))                             \
-      RTS_WIN64_ONLY(SymI_HasProto(fputc))                               \
-      RTS_WIN64_ONLY(SymI_HasProto(fread))                               \
-      RTS_WIN64_ONLY(SymI_HasProto(fwrite))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(ferror))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(printf))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(fprintf))                             \
-      RTS_WIN64_ONLY(SymI_HasProto(sprintf))                             \
-      RTS_WIN64_ONLY(SymI_HasProto(vsprintf))                            \
-      RTS_WIN64_ONLY(SymI_HasProto(sscanf))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(ldexp))                               \
-      RTS_WIN64_ONLY(SymI_HasProto(strlen))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(strnlen))                             \
-      RTS_WIN64_ONLY(SymI_HasProto(strchr))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(strtol))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(strerror))                            \
-      RTS_WIN64_ONLY(SymI_HasProto(memchr))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(memcmp))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(wcscpy))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(wcslen))                              \
-      RTS_WIN64_ONLY(SymI_HasProto(_lseeki64))                           \
-      RTS_WIN64_ONLY(SymI_HasProto(_wchmod))                             \
-      RTS_WIN64_ONLY(SymI_HasProto(closesocket))                         \
-      RTS_WIN64_ONLY(SymI_HasProto(send))                                \
-      RTS_WIN64_ONLY(SymI_HasProto(recv))                                \
-      RTS_WIN64_ONLY(SymI_HasProto(bsearch))                             \
-      RTS_WIN64_ONLY(SymI_HasProto(CommandLineToArgvW))                  \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateBitmap))                        \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateBitmapIndirect))                \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateCompatibleBitmap))              \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateDIBPatternBrushPt))             \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateDIBitmap))                      \
-      RTS_WIN64_ONLY(SymI_HasProto(SetBitmapDimensionEx))                \
-      RTS_WIN64_ONLY(SymI_HasProto(GetBitmapDimensionEx))                \
-      RTS_WIN64_ONLY(SymI_HasProto(GetStockObject))                      \
-      RTS_WIN64_ONLY(SymI_HasProto(GetObjectW))                          \
-      RTS_WIN64_ONLY(SymI_HasProto(DeleteObject))                        \
-      RTS_WIN64_ONLY(SymI_HasProto(SetDIBits))                           \
-      RTS_WIN64_ONLY(SymI_HasProto(GetDIBits))                           \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateSolidBrush))                    \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateHatchBrush))                    \
-      RTS_WIN64_ONLY(SymI_HasProto(CreatePatternBrush))                  \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateFontW))                         \
-      RTS_WIN64_ONLY(SymI_HasProto(AngleArc)) \
-      RTS_WIN64_ONLY(SymI_HasProto(Arc)) \
-      RTS_WIN64_ONLY(SymI_HasProto(ArcTo)) \
-      RTS_WIN64_ONLY(SymI_HasProto(BeginPath)) \
-      RTS_WIN64_ONLY(SymI_HasProto(BitBlt)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CancelDC)) \
-      RTS_WIN64_ONLY(SymI_HasProto(Chord)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CloseFigure)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CombineRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateCompatibleDC)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateEllipticRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateEllipticRgnIndirect)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CreatePen)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CreatePolygonRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateRectRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateRectRgnIndirect)) \
-      RTS_WIN64_ONLY(SymI_HasProto(CreateRoundRectRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(DeleteDC)) \
-      RTS_WIN64_ONLY(SymI_HasProto(Ellipse)) \
-      RTS_WIN64_ONLY(SymI_HasProto(EndPath)) \
-      RTS_WIN64_ONLY(SymI_HasProto(EqualRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(ExtSelectClipRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(FillPath)) \
-      RTS_WIN64_ONLY(SymI_HasProto(FillRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(FlattenPath)) \
-      RTS_WIN64_ONLY(SymI_HasProto(FrameRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetArcDirection)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetBkColor)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetBkMode)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetBrushOrgEx)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetCurrentObject)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetDCOrgEx)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetGraphicsMode)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetMiterLimit)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetPolyFillMode)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetRgnBox)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetStretchBltMode)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetTextAlign)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetTextCharacterExtra)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetTextColor)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetTextExtentPoint32W)) \
-      RTS_WIN64_ONLY(SymI_HasProto(InvertRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(LineTo)) \
-      RTS_WIN64_ONLY(SymI_HasProto(MaskBlt)) \
-      RTS_WIN64_ONLY(SymI_HasProto(MoveToEx)) \
-      RTS_WIN64_ONLY(SymI_HasProto(OffsetRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(PaintRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(PathToRegion)) \
-      RTS_WIN64_ONLY(SymI_HasProto(Pie)) \
-      RTS_WIN64_ONLY(SymI_HasProto(PlgBlt)) \
-      RTS_WIN64_ONLY(SymI_HasProto(PolyBezier)) \
-      RTS_WIN64_ONLY(SymI_HasProto(PolyBezierTo)) \
-      RTS_WIN64_ONLY(SymI_HasProto(Polygon)) \
-      RTS_WIN64_ONLY(SymI_HasProto(Polyline)) \
-      RTS_WIN64_ONLY(SymI_HasProto(PolylineTo)) \
-      RTS_WIN64_ONLY(SymI_HasProto(PtInRegion)) \
-      RTS_WIN64_ONLY(SymI_HasProto(Rectangle)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RectInRegion)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RestoreDC)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RoundRect)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SaveDC)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SelectClipPath)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SelectClipRgn)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SelectObject)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SelectPalette)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetArcDirection)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetBkColor)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetBkMode)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetBrushOrgEx)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetGraphicsMode)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetMiterLimit)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetPolyFillMode)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetStretchBltMode)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetTextAlign)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetTextCharacterExtra)) \
-      RTS_WIN64_ONLY(SymI_HasProto(SetTextColor)) \
-      RTS_WIN64_ONLY(SymI_HasProto(StretchBlt)) \
-      RTS_WIN64_ONLY(SymI_HasProto(StrokeAndFillPath)) \
-      RTS_WIN64_ONLY(SymI_HasProto(StrokePath)) \
-      RTS_WIN64_ONLY(SymI_HasProto(TextOutW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(timeGetTime)) \
-      RTS_WIN64_ONLY(SymI_HasProto(WidenPath)) \
-      RTS_WIN64_ONLY(SymI_HasProto(GetFileSecurityW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegCloseKey)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegConnectRegistryW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegCreateKeyExW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegCreateKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegDeleteKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegDeleteValueW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegEnumKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegEnumValueW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegFlushKey)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegLoadKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegNotifyChangeKeyValue)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegOpenKeyExW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegOpenKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegQueryInfoKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegQueryValueExW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegQueryValueW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegReplaceKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegRestoreKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegSaveKeyW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegSetValueExW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegSetValueW)) \
-      RTS_WIN64_ONLY(SymI_HasProto(RegUnLoadKeyW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(SHGetFolderPathW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_SetWindowLongPtrW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetWindowLongPtrW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_MenuItemFromPoint)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_ChildWindowFromPoint)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_ChildWindowFromPointEx)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_DeleteObject)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_UnmapViewOfFile)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_CloseHandle)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_FreeLibrary)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetMessageW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_TranslateMessage)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_DispatchMessageW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_DefWindowProcW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetDIBits)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GlobalAlloc)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GlobalFree)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_CreateFileW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_WriteFile)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_CreateCompatibleBitmap)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_SelectObject)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_Polygon)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_FormatMessageW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__localtime64)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__tzname)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__timezone)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_CreatePipe)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_SetHandleInformation)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetStdHandle)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetCurrentProcess)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_DuplicateHandle)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_CreateProcessW)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_TerminateProcess)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp__open_osfhandle)) \
-      RTS_WIN64_ONLY(SymI_NeedsProto(__imp_GetExitCodeProcess)) \
+      RTS_WIN32_ONLY(SymI_HasProto(_imp___iob))          \
+      RTS_WIN64_ONLY(SymI_HasProto(__iob_func))          \
+      SymI_HasProto(GetFileAttributesA)                  \
+      SymI_HasProto(GetFileInformationByHandle)          \
+      SymI_HasProto(GetFileType)                         \
+      SymI_HasProto(GetLastError)                        \
+      SymI_HasProto(QueryPerformanceFrequency)           \
+      SymI_HasProto(QueryPerformanceCounter)             \
+      SymI_HasProto(GetTickCount)                        \
+      SymI_HasProto(WaitForSingleObject)                 \
+      SymI_HasProto(PeekConsoleInputA)                   \
+      SymI_HasProto(ReadConsoleInputA)                   \
+      SymI_HasProto(PeekNamedPipe)                       \
+      SymI_HasProto(select)                              \
+      SymI_HasProto(isatty)                              \
+      SymI_HasProto(_get_osfhandle)                      \
+      SymI_HasProto(GetConsoleMode)                      \
+      SymI_HasProto(SetConsoleMode)                      \
+      SymI_HasProto(FlushConsoleInputBuffer)             \
+      SymI_HasProto(free)                                \
+      SymI_NeedsProto(raise)                             \
+      SymI_NeedsProto(_getpid)                           \
+      SymI_HasProto(getc)                                \
+      SymI_HasProto(ungetc)                              \
+      SymI_HasProto(puts)                                \
+      SymI_HasProto(putc)                                \
+      SymI_HasProto(putchar)                             \
+      SymI_HasProto(fputc)                               \
+      SymI_HasProto(fread)                               \
+      SymI_HasProto(fwrite)                              \
+      SymI_HasProto(ferror)                              \
+      SymI_HasProto(printf)                              \
+      SymI_HasProto(fprintf)                             \
+      SymI_HasProto(sprintf)                             \
+      SymI_HasProto(vsprintf)                            \
+      SymI_HasProto(sscanf)                              \
+      SymI_HasProto(ldexp)                               \
+      SymI_HasProto(strlen)                              \
+      SymI_HasProto(strnlen)                             \
+      SymI_HasProto(strchr)                              \
+      SymI_HasProto(strtol)                              \
+      SymI_HasProto(strerror)                            \
+      SymI_HasProto(memchr)                              \
+      SymI_HasProto(memcmp)                              \
+      SymI_HasProto(wcscpy)                              \
+      SymI_HasProto(wcslen)                              \
+      SymI_HasProto(_lseeki64)                           \
+      SymI_HasProto(_wchmod)                             \
+      SymI_HasProto(closesocket)                         \
+      SymI_HasProto(send)                                \
+      SymI_HasProto(recv)                                \
+      SymI_HasProto(bsearch)                             \
+      SymI_HasProto(CommandLineToArgvW)                  \
+      SymI_HasProto(CreateBitmap)                        \
+      SymI_HasProto(CreateBitmapIndirect)                \
+      SymI_HasProto(CreateCompatibleBitmap)              \
+      SymI_HasProto(CreateDIBPatternBrushPt)             \
+      SymI_HasProto(CreateDIBitmap)                      \
+      SymI_HasProto(SetBitmapDimensionEx)                \
+      SymI_HasProto(GetBitmapDimensionEx)                \
+      SymI_HasProto(GetStockObject)                      \
+      SymI_HasProto(GetObjectW)                          \
+      SymI_HasProto(DeleteObject)                        \
+      SymI_HasProto(SetDIBits)                           \
+      SymI_HasProto(GetDIBits)                           \
+      SymI_HasProto(CreateSolidBrush)                    \
+      SymI_HasProto(CreateHatchBrush)                    \
+      SymI_HasProto(CreatePatternBrush)                  \
+      SymI_HasProto(CreateFontW)                         \
+      SymI_HasProto(AngleArc)                            \
+      SymI_HasProto(Arc)                                 \
+      SymI_HasProto(ArcTo)                               \
+      SymI_HasProto(BeginPath)                           \
+      SymI_HasProto(BitBlt)                              \
+      SymI_HasProto(CancelDC)                            \
+      SymI_HasProto(Chord)                               \
+      SymI_HasProto(CloseFigure)                         \
+      SymI_HasProto(CombineRgn)                          \
+      SymI_HasProto(CreateCompatibleDC)                  \
+      SymI_HasProto(CreateEllipticRgn)                   \
+      SymI_HasProto(CreateEllipticRgnIndirect)           \
+      SymI_HasProto(CreatePen)                           \
+      SymI_HasProto(CreatePolygonRgn)                    \
+      SymI_HasProto(CreateRectRgn)                       \
+      SymI_HasProto(CreateRectRgnIndirect)               \
+      SymI_HasProto(CreateRoundRectRgn)                  \
+      SymI_HasProto(DeleteDC)                            \
+      SymI_HasProto(Ellipse)                             \
+      SymI_HasProto(EndPath)                             \
+      SymI_HasProto(EqualRgn)                            \
+      SymI_HasProto(ExtSelectClipRgn)                    \
+      SymI_HasProto(FillPath)                            \
+      SymI_HasProto(FillRgn)                             \
+      SymI_HasProto(FlattenPath)                         \
+      SymI_HasProto(FrameRgn)                            \
+      SymI_HasProto(GetArcDirection)                     \
+      SymI_HasProto(GetBkColor)                          \
+      SymI_HasProto(GetBkMode)                           \
+      SymI_HasProto(GetBrushOrgEx)                       \
+      SymI_HasProto(GetCurrentObject)                    \
+      SymI_HasProto(GetDCOrgEx)                          \
+      SymI_HasProto(GetGraphicsMode)                     \
+      SymI_HasProto(GetMiterLimit)                       \
+      SymI_HasProto(GetPolyFillMode)                     \
+      SymI_HasProto(GetRgnBox)                           \
+      SymI_HasProto(GetStretchBltMode)                   \
+      SymI_HasProto(GetTextAlign)                        \
+      SymI_HasProto(GetTextCharacterExtra)               \
+      SymI_HasProto(GetTextColor)                        \
+      SymI_HasProto(GetTextExtentPoint32W)               \
+      SymI_HasProto(InvertRgn)                           \
+      SymI_HasProto(LineTo)                              \
+      SymI_HasProto(MaskBlt)                             \
+      SymI_HasProto(MoveToEx)                            \
+      SymI_HasProto(OffsetRgn)                           \
+      SymI_HasProto(PaintRgn)                            \
+      SymI_HasProto(PathToRegion)                        \
+      SymI_HasProto(Pie)                                 \
+      SymI_HasProto(PlgBlt)                              \
+      SymI_HasProto(PolyBezier)                          \
+      SymI_HasProto(PolyBezierTo)                        \
+      SymI_HasProto(Polygon)                             \
+      SymI_HasProto(Polyline)                            \
+      SymI_HasProto(PolylineTo)                          \
+      SymI_HasProto(PtInRegion)                          \
+      SymI_HasProto(Rectangle)                           \
+      SymI_HasProto(RectInRegion)                        \
+      SymI_HasProto(RestoreDC)                           \
+      SymI_HasProto(RoundRect)                           \
+      SymI_HasProto(SaveDC)                              \
+      SymI_HasProto(SelectClipPath)                      \
+      SymI_HasProto(SelectClipRgn)                       \
+      SymI_HasProto(SelectObject)                        \
+      SymI_HasProto(SelectPalette)                       \
+      SymI_HasProto(SetArcDirection)                     \
+      SymI_HasProto(SetBkColor)                          \
+      SymI_HasProto(SetBkMode)                           \
+      SymI_HasProto(SetBrushOrgEx)                       \
+      SymI_HasProto(SetGraphicsMode)                     \
+      SymI_HasProto(SetMiterLimit)                       \
+      SymI_HasProto(SetPolyFillMode)                     \
+      SymI_HasProto(SetStretchBltMode)                   \
+      SymI_HasProto(SetTextAlign)                        \
+      SymI_HasProto(SetTextCharacterExtra)               \
+      SymI_HasProto(SetTextColor)                        \
+      SymI_HasProto(StretchBlt)                          \
+      SymI_HasProto(StrokeAndFillPath)                   \
+      SymI_HasProto(StrokePath)                          \
+      SymI_HasProto(TextOutW)                            \
+      SymI_HasProto(timeGetTime)                         \
+      SymI_HasProto(WidenPath)                           \
+      SymI_HasProto(GetFileSecurityW)                    \
+      SymI_HasProto(RegCloseKey)                         \
+      SymI_HasProto(RegConnectRegistryW)                 \
+      SymI_HasProto(RegCreateKeyExW)                     \
+      SymI_HasProto(RegCreateKeyW)                       \
+      SymI_HasProto(RegDeleteKeyW)                       \
+      SymI_HasProto(RegDeleteValueW)                     \
+      SymI_HasProto(RegEnumKeyW)                         \
+      SymI_HasProto(RegEnumValueW)                       \
+      SymI_HasProto(RegFlushKey)                         \
+      SymI_HasProto(RegLoadKeyW)                         \
+      SymI_HasProto(RegNotifyChangeKeyValue)             \
+      SymI_HasProto(RegOpenKeyExW)                       \
+      SymI_HasProto(RegOpenKeyW)                         \
+      SymI_HasProto(RegQueryInfoKeyW)                    \
+      SymI_HasProto(RegQueryValueExW)                    \
+      SymI_HasProto(RegQueryValueW)                      \
+      SymI_HasProto(RegReplaceKeyW)                      \
+      SymI_HasProto(RegRestoreKeyW)                      \
+      SymI_HasProto(RegSaveKeyW)                         \
+      SymI_HasProto(RegSetValueExW)                      \
+      SymI_HasProto(RegSetValueW)                        \
+      SymI_HasProto(RegUnLoadKeyW)                       \
+      SymI_HasProto(SHGetFolderPathW)                    \
+      RTS_WIN32_ONLY(SymI_HasProto(SetWindowLongW))      \
+      RTS_WIN32_ONLY(SymI_HasProto(GetWindowLongW))      \
+      RTS_WIN64_ONLY(SymI_HasProto(SetWindowLongPtrW))   \
+      RTS_WIN64_ONLY(SymI_HasProto(GetWindowLongPtrW))   \
+      SymI_HasProto(MenuItemFromPoint)                   \
+      SymI_HasProto(ChildWindowFromPoint)                \
+      SymI_HasProto(ChildWindowFromPointEx)              \
+      SymI_HasProto(UnmapViewOfFile)                     \
+      SymI_HasProto(CloseHandle)                         \
+      SymI_HasProto(FreeLibrary)                         \
+      SymI_HasProto(GetMessageW)                         \
+      SymI_HasProto(TranslateMessage)                    \
+      SymI_HasProto(DispatchMessageW)                    \
+      SymI_HasProto(DefWindowProcW)                      \
+      SymI_HasProto(GlobalAlloc)                         \
+      SymI_HasProto(GlobalFree)                          \
+      SymI_HasProto(CreateFileW)                         \
+      SymI_HasProto(WriteFile)                           \
+      SymI_HasProto(FormatMessageW)                      \
+      SymI_NeedsProto(_localtime64)                      \
+      SymI_NeedsProto(_tzname)                           \
+      SymI_NeedsProto(_timezone)                         \
+      SymI_HasProto(CreatePipe)                          \
+      SymI_HasProto(SetHandleInformation)                \
+      SymI_HasProto(GetStdHandle)                        \
+      SymI_HasProto(GetCurrentProcess)                   \
+      SymI_HasProto(DuplicateHandle)                     \
+      SymI_HasProto(CreateProcessW)                      \
+      SymI_HasProto(TerminateProcess)                    \
+      SymI_HasProto(_open_osfhandle)                     \
+      SymI_HasProto(GetExitCodeProcess)                  \
       RTS_MINGW_GETTIMEOFDAY_SYM                         \
       SymI_NeedsProto(closedir)
 
@@ -2111,14 +2102,10 @@ static void* lookupSymbol_ (char *lbl)
 #       elif defined(OBJFORMAT_PEi386)
         void* sym;
 
-        sym = lookupSymbolInDLLs((unsigned char*)lbl);
-        if (sym != NULL) {
-            return sym;
-        };
-
-        // Also try looking up the symbol without the @N suffix.  Some
-        // DLLs have the suffixes on their symbols, some don't.
-        zapTrailingAtSign ( (unsigned char*)lbl );
+/* See Note [mingw-w64 name decoration scheme] */
+#ifndef x86_64_HOST_ARCH
+         zapTrailingAtSign ( (unsigned char*)lbl );
+#endif
         sym = lookupSymbolInDLLs((unsigned char*)lbl);
         return sym; // might be NULL if not found
 
@@ -2401,6 +2388,7 @@ void freeObjectCode (ObjectCode *oc)
       stgFree(ia);
       ia = ia_next;
     }
+    indirects = NULL;
 
 #endif
 
@@ -3770,6 +3758,7 @@ typedef
 /* From PE spec doc, section 4.1 */
 #define MYIMAGE_SCN_CNT_CODE             0x00000020
 #define MYIMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define MYIMAGE_SCN_LNK_COMDAT           0x00001000
 #define MYIMAGE_SCN_LNK_NRELOC_OVFL      0x01000000
 
 /* From PE spec doc, section 5.2.1 */
@@ -3994,6 +3983,8 @@ findPEi386SectionCalled ( ObjectCode* oc,  UChar* name, UChar* strtab )
    return NULL;
 }
 
+/* See Note [mingw-w64 name decoration scheme] */
+#ifndef x86_64_HOST_ARCH
 static void
 zapTrailingAtSign ( UChar* sym )
 {
@@ -4008,6 +3999,30 @@ zapTrailingAtSign ( UChar* sym )
    if (j > 0 && sym[j] == '@' && j != i) sym[j] = 0;
 #  undef my_isdigit
 }
+#endif
+
+/* See Note [mingw-w64 name decoration scheme] */
+#ifndef x86_64_HOST_ARCH
+#define STRIP_LEADING_UNDERSCORE 1
+#else
+#define STRIP_LEADING_UNDERSCORE 0
+#endif
+
+/*
+  Note [mingw-w64 name decoration scheme]
+
+  What's going on with name decoration? Well, original code
+  have some crufty and ad-hocish paths related mostly to very old
+  mingw gcc/binutils/runtime combinations. Now mingw-w64 offers pretty
+  uniform and MS-compatible decoration scheme across its tools and runtime.
+
+  The scheme is pretty straightforward: on 32 bit objects symbols are exported
+  with underscore prepended (and @ + stack size suffix appended for stdcall
+  functions), on 64 bits no underscore is prepended and no suffix is appended
+  because we have no stdcall convention on 64 bits.
+
+  See #9218
+*/
 
 static void *
 lookupSymbolInDLLs ( UChar *lbl )
@@ -4018,17 +4033,10 @@ lookupSymbolInDLLs ( UChar *lbl )
     for (o_dll = opened_dlls; o_dll != NULL; o_dll = o_dll->next) {
         /* debugBelch("look in %ls for %s\n", o_dll->name, lbl); */
 
-        if (lbl[0] == '_') {
-            /* HACK: if the name has an initial underscore, try stripping
-               it off & look that up first. I've yet to verify whether there's
-               a Rule that governs whether an initial '_' *should always* be
-               stripped off when mapping from import lib name to the DLL name.
-            */
-            sym = GetProcAddress(o_dll->instance, (char*)(lbl+1));
-            if (sym != NULL) {
-                /*debugBelch("found %s in %s\n", lbl+1,o_dll->name);*/
-                return sym;
-            }
+        sym = GetProcAddress(o_dll->instance, (char*)(lbl+STRIP_LEADING_UNDERSCORE));
+        if (sym != NULL) {
+            /*debugBelch("found %s in %s\n", lbl+1,o_dll->name);*/
+            return sym;
         }
 
         /* Ticket #2283.
@@ -4039,7 +4047,7 @@ lookupSymbolInDLLs ( UChar *lbl )
              the same semantics as in __imp_foo = GetProcAddress(..., "foo")
          */
         if (sym == NULL && strncmp ((const char*)lbl, "__imp_", 6) == 0) {
-            sym = GetProcAddress(o_dll->instance, (char*)(lbl+6));
+            sym = GetProcAddress(o_dll->instance, (char*)(lbl+6+STRIP_LEADING_UNDERSCORE));
             if (sym != NULL) {
                 IndirectAddr* ret;
                 ret = stgMallocBytes( sizeof(IndirectAddr), "lookupSymbolInDLLs" );
@@ -4048,7 +4056,7 @@ lookupSymbolInDLLs ( UChar *lbl )
                 indirects = ret;
                 IF_DEBUG(linker,
                   debugBelch("warning: %s from %S is linked instead of %s",
-                             (char*)(lbl+6), o_dll->name, (char*)lbl));
+                             (char*)(lbl+6+STRIP_LEADING_UNDERSCORE), o_dll->name, (char*)lbl));
                 return (void*) & ret->addr;
                }
         }
@@ -4374,11 +4382,14 @@ ocGetNames_PEi386 ( ObjectCode* oc )
          kind = SECTIONKIND_CODE_OR_RODATA;
 #     endif
 
-      if (0==strcmp(".text",(char*)secname) ||
-          0==strcmp(".text.startup",(char*)secname) ||
+      if (0==strcmp(".text",(char*)secname)           ||
+          0==strcmp(".text.startup",(char*)secname)   ||
           0==strcmp(".text.unlikely", (char*)secname) ||
-          0==strcmp(".rdata",(char*)secname)||
-          0==strcmp(".eh_frame", (char*)secname)||
+          0==strncmp(".text$",(char*)secname, 6)      ||
+          /* See Note [.rdata section group] */
+          (0==strncmp(".rdata",(char*)secname, 6) &&
+           0!=strcmp(".rdata$zzz", (char*)secname))   ||
+          0==strcmp(".eh_frame", (char*)secname)      ||
           0==strcmp(".rodata",(char*)secname))
          kind = SECTIONKIND_CODE_OR_RODATA;
       if (0==strcmp(".data",(char*)secname) ||
@@ -4406,6 +4417,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
           && 0!= strncmp(".debug", (char*)secname, 6)
           /* ignore unknown section that appeared in gcc 3.4.5(?) */
           && 0!= strcmp(".reloc", (char*)secname)
+          /* See Note [.rdata section group] */
           && 0 != strcmp(".rdata$zzz", (char*)secname)
           /* ignore linker directive sections */
           && 0 != strcmp(".drectve", (char*)secname)
@@ -4427,6 +4439,24 @@ ocGetNames_PEi386 ( ObjectCode* oc )
       stgFree(secname);
    }
 
+/*
+  Note [.rdata section group]
+
+  Most of the sections .rdata group section we want to load
+  and consider a SECTIONKIND_CODE_OR_RODATA section.
+  With the exception of .rdata$zzz which is just a section
+  containing the GCC version:
+
+  Contents of section .rdata$zzz:
+   0000 4743433a 20285265 76332c20 4275696c  GCC: (Rev3, Buil
+   0010 74206279 204d5359 53322070 726f6a65  t by MSYS2 proje
+   0020 63742920 352e322e 30000000 00000000  ct) 5.2.0.......
+
+  Because we're inspecting the group members one by one, we shouldn't
+  consider this code since we can't load it. Instead consider it an OTHER
+  section.
+*/
+
    /* Copy exported symbols into the ObjectCode. */
 
    oc->n_symbols = hdr->NumberOfSymbols;
@@ -4445,8 +4475,8 @@ ocGetNames_PEi386 ( ObjectCode* oc )
 
       addr  = NULL;
 
-      if (symtab_i->StorageClass == MYIMAGE_SYM_CLASS_EXTERNAL
-          && symtab_i->SectionNumber != MYIMAGE_SYM_UNDEFINED) {
+      HsBool isWeak = HS_BOOL_FALSE;
+      if (symtab_i->SectionNumber != MYIMAGE_SYM_UNDEFINED) {
          /* This symbol is global and defined, viz, exported */
          /* for MYIMAGE_SYMCLASS_EXTERNAL
                 && !MYIMAGE_SYM_UNDEFINED,
@@ -4457,9 +4487,17 @@ ocGetNames_PEi386 ( ObjectCode* oc )
             = (COFF_section*) myindex ( sizeof_COFF_section,
                                         sectab,
                                         symtab_i->SectionNumber-1 );
-         addr = ((UChar*)(oc->image))
-                + (sectabent->PointerToRawData
-                   + symtab_i->Value);
+         if (symtab_i->StorageClass == MYIMAGE_SYM_CLASS_EXTERNAL
+            || (   symtab_i->StorageClass == MYIMAGE_SYM_CLASS_STATIC
+                && sectabent->Characteristics & MYIMAGE_SCN_LNK_COMDAT)
+            ) {
+                 addr = ((UChar*)(oc->image))
+                        + (sectabent->PointerToRawData
+                           + symtab_i->Value);
+                 if (sectabent->Characteristics & MYIMAGE_SCN_LNK_COMDAT) {
+                    isWeak = HS_BOOL_TRUE;
+              }
+         }
       }
       else
       if (symtab_i->SectionNumber == MYIMAGE_SYM_UNDEFINED
@@ -4482,7 +4520,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
          /* cstring_from_COFF_symbol_name always succeeds. */
          oc->symbols[i] = (char*)sname;
          if (! ghciInsertSymbolTable(oc->fileName, symhash, (char*)sname, addr,
-                                     HS_BOOL_FALSE, oc)) {
+                                     isWeak, oc)) {
              return 0;
          }
       } else {
diff --git a/tarballs b/tarballs
deleted file mode 100644 (file)
index 5a7b72d..0000000
--- a/tarballs
+++ /dev/null
@@ -1,13 +0,0 @@
-# The format of the lines in this file is:
-#   localpath    remotepath
-# where
-#   * localpath is where to put the repository in a checked out tree,
-#   * remotepath is where the tarball is in the central repository.
-#
-# Lines that start with a '#' are comments.
-mingw/binutils-2.19.1-mingw32-bin.tar.gz    ghc-tarballs/binutils-2.19.1-mingw32-bin.tar.gz
-mingw/gcc-core-3.4.5-20060117-3.tar.gz      ghc-tarballs/gcc-core-3.4.5-20060117-3.tar.gz
-mingw/mingw-runtime-3.14.tar.gz             ghc-tarballs/mingw-runtime-3.14.tar.gz
-mingw/w32api-3.13-mingw32-dev.tar.gz        ghc-tarballs/w32api-3.13-mingw32-dev.tar.gz
-libffi/tarball/libffi-3.0.8.tar.gz          ghc-tarballs/libffi-3.0.8.tar.gz
-