diff mbox series

[committed] libphobos: Merge upstream druntime 89f870b7, phobos e6907ff3e

Message ID 20210419173251.3760235-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] libphobos: Merge upstream druntime 89f870b7, phobos e6907ff3e | expand

Commit Message

Iain Buclaw April 19, 2021, 5:32 p.m. UTC
Hi,

This patch merges the D runtime library with upstream druntime 89f870b7,
and phobos e6907ff3e.  Synchronizes the C bindings with the latest port
fixes in upstream druntime, and adds a Config.stderrPassThrough enum
member to std.process (fixing PR98494).

Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and
committed to mainline.

---
libphobos/ChangeLog:

	PR d/98494
	* libdruntime/MERGE: Merge upstream druntime 89f870b7.
	* src/MERGE: Merge upstream phobos e6907ff3e.
---
 libphobos/libdruntime/MERGE                   |   2 +-
 libphobos/libdruntime/core/stdc/config.d      |  39 +--
 libphobos/libdruntime/core/stdc/math.d        | 295 +++++++++---------
 libphobos/libdruntime/core/stdc/stdio.d       |  82 ++++-
 libphobos/libdruntime/core/stdc/stdlib.d      |  27 +-
 libphobos/libdruntime/core/stdc/tgmath.d      |   7 +
 .../core/sys/darwin/mach/thread_act.d         |  66 ++++
 .../core/sys/openbsd/sys/link_elf.d           |   5 +
 libphobos/libdruntime/core/sys/posix/stdio.d  |  50 +++
 libphobos/libdruntime/core/sys/windows/com.d  |   4 +-
 .../libdruntime/core/sys/windows/dbghelp.d    |   2 +-
 libphobos/libdruntime/core/sys/windows/dll.d  |   4 +-
 .../libdruntime/core/sys/windows/threadaux.d  |   4 +-
 libphobos/libdruntime/core/thread/fiber.d     |  42 ++-
 libphobos/libdruntime/core/thread/osthread.d  |  44 ++-
 .../libdruntime/core/thread/threadbase.d      |   3 +
 libphobos/src/MERGE                           |   2 +-
 libphobos/src/std/process.d                   |  51 ++-
 18 files changed, 520 insertions(+), 209 deletions(-)
diff mbox series

Patch

diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index d839a08c19b..25cbb955ba2 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@ 
-1134b71039881464e9bf021836d82796b3a1fcfc
+89f870b76710a4cfa96f711bb5b14a7439c5c2a7
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/core/stdc/config.d b/libphobos/libdruntime/core/stdc/config.d
index 802f5b6fb21..44bb7077b59 100644
--- a/libphobos/libdruntime/core/stdc/config.d
+++ b/libphobos/libdruntime/core/stdc/config.d
@@ -186,7 +186,18 @@  else version (Posix)
   }
 }
 
