libphobos: Merge upstream druntime 89f870b7, phobos e6907ff3e

Phobos changes:

 - Synchronize C bindings with the latest port fixes in upstream
   druntime.

 - Add Config.stderrPassThrough to std.process (PR98494).

Reviewed-on: https://github.com/dlang/druntime/pull/3448
	     https://github.com/dlang/phobos/pull/7984

libphobos/ChangeLog:

	PR d/98494
	* libdruntime/MERGE: Merge upstream druntime 89f870b7.
	* src/MERGE: Merge upstream phobos e6907ff3e.
This commit is contained in:
Iain Buclaw 2021-04-19 13:51:02 +02:00
parent 6eae7549b8
commit e19c638996
18 changed files with 525 additions and 214 deletions

View file

@ -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.

View file

@ -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;

View file

@ -424,6 +424,90 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
pure int _fpclass(double x);
}
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
{
enum
{
///
@ -438,78 +522,79 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o
FP_NAN = 2,
}
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)
extern(D)
{
static if (real.sizeof == double.sizeof)
return fpclassify(cast(double) x);
else
static assert(false, "fpclassify(real) not supported by MS C runtime");
}
//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 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 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 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 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;
//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);

View file

@ -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);
}
///
int _fputc_nolock(int c, FILE *fp);
///
int _fgetc_nolock(FILE *fp);
//
// 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 _lock_file(FILE *fp);
int _fputc_nolock(int c, _iobuf* fp);
///
int _unlock_file(FILE *fp);
int _fgetc_nolock(_iobuf* fp);
///
wint_t _fputwc_nolock(wchar_t c, _iobuf* 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

View file

@ -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
{

View file

@ -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
{

View file

@ -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*);
}

View file

@ -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;
}

View file

@ -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*);

View file

@ -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)

View file

@ -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;

View file

@ -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
{

View file

@ -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

View file

@ -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) {}

View file

@ -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." );

View file

@ -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;

View file

@ -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.

View file

@ -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;