-version (CRuntime_Microsoft)
+version (GNU)
+    alias c_long_double = real;
+else version (LDC)
+    alias c_long_double = real; // 64-bit real for MSVC targets
+else version (SDC)
+{
+    version (X86)
+        alias c_long_double = real;
+    else version (X86_64)
+        alias c_long_double = real;
+}
+else version (CRuntime_Microsoft)
 {
     /* long double is 64 bits, not 80 bits, but is mangled differently
      * than double. To distinguish double from long double, create a wrapper to represent
@@ -222,17 +233,6 @@  else version (DigitalMars)
             alias real c_long_double;
     }
 }
-else version (GNU)
-    alias real c_long_double;
-else version (LDC)
-    alias real c_long_double;
-else version (SDC)
-{
-    version (X86)
-        alias real c_long_double;
-    else version (X86_64)
-        alias real c_long_double;
-}
 
 static assert(is(c_long_double), "c_long_double needs to be declared for this platform/architecture.");
 
@@ -257,18 +257,9 @@  private struct _Complex(T)
     T im;
 }
 
-version (Posix)
-{
-    align(float.alignof)  enum __c_complex_float : _Complex!float;
-    align(double.alignof) enum __c_complex_double : _Complex!double;
-    align(real.alignof)   enum __c_complex_real : _Complex!real;
-}
-else
-{
-    align(float.sizeof * 2)  enum __c_complex_float : _Complex!float;
-    align(double.sizeof * 2) enum __c_complex_double : _Complex!double;
-    align(real.alignof)      enum __c_complex_real : _Complex!real;
-}
+enum __c_complex_float  : _Complex!float;
+enum __c_complex_double : _Complex!double;
+enum __c_complex_real   : _Complex!c_long_double;
 
 alias c_complex_float = __c_complex_float;
 alias c_complex_double = __c_complex_double;
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index fba78ee233a..2de6e579575 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -424,92 +424,177 @@  else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
     pure int _fpclass(double x);
   }
 
+  version (MinGW)
+  {
     enum
     {
         ///
-        FP_SUBNORMAL = -2,
+        FP_NAN = 0x0100,
         ///
-        FP_NORMAL    = -1,
+        FP_NORMAL = 0x0400,
         ///
-        FP_ZERO      =  0,
+        FP_INFINITE = FP_NAN | FP_NORMAL,
         ///
-        FP_INFINITE  =  1,
+        FP_ZERO = 0x0400,
         ///
-        FP_NAN       =  2,
+        FP_SUBNORMAL = FP_NORMAL | FP_ZERO
     }
 
-  extern(D)
-  {
-    //int fpclassify(real-floating x);
-    ///
-    extern(C) pragma(mangle, "_fdclass") pure int fpclassify(float x);
-    ///
-    extern(C) pragma(mangle, "_dclass")  pure int fpclassify(double x);
-    ///
-    pure int fpclassify()(real x)
-    {
-        static if (real.sizeof == double.sizeof)
-            return fpclassify(cast(double) x);
-        else
-            static assert(false, "fpclassify(real) not supported by MS C runtime");
-    }
+    pure int __fpclassifyf(float x);
+    pure int __fpclassify(double x);
+    pure int __fpclassifyl(real x);
 
-    //int isfinite(real-floating x);
-    ///
-    pure int isfinite()(float x)     { return fpclassify(x) <= 0; }
-    ///
-    pure int isfinite()(double x)    { return fpclassify(x) <= 0; }
-    ///
-    pure int isfinite()(real x)      { return fpclassify(x) <= 0; }
+    pure int __isnanf(float x);
+    pure int __isnan(double x);
+    pure int __isnanl(real x);
 
-    //int isinf(real-floating x);
-    ///
-    pure int isinf()(float x)        { return fpclassify(x) == FP_INFINITE; }
-    ///
-    pure int isinf()(double x)       { return fpclassify(x) == FP_INFINITE; }
-    ///
-    pure int isinf()(real x)         { return fpclassify(x) == FP_INFINITE; }
+    pure int __signbitf(float x);
+    pure int __signbit(double x);
+    pure int __signbitl(real x);
 
-    //int isnan(real-floating x);
-    version (none) // requires MSVCRT 12+ (VS 2013)
+    extern (D)
     {
+        //int fpclassify(real-floating x);
+        ///
+        extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
+        ///
+        extern(C) pragma(mangle, "__fpclassify")  pure int fpclassify(double x);
+        ///
+        extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
+            pure int fpclassify(real x);
+
+        //int isfinite(real-floating x);
+        ///
+        pure int isfinite(float x)       { return (fpclassify(x) & FP_NORMAL) == 0; }
         ///
-        pure int isnan(float x)      { return fpclassify(x) == FP_NAN; }
+        pure int isfinite(double x)      { return (fpclassify(x) & FP_NORMAL) == 0; }
         ///
-        pure int isnan(double x)     { return fpclassify(x) == FP_NAN; }
+        pure int isfinite(real x)        { return (fpclassify(x) & FP_NORMAL) == 0; }
+
+        //int isinf(real-floating x);
+        ///
+        pure int isinf(float x)          { return fpclassify(x) == FP_INFINITE; }
+        ///
+        pure int isinf(double x)         { return fpclassify(x) == FP_INFINITE; }
+        ///
+        pure int isinf(real x)           { return fpclassify(x) == FP_INFINITE; }
+
+        //int isnan(real-floating x);
         ///
-        pure int isnan(real x)       { return fpclassify(x) == FP_NAN; }
+        extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
+        ///
+        extern(C) pragma(mangle, "__isnan")  pure int isnan(double x);
+        ///
+        extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
+            pure int isnan(real x);
+
+        //int isnormal(real-floating x);
+        ///
+        int isnormal(float x)       { return fpclassify(x) == FP_NORMAL; }
+        ///
+        int isnormal(double x)      { return fpclassify(x) == FP_NORMAL; }
+        ///
+        int isnormal(real x)        { return fpclassify(x) == FP_NORMAL; }
+
+        //int signbit(real-floating x);
+        ///
+        extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
+        ///
+        extern(C) pragma(mangle, "__signbit")  pure int signbit(double x);
+        ///
+        extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
+            int signbit(real x);
     }
-    else // for backward compatibility with older runtimes
+  }
+  else
+  {
+    enum
     {
         ///
-        pure int isnan(float x)      { version (Win64) return _isnanf(x); else return _isnan(cast(double) x); }
+        FP_SUBNORMAL = -2,
+        ///
+        FP_NORMAL    = -1,
         ///
-        extern(C) pragma(mangle, "_isnan") pure int isnan(double x);
+        FP_ZERO      =  0,
         ///
-        pure int isnan(real x)       { return _isnan(cast(double) x); }
+        FP_INFINITE  =  1,
+        ///
+        FP_NAN       =  2,
     }
 
-    //int isnormal(real-floating x);
-    ///
-    pure int isnormal()(float x)     { return fpclassify(x) == FP_NORMAL; }
-    ///
-    pure int isnormal()(double x)    { return fpclassify(x) == FP_NORMAL; }
-    ///
-    pure int isnormal()(real x)      { return fpclassify(x) == FP_NORMAL; }
-
-    //int signbit(real-floating x);
-    ///
-    extern(C) pragma(mangle, "_fdsign") pure int signbit(float x);
-    ///
-    extern(C) pragma(mangle, "_dsign")  pure int signbit(double x);
-    ///
-    pure int signbit()(real x)
+    extern(D)
     {
-        static if (real.sizeof == double.sizeof)
-            return signbit(cast(double) x);
-        else
-            return (cast(short*)&(x))[4] & 0x8000;
+        //int fpclassify(real-floating x);
+        ///
+        extern(C) pragma(mangle, "_fdclass") pure int fpclassify(float x);
+        ///
+        extern(C) pragma(mangle, "_dclass")  pure int fpclassify(double x);
+        ///
+        pure int fpclassify()(real x)
+        {
+            static if (real.sizeof == double.sizeof)
+                return fpclassify(cast(double) x);
+            else
+                static assert(false, "fpclassify(real) not supported by MS C runtime");
+        }
+
+        //int isfinite(real-floating x);
+        ///
+        pure int isfinite()(float x)     { return fpclassify(x) <= 0; }
+        ///
+        pure int isfinite()(double x)    { return fpclassify(x) <= 0; }
+        ///
+        pure int isfinite()(real x)      { return fpclassify(x) <= 0; }
+
+        //int isinf(real-floating x);
+        ///
+        pure int isinf()(float x)        { return fpclassify(x) == FP_INFINITE; }
+        ///
+        pure int isinf()(double x)       { return fpclassify(x) == FP_INFINITE; }
+        ///
+        pure int isinf()(real x)         { return fpclassify(x) == FP_INFINITE; }
+
+        //int isnan(real-floating x);
+        version (none) // requires MSVCRT 12+ (VS 2013)
+        {
+            ///
+            pure int isnan(float x)      { return fpclassify(x) == FP_NAN; }
+            ///
+            pure int isnan(double x)     { return fpclassify(x) == FP_NAN; }
+            ///
+            pure int isnan(real x)       { return fpclassify(x) == FP_NAN; }
+        }
+        else // for backward compatibility with older runtimes
+        {
+            ///
+            pure int isnan(float x)      { version (Win64) return _isnanf(x); else return _isnan(cast(double) x); }
+            ///
+            extern(C) pragma(mangle, "_isnan") pure int isnan(double x);
+            ///
+            pure int isnan(real x)       { return _isnan(cast(double) x); }
+        }
+
+        //int isnormal(real-floating x);
+        ///
+        pure int isnormal()(float x)     { return fpclassify(x) == FP_NORMAL; }
+        ///
+        pure int isnormal()(double x)    { return fpclassify(x) == FP_NORMAL; }
+        ///
+        pure int isnormal()(real x)      { return fpclassify(x) == FP_NORMAL; }
+
+        //int signbit(real-floating x);
+        ///
+        extern(C) pragma(mangle, "_fdsign") pure int signbit(float x);
+        ///
+        extern(C) pragma(mangle, "_dsign")  pure int signbit(double x);
+        ///
+        pure int signbit()(real x)
+        {
+            static if (real.sizeof == double.sizeof)
+                return signbit(cast(double) x);
+            else
+                return (cast(short*)&(x))[4] & 0x8000;
+        }
     }
   }
 }
@@ -835,88 +920,6 @@  else version (CRuntime_UClibc)
     int signbit(real x);
   }
 }
-else version (MinGW)
-{
-    enum
-    {
-        ///
-        FP_NAN = 0x0100,
-        ///
-        FP_NORMAL = 0x0400,
-        ///
-        FP_INFINITE = FP_NAN | FP_NORMAL,
-        ///
-        FP_ZERO = 0x0400,
-        ///
-        FP_SUBNORMAL = FP_NORMAL | FP_ZERO
-    }
-
-    pure int __fpclassifyf(float x);
-    pure int __fpclassify(double x);
-    pure int __fpclassifyl(real x);
-
-    pure int __isnanf(float x);
-    pure int __isnan(double x);
-    pure int __isnanl(real x);
-
-    pure int __signbitf(float x);
-    pure int __signbit(double x);
-    pure int __signbitl(real x);
-
-  extern (D)
-  {
-    //int fpclassify(real-floating x);
-      ///
-    extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
-    ///
-    extern(C) pragma(mangle, "__fpclassify")  pure int fpclassify(double x);
-    ///
-    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl")
-    pure int fpclassify(real x);
-
-    //int isfinite(real-floating x);
-    ///
-    pure int isfinite(float x)       { return (fpclassify(x) & FP_NORMAL) == 0; }
-    ///
-    pure int isfinite(double x)      { return (fpclassify(x) & FP_NORMAL) == 0; }
-    ///
-    pure int isfinite(real x)        { return (fpclassify(x) & FP_NORMAL) == 0; }
-
-    //int isinf(real-floating x);
-    ///
-    pure int isinf(float x)          { return fpclassify(x) == FP_INFINITE; }
-    ///
-    pure int isinf(double x)         { return fpclassify(x) == FP_INFINITE; }
-    ///
-    pure int isinf(real x)           { return fpclassify(x) == FP_INFINITE; }
-
-    //int isnan(real-floating x);
-    ///
-    extern(C) pragma(mangle, "__isnanf") pure int isnan(float x);
-    ///
-    extern(C) pragma(mangle, "__isnan")  pure int isnan(double x);
-    ///
-    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl")
-    pure int isnan(real x);
-
-    //int isnormal(real-floating x);
-    ///
-    int isnormal(float x)       { return fpclassify(x) == FP_NORMAL; }
-    ///
-    int isnormal(double x)      { return fpclassify(x) == FP_NORMAL; }
-    ///
-    int isnormal(real x)        { return fpclassify(x) == FP_NORMAL; }
-
-    //int signbit(real-floating x);
-    ///
-    extern(C) pragma(mangle, "__signbitf") pure int signbit(float x);
-    ///
-    extern(C) pragma(mangle, "__signbit")  pure int signbit(double x);
-    ///
-    extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl")
-    int signbit(real x);
-  }
-}
 else version (Darwin)
 {
     enum
@@ -1166,7 +1169,7 @@  else version (OpenBSD)
         FP_FAST_FMAL = 1,
     }
 
-    pure int __fpclassifyd(double);
+    pure int __fpclassify(double);
     pure int __fpclassifyf(float);
     pure int __fpclassifyl(real);
     pure int __isfinitef(float);
@@ -1188,7 +1191,7 @@  else version (OpenBSD)
       ///
     extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x);
     ///
-    extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x);
+    extern(C) pragma(mangle, "__fpclassify") pure int fpclassify(double x);
     ///
     extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x);
 
diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d
index 532a0803f55..c76b922a3eb 100644
--- a/libphobos/libdruntime/core/stdc/stdio.d
+++ b/libphobos/libdruntime/core/stdc/stdio.d
@@ -1347,7 +1347,7 @@  version (CRuntime_DigitalMars)
     ///
     pure int  fileno()(FILE* stream)   { return stream._file; }
   }
-  ///
+    ///
     pragma(printf)
     int   _snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
     ///
@@ -1358,6 +1358,26 @@  version (CRuntime_DigitalMars)
     int   _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
     ///
     alias _vsnprintf vsnprintf;
+
+    //
+    // Digital Mars under-the-hood C I/O functions. Uses _iobuf* for the
+    // unshared version of FILE*, usable when the FILE is locked.
+    //
+
+    ///
+    int _fputc_nlock(int c, _iobuf* fp);
+    ///
+    int _fputwc_nlock(int c, _iobuf* fp);
+    ///
+    int _fgetc_nlock(_iobuf* fp);
+    ///
+    int _fgetwc_nlock(_iobuf* fp);
+    ///
+    int __fp_lock(FILE* fp);
+    ///
+    void __fp_unlock(FILE* fp);
+    ///
+    int setmode(int fd, int mode);
 }
 else version (CRuntime_Microsoft)
 {
@@ -1410,16 +1430,31 @@  else version (CRuntime_Microsoft)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
   }
 
+    //
+    // Microsoft under-the-hood C I/O functions. Uses _iobuf* for the unshared
+    // version of FILE*, usable when the FILE is locked.
+    //
+    import core.stdc.stddef : wchar_t;
+    import core.stdc.wchar_ : wint_t;
+
     ///
-    int _fputc_nolock(int c, FILE *fp);
+    int _fputc_nolock(int c, _iobuf* fp);
     ///
-    int _fgetc_nolock(FILE *fp);
-
+    int _fgetc_nolock(_iobuf* fp);
     ///
-    int _lock_file(FILE *fp);
+    wint_t _fputwc_nolock(wchar_t c, _iobuf* fp);
     ///
-    int _unlock_file(FILE *fp);
-
+    wint_t _fgetwc_nolock(_iobuf* fp);
+    ///
+    void _lock_file(FILE* fp);
+    ///
+    void _unlock_file(FILE* fp);
+    ///
+    int _setmode(int fd, int mode);
+    ///
+    int _fseeki64(FILE* stream, long offset, int origin);
+    ///
+    long _ftelli64(FILE* stream);
     ///
     intptr_t _get_osfhandle(int fd);
     ///
@@ -1448,6 +1483,23 @@  else version (CRuntime_Glibc)
     ///
     pragma(printf)
     int  vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
+
+    //
+    // Gnu under-the-hood C I/O functions. Uses _iobuf* for the unshared
+    // version of FILE*, usable when the FILE is locked.
+    // See http://gnu.org/software/libc/manual/html_node/I_002fO-on-Streams.html
+    //
+    import core.stdc.wchar_ : wint_t;
+    import core.stdc.stddef : wchar_t;
+
+    ///
+    int fputc_unlocked(int c, _iobuf* stream);
+    ///
+    int fgetc_unlocked(_iobuf* stream);
+    ///
+    wint_t fputwc_unlocked(wchar_t wc, _iobuf* stream);
+    ///
+    wint_t fgetwc_unlocked(_iobuf* stream);
 }
 else version (Darwin)
 {
@@ -1907,6 +1959,22 @@  version (Windows)
         O_TEXT = _O_TEXT, ///
         _O_BINARY = 0x8000, ///
         O_BINARY = _O_BINARY, ///
+        _O_WTEXT = 0x10000, ///
+        _O_U16TEXT = 0x20000, ///
+        _O_U8TEXT = 0x40000, ///
+        _O_ACCMODE = (_O_RDONLY|_O_WRONLY|_O_RDWR), ///
+        O_ACCMODE = _O_ACCMODE, ///
+        _O_RAW = _O_BINARY, ///
+        O_RAW = _O_BINARY, ///
+        _O_NOINHERIT = 0x0080, ///
+        O_NOINHERIT = _O_NOINHERIT, ///
+        _O_TEMPORARY = 0x0040, ///
+        O_TEMPORARY = _O_TEMPORARY, ///
+        _O_SHORT_LIVED = 0x1000, ///
+        _O_SEQUENTIAL = 0x0020, ///
+        O_SEQUENTIAL = _O_SEQUENTIAL, ///
+        _O_RANDOM = 0x0010, ///
+        O_RANDOM = _O_RANDOM, ///
     }
 
     enum
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..2d1a198543f 100644
--- a/libphobos/libdruntime/core/stdc/tgmath.d
+++ b/libphobos/libdruntime/core/stdc/tgmath.d
@@ -1285,6 +1285,13 @@  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
     {
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/thread_act.d b/libphobos/libdruntime/core/sys/darwin/mach/thread_act.d
index b61673fb4f1..d455d1b8303 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/thread_act.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/thread_act.d
@@ -38,6 +38,10 @@  version (AArch64)
     version = AnyARM;
 version (ARM)
     version = AnyARM;
+version (PPC)
+    version = AnyPPC;
+version (PPC64)
+    version = AnyPPC;
 
 version (i386)
 {
@@ -235,3 +239,65 @@  else version (AnyARM)
     kern_return_t thread_resume(thread_act_t);
     kern_return_t thread_get_state(thread_act_t, thread_state_flavor_t, thread_state_t*, mach_msg_type_number_t*);
 }
+else version (AnyPPC)
+{
+    alias thread_act_t = mach_port_t;
+    alias thread_state_t = void;
+    alias thread_state_flavor_t = int;
+    alias mach_msg_type_number_t = natural_t;
+
+    enum
+    {
+        PPC_THREAD_STATE = 1,
+        PPC_FLOAT_STATE = 2,
+        PPC_EXCEPTION_STATE = 3,
+        PPC_VECTOR_STATE = 4,
+        PPC_THREAD_STATE64 = 5,
+        PPC_EXCEPTION_STATE64 = 6,
+        THREAD_STATE_NONE = 7
+    }
+
+    struct ppc_thread_state_t
+    {
+        uint srr0;   /// Instruction address register (PC)
+        uint srr1;   /// Machine state register (supervisor)
+        uint[32] r;  /// General purpose register r0-r31
+        uint cr;     /// Condition register
+        uint xer;    /// User's integer exception register
+        uint lr;     /// Link register
+        uint ctr;    /// Count register
+        uint mq;     /// MQ register (601 only)
+        uint vrsave; /// Vector save register
+    }
+
+    alias ppc_thread_state32_t = ppc_thread_state_t;
+
+    struct ppc_thread_state64_t
+    {
+        ulong srr0;   /// Instruction address register (PC)
+        ulong srr1;   /// Machine state register (supervisor)
+        ulong[32] r;  /// General purpose register r0-r31
+        uint cr;      /// Condition register
+        uint pad0;
+        ulong xer;    /// User's integer exception register
+        ulong lr;     /// Link register
+        ulong ctr;    /// Count register
+        uint vrsave;  /// Vector save register
+        uint pad1;
+    }
+
+    enum : mach_msg_type_number_t
+    {
+        PPC_THREAD_STATE_COUNT = cast(mach_msg_type_number_t) (ppc_thread_state_t.sizeof / uint.sizeof),
+        PPC_THREAD_STATE32_COUNT = cast(mach_msg_type_number_t) (ppc_thread_state32_t.sizeof / uint.sizeof),
+        PPC_THREAD_STATE64_COUNT = cast(mach_msg_type_number_t) (ppc_thread_state64_t.sizeof / uint.sizeof),
+    }
+
+    alias MACHINE_THREAD_STATE = PPC_THREAD_STATE;
+    alias MACHINE_THREAD_STATE_COUNT = PPC_THREAD_STATE_COUNT;
+
+    mach_port_t   mach_thread_self();
+    kern_return_t thread_suspend(thread_act_t);
+    kern_return_t thread_resume(thread_act_t);
+    kern_return_t thread_get_state(thread_act_t, thread_state_flavor_t, thread_state_t*, mach_msg_type_number_t*);
+}
diff --git a/libphobos/libdruntime/core/sys/openbsd/sys/link_elf.d b/libphobos/libdruntime/core/sys/openbsd/sys/link_elf.d
index f88671a3160..55fc79268e2 100644
--- a/libphobos/libdruntime/core/sys/openbsd/sys/link_elf.d
+++ b/libphobos/libdruntime/core/sys/openbsd/sys/link_elf.d
@@ -63,3 +63,8 @@  private alias int function(dl_phdr_info*, size_t, void *) @nogc dl_iterate_phdr_
 
 int dl_iterate_phdr(dl_iterate_phdr_cb __callback, void*__data);
 int dl_iterate_phdr(dl_iterate_phdr_cb_ngc __callback, void*__data) @nogc;
+
+int _rtld_addr_phdr(const void*, dl_phdr_info*) @nogc
+{
+    return 0;
+}
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index 031bcb7341f..41b52da7c64 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -516,6 +516,46 @@  version (CRuntime_Glibc)
     int    putc_unlocked(int, FILE*);
     int    putchar_unlocked(int);
 }
+else version (CRuntime_Musl)
+{
+    void   flockfile(FILE*);
+    int    ftrylockfile(FILE*);
+    void   funlockfile(FILE*);
+    int    getc_unlocked(FILE*);
+    int    getchar_unlocked();
+    int    putc_unlocked(int, FILE*);
+    int    putchar_unlocked(int);
+}
+else version (Darwin)
+{
+    void   flockfile(FILE*);
+    int    ftrylockfile(FILE*);
+    void   funlockfile(FILE*);
+    int    getc_unlocked(FILE*);
+    int    getchar_unlocked();
+    int    putc_unlocked(int, FILE*);
+    int    putchar_unlocked(int);
+}
+else version (FreeBSD)
+{
+    void   flockfile(FILE*);
+    int    ftrylockfile(FILE*);
+    void   funlockfile(FILE*);
+    int    getc_unlocked(FILE*);
+    int    getchar_unlocked();
+    int    putc_unlocked(int, FILE*);
+    int    putchar_unlocked(int);
+}
+else version (NetBSD)
+{
+    void   flockfile(FILE*);
+    int    ftrylockfile(FILE*);
+    void   funlockfile(FILE*);
+    int    getc_unlocked(FILE*);
+    int    getchar_unlocked();
+    int    putc_unlocked(int, FILE*);
+    int    putchar_unlocked(int);
+}
 else version (OpenBSD)
 {
     void   flockfile(FILE*);
@@ -526,6 +566,16 @@  else version (OpenBSD)
     int    putc_unlocked(int, FILE*);
     int    putchar_unlocked(int);
 }
+else version (DragonFlyBSD)
+{
+    void   flockfile(FILE*);
+    int    ftrylockfile(FILE*);
+    void   funlockfile(FILE*);
+    int    getc_unlocked(FILE*);
+    int    getchar_unlocked();
+    int    putc_unlocked(int, FILE*);
+    int    putchar_unlocked(int);
+}
 else version (Solaris)
 {
     void   flockfile(FILE*);
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/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d
index 3df0d7fd41b..cc2422bcaa0 100644
--- a/libphobos/libdruntime/core/sys/windows/dll.d
+++ b/libphobos/libdruntime/core/sys/windows/dll.d
@@ -414,7 +414,7 @@  int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc
     {
         version (GNU_InlineAsm)
         {
-            asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" peb; }
+            asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" (peb); }
         }
         else
         {
@@ -431,7 +431,7 @@  int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc
     {
         version (GNU_InlineAsm)
         {
-            asm pure nothrow @nogc { "movl %%fs:0x30, %0;" : "=r" peb; }
+            asm pure nothrow @nogc { "movl %%fs:0x30, %0;" : "=r" (peb); }
         }
         else
         {
diff --git a/libphobos/libdruntime/core/sys/windows/threadaux.d b/libphobos/libdruntime/core/sys/windows/threadaux.d
index fb4d1ee64ba..34fda656c8c 100644
--- a/libphobos/libdruntime/core/sys/windows/threadaux.d
+++ b/libphobos/libdruntime/core/sys/windows/threadaux.d
@@ -172,7 +172,7 @@  struct thread_aux
             version (GNU_InlineAsm)
             {
                 void** teb;
-                asm pure nothrow @nogc { "movl %%fs:0x18, %0;" : "=r" teb; }
+                asm pure nothrow @nogc { "movl %%fs:0x18, %0;" : "=r" (teb); }
                 return teb;
             }
             else
@@ -190,7 +190,7 @@  struct thread_aux
             version (GNU_InlineAsm)
             {
                 void** teb;
-                asm pure nothrow @nogc { "movq %%gs:0x30, %0;" : "=r" teb; }
+                asm pure nothrow @nogc { "movq %%gs:0x30, %0;" : "=r" (teb); }
                 return teb;
             }
             else
diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber.d
index 67d9937e31a..f4c04ce7358 100644
--- a/libphobos/libdruntime/core/thread/fiber.d
+++ b/libphobos/libdruntime/core/thread/fiber.d
@@ -82,6 +82,8 @@  private
 
             version (MinGW)
                 version = GNU_AsmX86_Windows;
+            else version (OSX)
+                version = AsmX86_Posix;
             else version (Posix)
                 version = AsmX86_Posix;
         }
@@ -105,13 +107,21 @@  private
 
             version (MinGW)
                 version = GNU_AsmX86_64_Windows;
+            else version (OSX)
+                version = AsmX86_64_Posix;
             else version (Posix)
                 version = AsmX86_64_Posix;
         }
     }
     else version (PPC)
     {
-        version (Posix)
+        version (OSX)
+        {
+            version = AsmPPC_Darwin;
+            version = AsmExternal;
+            version = AlignFiberStackTo16Byte;
+        }
+        else version (Posix)
         {
             version = AsmPPC_Posix;
             version = AsmExternal;
@@ -119,7 +129,13 @@  private
     }
     else version (PPC64)
     {
-        version (Posix)
+        version (OSX)
+        {
+            version = AsmPPC_Darwin;
+            version = AsmExternal;
+            version = AlignFiberStackTo16Byte;
+        }
+        else version (Posix)
         {
             version = AlignFiberStackTo16Byte;
         }
@@ -1347,6 +1363,28 @@  private:
 
             assert( (cast(size_t) pstack & 0x0f) == 0 );
         }
+        else version (AsmPPC_Darwin)
+        {
+            version (StackGrowsDown) {}
+            else static assert(false, "PowerPC Darwin only supports decrementing stacks");
+
+            uint wsize = size_t.sizeof;
+
+            // linkage + regs + FPRs + VRs
+            uint space = 8 * wsize + 20 * wsize + 18 * 8 + 12 * 16;
+            (cast(ubyte*)pstack - space)[0 .. space] = 0;
+
+            pstack -= wsize * 6;
+            *cast(size_t*)pstack = cast(size_t) &fiber_entryPoint; // LR
+            pstack -= wsize * 22;
+
+            // On Darwin PPC64 pthread self is in R13 (which is reserved).
+            // At present, it is not safe to migrate fibers between threads, but if that
+            // changes, then updating the value of R13 will also need to be handled.
+            version (PPC64)
+              *cast(size_t*)(pstack + wsize) = cast(size_t) Thread.getThis().m_addr;
+            assert( (cast(size_t) pstack & 0x0f) == 0 );
+        }
         else version (AsmMIPS_O32_Posix)
         {
             version (StackGrowsDown) {}
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index 0fffc7ed3f7..31764e69691 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -349,7 +349,8 @@  class Thread : ThreadBase
         }
         else version (Posix)
         {
-            pthread_detach( m_addr );
+            if (m_addr != m_addr.init)
+                pthread_detach( m_addr );
             m_addr = m_addr.init;
         }
         version (Darwin)
@@ -420,6 +421,17 @@  class Thread : ThreadBase
         {
             uint[16]        m_reg; // r0-r15
         }
+        else version (PPC)
+        {
+            // Make the assumption that we only care about non-fp and non-vr regs.
+            // ??? : it seems plausible that a valid address can be copied into a VR.
+            uint[32]        m_reg; // r0-31
+        }
+        else version (PPC64)
+        {
+            // As above.
+            ulong[32]       m_reg; // r0-31
+        }
         else
         {
             static assert(false, "Architecture not supported." );
@@ -578,7 +590,7 @@  class Thread : ThreadBase
     {
         version (Windows)
         {
-            if ( WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 )
+            if ( m_addr != m_addr.init && WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 )
                 throw new ThreadException( "Unable to join thread" );
             // NOTE: m_addr must be cleared before m_hndl is closed to avoid
             //       a race condition with isRunning. The operation is done
@@ -589,7 +601,7 @@  class Thread : ThreadBase
         }
         else version (Posix)
         {
-            if ( pthread_join( m_addr, null ) != 0 )
+            if ( m_addr != m_addr.init && pthread_join( m_addr, null ) != 0 )
                 throw new ThreadException( "Unable to join thread" );
             // NOTE: pthread_join acts as a substitute for pthread_detach,
             //       which is normally called by the dtor.  Setting m_addr
@@ -1629,9 +1641,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.");
 
@@ -1880,6 +1892,28 @@  private extern (D) bool suspend( Thread t ) nothrow @nogc
             t.m_reg[14] = state.lr;
             t.m_reg[15] = state.pc;
         }
+        else version (PPC)
+        {
+            ppc_thread_state_t state = void;
+            mach_msg_type_number_t count = PPC_THREAD_STATE_COUNT;
+
+            if (thread_get_state(t.m_tmach, PPC_THREAD_STATE, &state, &count) != KERN_SUCCESS)
+                onThreadError("Unable to load thread state");
+            if (!t.m_lock)
+                t.m_curr.tstack = cast(void*) state.r[1];
+            t.m_reg[] = state.r[];
+        }
+        else version (PPC64)
+        {
+            ppc_thread_state64_t state = void;
+            mach_msg_type_number_t count = PPC_THREAD_STATE64_COUNT;
+
+            if (thread_get_state(t.m_tmach, PPC_THREAD_STATE64, &state, &count) != KERN_SUCCESS)
+                onThreadError("Unable to load thread state");
+            if (!t.m_lock)
+                t.m_curr.tstack = cast(void*) state.r[1];
+            t.m_reg[] = state.r[];
+        }
         else
         {
             static assert(false, "Architecture not supported." );
diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d
index 50795e444be..0a8de10e17b 100644
--- a/libphobos/libdruntime/core/thread/threadbase.d
+++ b/libphobos/libdruntime/core/thread/threadbase.d
@@ -10,6 +10,9 @@ 
  * Source:    $(DRUNTIMESRC core/thread/osthread.d)
  */
 
+/* NOTE: This file has been patched from the original DMD distribution to
+ * work with the GDC compiler.
+ */
 module core.thread.threadbase;
 
 import core.thread.context;
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 4f6a168350b..6f9740404ef 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@ 
-f89dc217a680fa1a83f2999fea04b7c562f705ee
+e6907ff3e28d3c43469c46df4a0426726ecb8631
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d
index b0310a870d9..9cbeca8e9a8 100644
--- a/libphobos/src/std/process.d
+++ b/libphobos/src/std/process.d
@@ -1358,7 +1358,8 @@  version (Windows)
 
 
 /**
-Flags that control the behaviour of $(LREF spawnProcess) and
+Flags that control the behaviour of process creation functions in this
+module. Most flags only apply to $(LREF spawnProcess) and
 $(LREF spawnShell).
 
 Use bitwise OR to combine flags.
@@ -1433,6 +1434,21 @@  enum Config
     Calling $(LREF wait) or $(LREF kill) with the resulting $(D Pid) is invalid.
     */
     detached = 64,
+
+    /**
+    By default, the $(LREF execute) and $(LREF executeShell) functions
+    will capture child processes' both stdout and stderr. This can be
+    undesirable if the standard output is to be processed or otherwise
+    used by the invoking program, as `execute`'s result would then
+    contain a mix of output and warning/error messages.
+
+    Specify this flag when calling `execute` or `executeShell` to
+    cause invoked processes' stderr stream to be sent to $(REF stderr,
+    std,stdio), and only capture and return standard output.
+
+    This flag has no effect on $(LREF spawnProcess) or $(LREF spawnShell).
+    */
+    stderrPassThrough = 128,
 }
 
 
@@ -2487,7 +2503,11 @@  private auto executeImpl(alias pipeFunc, Cmd, ExtraPipeFuncArgs...)(
     import std.array : appender;
     import std.typecons : Tuple;
 
-    auto p = pipeFunc(commandLine, Redirect.stdout | Redirect.stderrToStdout,
+    auto redirect = (config & Config.stderrPassThrough)
+        ? Redirect.stdout
+        : Redirect.stdout | Redirect.stderrToStdout;
+
+    auto p = pipeFunc(commandLine, redirect,
                       env, config, workDir, extraArgs);
 
     auto a = appender!(ubyte[])();
@@ -2551,6 +2571,30 @@  private auto executeImpl(alias pipeFunc, Cmd, ExtraPipeFuncArgs...)(
     assert(r3.output.empty);
 }
 
+@system unittest
+{
+    // Temporarily disable output to stderr so as to not spam the build log.
+    import std.stdio : stderr;
+    import std.typecons : Tuple;
+    import std.file : readText;
+    import std.traits : ReturnType;
+
+    ReturnType!executeShell r;
+    auto tmpname = uniqueTempPath;
+    auto t = stderr;
+    // Open a new scope to minimize code ran with stderr redirected.
+    {
+        stderr.open(tmpname, "w");
+        scope(exit) stderr = t;
+        r = executeShell("echo D rox>&2", null, Config.stderrPassThrough);
+    }
+    assert(r.status == 0);
+    assert(r.output.empty);
+    auto witness = readText(tmpname);
+    import std.ascii : newline;
+    assert(witness == "D rox" ~ newline, "'" ~ witness ~ "'");
+}
+
 @safe unittest
 {
     import std.typecons : Tuple;
@@ -2750,8 +2794,7 @@  private struct TestScript
     string path;
 }
 
-version (unittest)
-private string uniqueTempPath() @safe
+package(std) string uniqueTempPath() @safe
 {
     import std.file : tempDir;
     import std.path : buildPath;