diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2024-01-18 02:39:20 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2024-02-03 00:49:46 +0100 |
commit | f204359931866b917856fc959c70dbf55f28c14d (patch) | |
tree | ba1c671045e384fa49a6381f79abf7c1b84a55ea /libphobos | |
parent | 5470a9b176c2b3030ff3891c7e9403db2b0685b8 (diff) | |
download | gcc-f204359931866b917856fc959c70dbf55f28c14d.zip gcc-f204359931866b917856fc959c70dbf55f28c14d.tar.gz gcc-f204359931866b917856fc959c70dbf55f28c14d.tar.bz2 |
d: Merge dmd, druntime bce5c1f7b5, phobos e4d0dd513.
D front-end changes:
- Import latest changes from dmd v2.107.0-beta.1.
- Keywords like `__FILE__' are now always evaluated at the
callsite.
D runtime changes:
- Import latest changes from druntime v2.107.0-beta.1.
- Added `nameSig' field to TypeInfo_Class in object.d.
Phobos changes:
- Import latest changes from phobos v2.107.0-beta.1.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd bce5c1f7b5.
* d-attribs.cc (build_attributes): Update for new front-end interface.
* d-lang.cc (d_parse_file): Likewise.
* decl.cc (DeclVisitor::visit (VarDeclaration *)): Likewise.
* expr.cc (build_lambda_tree): New function.
(ExprVisitor::visit (FuncExp *)): Use build_lambda_tree.
(ExprVisitor::visit (SymOffExp *)): Likewise.
(ExprVisitor::visit (VarExp *)): Likewise.
* typeinfo.cc (create_tinfo_types): Add two ulong fields to internal
TypeInfo representation.
(TypeInfoVisitor::visit (TypeInfoClassDeclaration *)): Emit stub data
for TypeInfo_Class.nameSig.
(TypeInfoVisitor::visit (TypeInfoStructDeclaration *)): Update for new
front-end interface.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime bce5c1f7b5.
* src/MERGE: Merge upstream phobos e4d0dd513.
Diffstat (limited to 'libphobos')
62 files changed, 1073 insertions, 408 deletions
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 2b4400f..138b0b6 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -d8e3976a58d6aef7c2c9371028a2ca4460b5b2ce +bce5c1f7b521d22dcf1ea4e2bc3f76d9d28274fa The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/libphobos/libdruntime/core/exception.d b/libphobos/libdruntime/core/exception.d index d2016b1..959ce83 100644 --- a/libphobos/libdruntime/core/exception.d +++ b/libphobos/libdruntime/core/exception.d @@ -697,17 +697,17 @@ else * Throws: * $(LREF OutOfMemoryError). */ - extern (C) noreturn onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */ + extern (C) noreturn onOutOfMemoryError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */ { // NOTE: Since an out of memory condition exists, no allocation must occur // while generating this object. - throw staticError!OutOfMemoryError(); + throw staticError!OutOfMemoryError(file, line); } - extern (C) noreturn onOutOfMemoryErrorNoGC() @trusted nothrow @nogc + extern (C) noreturn onOutOfMemoryErrorNoGC(string file = __FILE__, size_t line = __LINE__) @trusted nothrow @nogc { // suppress stacktrace until they are @nogc - throw staticError!OutOfMemoryError(false); + throw staticError!OutOfMemoryError(false, file, line); } } @@ -718,11 +718,11 @@ else * Throws: * $(LREF InvalidMemoryOperationError). */ -extern (C) noreturn onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */ +extern (C) noreturn onInvalidMemoryOperationError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */ { // The same restriction applies as for onOutOfMemoryError. The GC is in an // undefined state, thus no allocation must occur while generating this object. - throw staticError!InvalidMemoryOperationError(); + throw staticError!InvalidMemoryOperationError(file, line); } diff --git a/libphobos/libdruntime/core/internal/container/array.d b/libphobos/libdruntime/core/internal/container/array.d index 27292cd..b583341 100644 --- a/libphobos/libdruntime/core/internal/container/array.d +++ b/libphobos/libdruntime/core/internal/container/array.d @@ -9,7 +9,7 @@ module core.internal.container.array; static import common = core.internal.container.common; -import core.exception : onOutOfMemoryErrorNoGC; +import core.exception : onOutOfMemoryError; struct Array(T) { @@ -47,7 +47,7 @@ nothrow: _length = nlength; } else - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); } @@ -103,7 +103,7 @@ nothrow: back = val; } else - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); } void popBack() diff --git a/libphobos/libdruntime/core/internal/container/common.d b/libphobos/libdruntime/core/internal/container/common.d index 582d63b..659b2b5 100644 --- a/libphobos/libdruntime/core/internal/container/common.d +++ b/libphobos/libdruntime/core/internal/container/common.d @@ -18,7 +18,7 @@ void* xrealloc(void* ptr, size_t sz) nothrow @nogc if (!sz) { .free(ptr); return null; } if (auto nptr = .realloc(ptr, sz)) return nptr; - .free(ptr); onOutOfMemoryErrorNoGC(); + .free(ptr); onOutOfMemoryError(); assert(0); } @@ -27,7 +27,7 @@ void* xmalloc(size_t sz) nothrow @nogc import core.exception; if (auto nptr = .malloc(sz)) return nptr; - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); assert(0); } diff --git a/libphobos/libdruntime/core/internal/dassert.d b/libphobos/libdruntime/core/internal/dassert.d index dbad0e6..76948c8 100644 --- a/libphobos/libdruntime/core/internal/dassert.d +++ b/libphobos/libdruntime/core/internal/dassert.d @@ -180,6 +180,8 @@ private string miniFormat(V)(const scope ref V v) /// `shared` values are formatted as their base type static if (is(V == shared T, T)) { + import core.atomic : atomicLoad; + // Use atomics to avoid race conditions whenever possible static if (__traits(compiles, atomicLoad(v))) { @@ -472,11 +474,6 @@ private bool[] calcFieldOverlap(const scope size_t[] offsets) return overlaps; } -// This should be a local import in miniFormat but fails with a cyclic dependency error -// core.thread.osthread -> core.time -> object -> core.internal.array.capacity -// -> core.atomic -> core.thread -> core.thread.osthread -import core.atomic : atomicLoad; - /// Negates a comparison token, e.g. `==` is mapped to `!=` private string invertCompToken(scope string comp) pure nothrow @nogc @safe { diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d index 6f19412..ca4577f 100644 --- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d +++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d @@ -94,8 +94,8 @@ private // Declared as an extern instead of importing core.exception // to avoid inlining - see https://issues.dlang.org/show_bug.cgi?id=13725. - void onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; - void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc; + void onInvalidMemoryOperationError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted pure nothrow @nogc; + void onOutOfMemoryError(void* pretend_sideffect = null, string file = __FILE__, size_t line = __LINE__) @trusted nothrow @nogc; version (COLLECT_FORK) version (OSX) @@ -141,7 +141,7 @@ private GC initialize() auto gc = cast(ConservativeGC) cstdlib.malloc(__traits(classInstanceSize, ConservativeGC)); if (!gc) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); return emplace(gc); } @@ -160,7 +160,7 @@ class ConservativeGC : GC Gcx *gcx; // implementation - static gcLock = shared(AlignedSpinLock)(SpinLock.Contention.lengthy); + static gcLock = shared(AlignedSpinLock)(SpinLock.Contention.brief); static bool _inFinalizer; __gshared bool isPrecise = false; @@ -188,7 +188,7 @@ class ConservativeGC : GC gcx = cast(Gcx*)cstdlib.calloc(1, Gcx.sizeof); if (!gcx) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); gcx.initialize(); if (config.initReserve) @@ -509,7 +509,7 @@ class ConservativeGC : GC auto p = gcx.alloc(size + SENTINEL_EXTRA, alloc_size, bits, ti); if (!p) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); debug (SENTINEL) { @@ -1968,7 +1968,7 @@ struct Gcx // tryAlloc will succeed if a new pool was allocated above, if it fails allocate a new pool now if (!tryAlloc() && (!newPool(1, false) || !tryAlloc())) // out of luck or memory - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); } assert(p !is null); L_hasBin: @@ -2008,7 +2008,7 @@ struct Gcx size_t pn; immutable npages = LargeObjectPool.numPages(size); if (npages == size_t.max) - onOutOfMemoryErrorNoGC(); // size just below size_t.max requested + onOutOfMemoryError(); // size just below size_t.max requested bool tryAlloc() nothrow { @@ -2248,7 +2248,7 @@ struct Gcx enum initSize = 64 * 1024; // Windows VirtualAlloc granularity immutable ncap = _cap ? 2 * _cap : initSize / RANGE.sizeof; auto p = cast(RANGE*)os_mem_map(ncap * RANGE.sizeof); - if (p is null) onOutOfMemoryErrorNoGC(); + if (p is null) onOutOfMemoryError(); debug (VALGRIND) makeMemUndefined(p[0..ncap]); if (_p !is null) { @@ -3394,7 +3394,7 @@ Lmark: scanThreadData = cast(ScanThreadData*) cstdlib.calloc(numScanThreads, ScanThreadData.sizeof); if (!scanThreadData) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); evStart.initialize(false, false); evDone.initialize(false, false); @@ -3610,7 +3610,7 @@ struct Pool { rtinfo = cast(immutable(size_t)**)cstdlib.malloc(npages * (size_t*).sizeof); if (!rtinfo) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); memset(rtinfo, 0, npages * (size_t*).sizeof); } else @@ -3633,13 +3633,13 @@ struct Pool pagetable = cast(Bins*)cstdlib.malloc(npages * Bins.sizeof); if (!pagetable) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); if (npages > 0) { bPageOffsets = cast(uint*)cstdlib.malloc(npages * uint.sizeof); if (!bPageOffsets) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); if (isLargeObject) { @@ -4643,14 +4643,14 @@ debug (LOGGING) { data = cast(Log*)cstdlib.malloc(allocdim * Log.sizeof); if (!data && allocdim) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); } else { Log *newdata; newdata = cast(Log*)cstdlib.malloc(allocdim * Log.sizeof); if (!newdata && allocdim) - onOutOfMemoryErrorNoGC(); + onOutOfMemoryError(); memcpy(newdata, data, dim * Log.sizeof); cstdlib.free(data); data = newdata; @@ -4989,8 +4989,8 @@ version (D_LP64) unittest // only run if the system has enough physical memory size_t sz = 2L^^32; //import core.stdc.stdio; - //printf("availphys = %lld", os_physical_mem()); - if (os_physical_mem() > sz) + //printf("availphys = %lld", os_physical_mem(true)); + if (os_physical_mem(true) > sz) { import core.memory; GC.collect(); diff --git a/libphobos/libdruntime/core/internal/gc/os.d b/libphobos/libdruntime/core/internal/gc/os.d index 38b60cb..0db1753 100644 --- a/libphobos/libdruntime/core/internal/gc/os.d +++ b/libphobos/libdruntime/core/internal/gc/os.d @@ -254,23 +254,26 @@ bool isLowOnMem(size_t mapped) nothrow @nogc /** Get the size of available physical memory + Params: + avail = if supported on the current platform, return the currently unused memory + rather than the installed physical memory Returns: size of installed physical RAM */ version (Windows) { - ulong os_physical_mem() nothrow @nogc + ulong os_physical_mem(bool avail) nothrow @nogc { import core.sys.windows.winbase : GlobalMemoryStatus, MEMORYSTATUS; MEMORYSTATUS stat; GlobalMemoryStatus(&stat); - return stat.dwTotalPhys; // limited to 4GB for Win32 + return avail ? stat.dwAvailPhys : stat.dwTotalPhys; // limited to 4GB for Win32 } } else version (Darwin) { extern (C) int sysctl(const int* name, uint namelen, void* oldp, size_t* oldlenp, const void* newp, size_t newlen) @nogc nothrow; - ulong os_physical_mem() nothrow @nogc + ulong os_physical_mem(bool avail) nothrow @nogc { enum { @@ -287,11 +290,15 @@ else version (Darwin) } else version (Posix) { - ulong os_physical_mem() nothrow @nogc + ulong os_physical_mem(bool avail) nothrow @nogc { - import core.sys.posix.unistd : sysconf, _SC_PAGESIZE, _SC_PHYS_PAGES; + import core.sys.posix.unistd; const pageSize = sysconf(_SC_PAGESIZE); - const pages = sysconf(_SC_PHYS_PAGES); + static if (__traits(compiles, _SC_AVPHYS_PAGES)) // not available on all platforms + const sc = avail ? _SC_AVPHYS_PAGES : _SC_PHYS_PAGES; + else + const sc = _SC_PHYS_PAGES; + const pages = sysconf(sc); return pageSize * pages; } } diff --git a/libphobos/libdruntime/core/internal/spinlock.d b/libphobos/libdruntime/core/internal/spinlock.d index 36d806a..b0ea8f6 100644 --- a/libphobos/libdruntime/core/internal/spinlock.d +++ b/libphobos/libdruntime/core/internal/spinlock.d @@ -53,9 +53,9 @@ shared struct SpinLock import core.time; if (k < pauseThresh) return core.atomic.pause(); - else if (k < 32) + else // if (k < 32) return Thread.yield(); - Thread.sleep(1.msecs); + // Thread.sleep(1.msecs); } private: diff --git a/libphobos/libdruntime/core/memory.d b/libphobos/libdruntime/core/memory.d index 4f44b604..f2a48f9 100644 --- a/libphobos/libdruntime/core/memory.d +++ b/libphobos/libdruntime/core/memory.d @@ -266,8 +266,8 @@ extern(C): /** * Enables automatic garbage collection behavior if collections have - * previously been suspended by a call to disable. This function is - * reentrant, and must be called once for every call to disable before + * previously been suspended by a call to `GC.disable()`. This function is + * reentrant, and must be called once for every call to `GC.disable()` before * automatic collections are enabled. */ pragma(mangle, "gc_enable") static void enable() @safe nothrow pure; @@ -278,7 +278,12 @@ extern(C): * process footprint. Collections may continue to occur in instances * where the implementation deems necessary for correct program behavior, * such as during an out of memory condition. This function is reentrant, - * but enable must be called once for each call to disable. + * but `GC.enable()` must be called once for each call to `GC.disable()`. + * Unlike the + * $(LINK2 https://dlang.org/spec/function.html#nogc-functions, `@nogc` attribute), + * `GC.disable()` halts + * collections across all threads, yet still allows GC allocations. + * Disabling collections eliminates GC pauses. */ pragma(mangle, "gc_disable") static void disable() @safe nothrow pure; diff --git a/libphobos/libdruntime/core/stdc/assert_.d b/libphobos/libdruntime/core/stdc/assert_.d index d6cb8a6..c6d9d9f 100644 --- a/libphobos/libdruntime/core/stdc/assert_.d +++ b/libphobos/libdruntime/core/stdc/assert_.d @@ -113,6 +113,15 @@ else version (CRuntime_Musl) */ noreturn __assert_fail(const(char)* exp, const(char)* file, uint line, const(char)* func); } +else version (CRuntime_Newlib) +{ + /*** + * Assert failure function in the Newlib library. + */ + noreturn __assert(const(char)* file, int line, const(char)* exp); + /// + noreturn __assert_func(const(char)* file, int line, const(char)* func, const(char)* exp); +} else version (CRuntime_UClibc) { noreturn __assert(const(char)* exp, const(char)* file, uint line, const(char)* func); diff --git a/libphobos/libdruntime/core/stdc/errno.d b/libphobos/libdruntime/core/stdc/errno.d index e503dd9..ddec70f 100644 --- a/libphobos/libdruntime/core/stdc/errno.d +++ b/libphobos/libdruntime/core/stdc/errno.d @@ -75,6 +75,14 @@ else version (CRuntime_Musl) alias errno = __errno_location; } } +else version (CRuntime_Newlib) +{ + extern (C) + { + ref int __errno(); + alias errno = __errno; + } +} else version (OpenBSD) { // https://github.com/openbsd/src/blob/master/include/errno.h @@ -164,7 +172,7 @@ else extern (C): -version (Windows) +version (CRuntime_DigitalMars) { enum EPERM = 1; /// Operation not permitted enum ENOENT = 2; /// No such file or directory @@ -250,6 +258,230 @@ version (Windows) enum ETXTBSY = 139; enum EWOULDBLOCK = 140; } +else version (CRuntime_Microsoft) +{ + enum EPERM = 1; /// Operation not permitted + enum ENOENT = 2; /// No such file or directory + enum ESRCH = 3; /// No such process + enum EINTR = 4; /// Interrupted system call + enum EIO = 5; /// I/O error + enum ENXIO = 6; /// No such device or address + enum E2BIG = 7; /// Argument list too long + enum ENOEXEC = 8; /// Exec format error + enum EBADF = 9; /// Bad file number + enum ECHILD = 10; /// No child processes + enum EAGAIN = 11; /// Try again + enum ENOMEM = 12; /// Out of memory + enum EACCES = 13; /// Permission denied + enum EFAULT = 14; /// Bad address + enum EBUSY = 16; /// Device or resource busy + enum EEXIST = 17; /// File exists + enum EXDEV = 18; /// Cross-device link + enum ENODEV = 19; /// No such device + enum ENOTDIR = 20; /// Not a directory + enum EISDIR = 21; /// Is a directory + enum EINVAL = 22; /// Invalid argument + enum ENFILE = 23; /// File table overflow + enum EMFILE = 24; /// Too many open files + enum ENOTTY = 25; /// Not a typewriter + enum EFBIG = 27; /// File too large + enum ENOSPC = 28; /// No space left on device + enum ESPIPE = 29; /// Illegal seek + enum EROFS = 30; /// Read-only file system + enum EMLINK = 31; /// Too many links + enum EPIPE = 32; /// Broken pipe + enum EDOM = 33; /// Math argument out of domain of func + enum ERANGE = 34; /// Math result not representable + enum EDEADLK = 36; /// Resource deadlock would occur + enum ENAMETOOLONG = 38; /// File name too long + enum ENOLCK = 39; /// No record locks available + enum ENOSYS = 40; /// Function not implemented + enum ENOTEMPTY = 41; /// Directory not empty + enum EILSEQ = 42; /// Illegal byte sequence + enum EDEADLOCK = EDEADLK; /// Resource deadlock would occur + + // POSIX compatibility + // See_Also: https://docs.microsoft.com/en-us/cpp/c-runtime-library/errno-constants + enum EADDRINUSE = 100; + enum EADDRNOTAVAIL = 101; + enum EAFNOSUPPORT = 102; + enum EALREADY = 103; + enum EBADMSG = 104; + enum ECANCELED = 105; + enum ECONNABORTED = 106; + enum ECONNREFUSED = 107; + enum ECONNRESET = 108; + enum EDESTADDRREQ = 109; + enum EHOSTUNREACH = 110; + enum EIDRM = 111; + enum EINPROGRESS = 112; + enum EISCONN = 113; + enum ELOOP = 114; + enum EMSGSIZE = 115; + enum ENETDOWN = 116; + enum ENETRESET = 117; + enum ENETUNREACH = 118; + enum ENOBUFS = 119; + enum ENODATA = 120; + enum ENOLINK = 121; + enum ENOMSG = 122; + enum ENOPROTOOPT = 123; + enum ENOSR = 124; + enum ENOSTR = 125; + enum ENOTCONN = 126; + enum ENOTRECOVERABLE = 127; + enum ENOTSOCK = 128; + enum ENOTSUP = 129; + enum EOPNOTSUPP = 130; + enum EOTHER = 131; + enum EOVERFLOW = 132; + enum EOWNERDEAD = 133; + enum EPROTO = 134; + enum EPROTONOSUPPORT = 135; + enum EPROTOTYPE = 136; + enum ETIME = 137; + enum ETIMEDOUT = 138; + enum ETXTBSY = 139; + enum EWOULDBLOCK = 140; +} +else version (CRuntime_Newlib) +{ + enum EPERM = 1; + enum ENOENT = 2; + enum ESRCH = 3; + enum EINTR = 4; + enum EIO = 5; + enum ENXIO = 6; + enum E2BIG = 7; + enum ENOEXEC = 8; + enum EBADF = 9; + enum ECHILD = 10; + enum EAGAIN = 11; + enum ENOMEM = 12; + enum EACCES = 13; + enum EFAULT = 14; + enum EBUSY = 16; + enum EEXIST = 17; + enum EXDEV = 18; + enum ENODEV = 19; + enum ENOTDIR = 20; + enum EISDIR = 21; + enum EINVAL = 22; + enum ENFILE = 23; + enum EMFILE = 24; + enum ENOTTY = 25; + enum ETXTBSY = 26; + enum EFBIG = 27; + enum ENOSPC = 28; + enum ESPIPE = 29; + enum EROFS = 30; + enum EMLINK = 31; + enum EPIPE = 32; + enum EDOM = 33; + enum ERANGE = 34; + enum ENOMSG = 35; + enum EIDRM = 36; + enum EDEADLK = 45; + enum ENOLCK = 46; + enum ENOSTR = 60; + enum ENODATA = 61; + enum ETIME = 62; + enum ENOSR = 63; + enum ENOLINK = 67; + enum EPROTO = 71; + enum EMULTIHOP = 74; + enum EBADMSG = 77; + enum EFTYPE = 79; + enum ENOSYS = 88; + enum ENOTEMPTY = 90; + enum ENAMETOOLONG = 91; + enum ELOOP = 92; + enum EOPNOTSUPP = 95; + enum EPFNOSUPPORT = 96; + enum ECONNRESET = 104; + enum ENOBUFS = 105; + enum EAFNOSUPPORT = 106; + enum EPROTOTYPE = 107; + enum ENOTSOCK = 108; + enum ENOPROTOOPT = 109; + enum ECONNREFUSED = 111; + enum EADDRINUSE = 112; + enum ECONNABORTED = 113; + enum ENETUNREACH = 114; + enum ENETDOWN = 115; + enum ETIMEDOUT = 116; + enum EHOSTDOWN = 117; + enum EHOSTUNREACH = 118; + enum EINPROGRESS = 119; + enum EALREADY = 120; + enum EDESTADDRREQ = 121; + enum EMSGSIZE = 122; + enum EPROTONOSUPPORT = 123; + enum EADDRNOTAVAIL = 125; + enum ENETRESET = 126; + enum EISCONN = 127; + enum ENOTCONN = 128; + enum ETOOMANYREFS = 129; + enum EDQUOT = 132; + enum ESTALE = 133; + enum ENOTSUP = 134; + enum EILSEQ = 138; + enum EOVERFLOW = 139; + enum ECANCELED = 140; + enum ENOTRECOVERABLE = 141; + enum EOWNERDEAD = 142; + + enum EWOULDBLOCK = EAGAIN; + + enum __ELASTERROR = 2000; + + // Linux errno extensions + version (Cygwin) + { + enum ENOTBLK = 15; + enum ECHRNG = 37; + enum EL2NSYNC = 38; + enum EL3HLT = 39; + enum EL3RST = 40; + enum ELNRNG = 41; + enum EUNATCH = 42; + enum ENOCSI = 43; + enum EL2HLT = 44; + enum EBADE = 50; + enum EBADR = 51; + enum EXFULL = 52; + enum ENOANO = 53; + enum EBADRQC = 54; + enum EBADSLT = 55; + enum EDEADLOCK = 56; + enum EBFONT = 57; + enum ENONET = 64; + enum ENOPKG = 65; + enum EREMOTE = 66; + enum EADV = 68; + enum ESRMNT = 69; + enum ECOMM = 70; + enum ELBIN = 75; + enum EDOTDOT = 76; + enum ENOTUNIQ = 80; + enum EBADFD = 81; + enum EREMCHG = 82; + enum ELIBACC = 83; + enum ELIBBAD = 84; + enum ELIBSCN = 85; + enum ELIBMAX = 86; + enum ELIBEXEC = 87; + enum ENMFILE = 89; + enum ESHUTDOWN = 110; + enum ESOCKTNOSUPPORT = 124; + enum EPROCLIM = 130; + enum EUSERS = 131; + enum ENOMEDIUM = 135; + enum ENOSHARE = 136; + enum ECASECLASH = 137; + enum ESTRPIPE = 143; + } +} else version (linux) { enum EPERM = 1; /// diff --git a/libphobos/libdruntime/core/stdc/fenv.d b/libphobos/libdruntime/core/stdc/fenv.d index 0051ecd..a7364c0 100644 --- a/libphobos/libdruntime/core/stdc/fenv.d +++ b/libphobos/libdruntime/core/stdc/fenv.d @@ -448,6 +448,49 @@ else version (CRuntime_Musl) static assert(false, "Architecture not supported."); } } +else version (CRuntime_Newlib) +{ + version (AArch64) + { + alias fenv_t = ulong; + alias fexcept_t = ulong; + } + else version (RISCV_Any) + { + alias fenv_t = size_t; + alias fexcept_t = size_t; + } + else version (X86_Any) + { + struct fenv_t + { + uint _fpu_cw; + uint _fpu_sw; + uint _fpu_tagw; + uint _fpu_ipoff; + uint _fpu_ipsel; + uint _fpu_opoff; + uint _fpu_opsel; + uint _sse_mxcsr; + } + alias fexcept_t = uint; + } + else version (SPARC64) + { + alias fenv_t = ulong; + alias fexcept_t = ulong; + } + else version (SPARC) + { + alias fenv_t = uint; + alias fexcept_t = uint; + } + else + { + alias fenv_t = int; + alias fexcept_t = int; + } +} else version (CRuntime_UClibc) { version (X86) diff --git a/libphobos/libdruntime/core/stdc/locale.d b/libphobos/libdruntime/core/stdc/locale.d index 4b8d5c8..357d75e 100644 --- a/libphobos/libdruntime/core/stdc/locale.d +++ b/libphobos/libdruntime/core/stdc/locale.d @@ -252,6 +252,23 @@ else version (CRuntime_Musl) /// enum LC_ALL = 6; } +else version (CRuntime_Newlib) +{ + /// + enum LC_ALL = 0; + /// + enum LC_COLLATE = 1; + /// + enum LC_CTYPE = 2; + /// + enum LC_MONETARY = 3; + /// + enum LC_NUMERIC = 4; + /// + enum LC_TIME = 5; + /// + enum LC_MESSAGES = 6; +} else version (CRuntime_UClibc) { /// diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d index ee37da1..1fc0461 100644 --- a/libphobos/libdruntime/core/stdc/stdio.d +++ b/libphobos/libdruntime/core/stdc/stdio.d @@ -328,6 +328,30 @@ else version (CRuntime_Bionic) int _size; } } +else version (CRuntime_Newlib) +{ + enum + { + /// + BUFSIZ = 1024, + /// + EOF = -1, + /// + FOPEN_MAX = 20, + /// + FILENAME_MAX = 1024, + /// + TMP_MAX = 26, + /// + L_tmpnam = 1024 + } + + struct __sbuf + { + ubyte* _base; + int _size; + } +} else version (CRuntime_UClibc) { enum @@ -769,6 +793,57 @@ else version (CRuntime_Bionic) /// alias shared(__sFILE) FILE; } +else version (CRuntime_Newlib) +{ + import core.sys.posix.sys.types : ssize_t; + import core.stdc.wchar_ : mbstate_t; + + /// + alias fpos_t = c_long; + + /// + struct __sFILE + { + ubyte* _p; + int _r; + int _w; + short _flags; + short _file; + __sbuf _bf; + int _lbfsize; + + void* _data; + void* _cookie; + + ssize_t function(void*, void*, scope char*, size_t) _read; + ssize_t function(void*, void*, scope const char*, size_t) _write; + fpos_t function(void*, void*, fpos_t, int) _seek; + int function(void*, void*) _close; + + __sbuf _ub; + ubyte* _up; + int _ur; + + ubyte[3] _ubuf; + ubyte[1] _nbuf; + + __sbuf _lb; + + int _blksize; + int _flags2; + + long _offset; + void* _unused; + + void* _lock; + mbstate_t _mbstate; + } + + /// + alias __sFILE _iobuf; // needed for phobos + /// + alias shared(__sFILE) FILE; +} else version (CRuntime_UClibc) { import core.stdc.wchar_ : mbstate_t; @@ -1137,6 +1212,40 @@ else version (CRuntime_Musl) _IONBF = 2, } } +else version (CRuntime_Newlib) +{ + enum + { + /// + _IOFBF = 0, + /// + _IOLBF = 1, + /// + _IONBF = 2, + } + + private + { + shared struct _reent + { + int _errno; + __sFILE* _stdin; + __sFILE* _stdout; + __sFILE* _stderr; + } + _reent* __getreent(); + } + + pragma(inline, true) + { + /// + @property auto stdin()() { return __getreent()._stdin; } + /// + @property auto stdout()() { return __getreent()._stdout; } + /// + @property auto stderr()() { return __getreent()._stderr; } + } +} else version (CRuntime_UClibc) { enum @@ -1869,6 +1978,47 @@ else version (CRuntime_Musl) pragma(printf) int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } +else version (CRuntime_Newlib) +{ + // No unsafe pointer manipulation. + @trusted + { + /// + void rewind(FILE* stream); + /// + pure void clearerr(FILE* stream); + /// + pure int feof(FILE* stream); + /// + pure int ferror(FILE* stream); + /// + int fileno(FILE *); + } + + /// + pragma(printf) + int snprintf(scope char* s, size_t n, scope const char* format, scope const ...); + /// + 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 (CRuntime_UClibc) { // No unsafe pointer manipulation. diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d index 0b42de8..bd5fc2b 100644 --- a/libphobos/libdruntime/core/stdc/stdlib.d +++ b/libphobos/libdruntime/core/stdc/stdlib.d @@ -28,6 +28,8 @@ else version (WatchOS) version (CRuntime_Glibc) version = AlignedAllocSupported; +else version (CRuntime_Newlib) + version = AlignedAllocSupported; else {} extern (C): @@ -97,6 +99,7 @@ else version (DragonFlyBSD) enum RAND_MAX = 0x7fffffff; else version (Solaris) enum RAND_MAX = 0x7fff; else version (CRuntime_Bionic) enum RAND_MAX = 0x7fffffff; else version (CRuntime_Musl) enum RAND_MAX = 0x7fffffff; +else version (CRuntime_Newlib) enum RAND_MAX = 0x7fffffff; else version (CRuntime_UClibc) enum RAND_MAX = 0x7fffffff; else version (WASI) enum RAND_MAX = 0x7fffffff; else static assert( false, "Unsupported platform" ); diff --git a/libphobos/libdruntime/core/stdc/string.d b/libphobos/libdruntime/core/stdc/string.d index 3591a6d..b9e3bb7 100644 --- a/libphobos/libdruntime/core/stdc/string.d +++ b/libphobos/libdruntime/core/stdc/string.d @@ -72,8 +72,15 @@ version (ReturnStrerrorR) const(char)* strerror_r(int errnum, return scope char* buf, size_t buflen); } // This one is +else version (CRuntime_Newlib) +{ + /// + pragma(mangle, "__xpg_strerror_r") + int strerror_r(int errnum, scope char* buf, size_t buflen); +} else { + /// int strerror_r(int errnum, scope char* buf, size_t buflen); } /// diff --git a/libphobos/libdruntime/core/stdc/wchar_.d b/libphobos/libdruntime/core/stdc/wchar_.d index 2d01e26..6ed2dfe 100644 --- a/libphobos/libdruntime/core/stdc/wchar_.d +++ b/libphobos/libdruntime/core/stdc/wchar_.d @@ -106,6 +106,20 @@ else version (Solaris) /// alias mbstate_t = __mbstate_t; } +else version (CRuntime_Newlib) +{ + /// + struct mbstate_t + { + int __count; + union ___value + { + wint_t __wch = 0; + char[4] __wchb; + } + ___value __value; + } +} else version (CRuntime_UClibc) { /// diff --git a/libphobos/libdruntime/core/sys/windows/basetsd.d b/libphobos/libdruntime/core/sys/windows/basetsd.d index e70dbdc..1e5a454 100644 --- a/libphobos/libdruntime/core/sys/windows/basetsd.d +++ b/libphobos/libdruntime/core/sys/windows/basetsd.d @@ -15,9 +15,6 @@ version (Windows): // import. alias HANDLE = void*; -package template DECLARE_HANDLE(string name, base = HANDLE) { - mixin ("alias " ~ base.stringof ~ " " ~ name ~ ";"); -} alias HANDLE* PHANDLE, LPHANDLE; // helper for aligned structs diff --git a/libphobos/libdruntime/core/sys/windows/commctrl.d b/libphobos/libdruntime/core/sys/windows/commctrl.d index dabee56..fe4ebbc 100644 --- a/libphobos/libdruntime/core/sys/windows/commctrl.d +++ b/libphobos/libdruntime/core/sys/windows/commctrl.d @@ -1740,8 +1740,8 @@ enum { I_CHILDRENCALLBACK = -1 } -mixin DECLARE_HANDLE!("HTREEITEM"); -mixin DECLARE_HANDLE!("HIMAGELIST"); +alias HTREEITEM = HANDLE; +alias HIMAGELIST = HANDLE; version (Win64) { @@ -4482,8 +4482,8 @@ static if (_WIN32_IE >= 0x400) { alias RBHITTESTINFO* LPRBHITTESTINFO; } -mixin DECLARE_HANDLE!("HDSA"); -mixin DECLARE_HANDLE!("HDPA"); +alias HDSA = HANDLE; +alias HDPA = HANDLE; version (Unicode) { alias HDITEMW HDITEM; diff --git a/libphobos/libdruntime/core/sys/windows/ddeml.d b/libphobos/libdruntime/core/sys/windows/ddeml.d index 00bad1d..2e8e3ee 100644 --- a/libphobos/libdruntime/core/sys/windows/ddeml.d +++ b/libphobos/libdruntime/core/sys/windows/ddeml.d @@ -15,10 +15,10 @@ pragma(lib, "user32"); import core.sys.windows.basetsd, core.sys.windows.windef, core.sys.windows.winnt; -mixin DECLARE_HANDLE!("HCONVLIST"); -mixin DECLARE_HANDLE!("HCONV"); -mixin DECLARE_HANDLE!("HSZ"); -mixin DECLARE_HANDLE!("HDDEDATA"); +alias HCONVLIST = HANDLE; +alias HCONV = HANDLE; +alias HSZ = HANDLE; +alias HDDEDATA = HANDLE; enum : int { CP_WINANSI = 1004, diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d index 5b02fb5..77141d5 100644 --- a/libphobos/libdruntime/core/sys/windows/dll.d +++ b/libphobos/libdruntime/core/sys/windows/dll.d @@ -487,10 +487,20 @@ bool dll_process_attach( HINSTANCE hInstance, bool attach_threads, }, null ); } -/** same as above, but only usable if druntime is linked statically +version (Shared) version (DigitalMars) private extern(C) extern __gshared void* __ImageBase; + +/** same as above, but checking for shared runtime */ +pragma(inline, false) // version (Shared) only set when compiling druntime bool dll_process_attach( HINSTANCE hInstance, bool attach_threads = true ) { + version (Shared) version (DigitalMars) + { + // cannot declare rt_initSharedModule globally as it then conflicts with the definition in sections_win64.d + pragma(mangle, "rt_initSharedModule") extern(C) bool rt_initSharedModule( void* handle ); + if ( hInstance != &__ImageBase ) + return rt_initSharedModule( hInstance ); + } version (Win64) { return dll_process_attach( hInstance, attach_threads, @@ -506,8 +516,16 @@ bool dll_process_attach( HINSTANCE hInstance, bool attach_threads = true ) /** * to be called from DllMain with reason DLL_PROCESS_DETACH */ +pragma(inline, false) // version (Shared) only set when compiling druntime void dll_process_detach( HINSTANCE hInstance, bool detach_threads = true ) { + version (Shared) version (DigitalMars) + { + // cannot declare rt_termSharedModule globally as it then conflicts with the definition in sections_win64.d + pragma(mangle, "rt_termSharedModule") extern(C) bool rt_termSharedModule( void* handle ); + if ( hInstance != &__ImageBase ) + return cast(void) rt_termSharedModule( hInstance ); + } // notify core.thread.joinLowLevelThread that the DLL is about to be unloaded thread_DLLProcessDetaching = true; @@ -531,6 +549,21 @@ void dll_process_detach( HINSTANCE hInstance, bool detach_threads = true ) Runtime.terminate(); } +/***************************** +* Check whether the D runtime is built as a DLL or linked statically +* +* Returns: +* true = DLL, false = static library +*/ +pragma(inline, false) // version (Shared) only set when compiling druntime +bool isSharedDRuntime() +{ + version (Shared) + return true; + else + return false; +} + /* Make sure that tlsCtorRun is itself a tls variable */ static bool tlsCtorRun; @@ -542,8 +575,15 @@ static ~this() { tlsCtorRun = false; } * Returns: * true for success, false for failure */ -bool dll_thread_attach( bool attach_thread = true, bool initTls = true ) +pragma(inline, false) // version (Shared) only set when compiling druntime +bool dll_thread_attach( bool attach_thread = true, bool initTls = true, HINSTANCE hInstance = null ) { + version (Shared) version (DigitalMars) + { + if ( hInstance && hInstance != &__ImageBase ) + return true; + } + // if the OS has not prepared TLS for us, don't attach to the thread // (happened when running under x64 OS) auto tid = GetCurrentThreadId(); @@ -565,8 +605,15 @@ bool dll_thread_attach( bool attach_thread = true, bool initTls = true ) * Returns: * true for success, false for failure */ -bool dll_thread_detach( bool detach_thread = true, bool exitTls = true ) +pragma(inline, false) // version (Shared) only set when compiling druntime +bool dll_thread_detach( bool detach_thread = true, bool exitTls = true, HINSTANCE hInstance = null ) { + version (Shared) version (DigitalMars) + { + if ( hInstance && hInstance != &__ImageBase ) + return true; + } + // if the OS has not prepared TLS for us, we did not attach to the thread if ( !GetTlsDataAddress( GetCurrentThreadId() ) ) return false; @@ -613,10 +660,10 @@ mixin template SimpleDllMain() return true; case DLL_THREAD_ATTACH: - return dll_thread_attach( true, true ); + return dll_thread_attach( true, true, hInstance ); case DLL_THREAD_DETACH: - return dll_thread_detach( true, true ); + return dll_thread_detach( true, true, hInstance ); } } } diff --git a/libphobos/libdruntime/core/sys/windows/httpext.d b/libphobos/libdruntime/core/sys/windows/httpext.d index 6973879..200b284 100644 --- a/libphobos/libdruntime/core/sys/windows/httpext.d +++ b/libphobos/libdruntime/core/sys/windows/httpext.d @@ -19,7 +19,7 @@ version (Windows): MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ -import core.sys.windows.basetsd /+: DECLARE_HANDLE, HANDLE+/; +import core.sys.windows.basetsd /+: HANDLE+/; import core.sys.windows.windef /+: BOOL, CHAR, DWORD, LPBYTE, LPDWORD+/; import core.sys.windows.winnt /+: LPCSTR, LPSTR, LPVOID, PVOID, VOID+/; @@ -47,7 +47,7 @@ enum { HSE_IO_SEND_HEADERS = 0x00000008 } -mixin DECLARE_HANDLE!("HCONN"); +alias HCONN = HANDLE; struct HSE_VERSION_INFO { DWORD dwExtensionVersion; diff --git a/libphobos/libdruntime/core/sys/windows/imagehlp.d b/libphobos/libdruntime/core/sys/windows/imagehlp.d index 399c0b2..68d88d7 100644 --- a/libphobos/libdruntime/core/sys/windows/imagehlp.d +++ b/libphobos/libdruntime/core/sys/windows/imagehlp.d @@ -275,7 +275,7 @@ struct IMAGEHLP_DUPLICATE_SYMBOL { } alias IMAGEHLP_DUPLICATE_SYMBOL* PIMAGEHLP_DUPLICATE_SYMBOL; -mixin DECLARE_HANDLE!("DIGEST_HANDLE"); +alias DIGEST_HANDLE = HANDLE; extern (Windows) { alias BOOL function(IMAGEHLP_STATUS_REASON, LPSTR, LPSTR, ULONG_PTR, ULONG_PTR) diff --git a/libphobos/libdruntime/core/sys/windows/msacm.d b/libphobos/libdruntime/core/sys/windows/msacm.d index 645e40d..df4d6c4 100644 --- a/libphobos/libdruntime/core/sys/windows/msacm.d +++ b/libphobos/libdruntime/core/sys/windows/msacm.d @@ -14,8 +14,8 @@ version (ANSI) {} else version = Unicode; import core.sys.windows.basetsd, core.sys.windows.mmsystem, core.sys.windows.windef; -mixin DECLARE_HANDLE!("HACMDRIVERID"); -mixin DECLARE_HANDLE!("HACMDRIVER"); +alias HACMDRIVERID = HANDLE; +alias HACMDRIVER = HANDLE; alias HACMDRIVER* LPHACMDRIVER; enum size_t diff --git a/libphobos/libdruntime/core/sys/windows/ntsecapi.d b/libphobos/libdruntime/core/sys/windows/ntsecapi.d index fbc6b7f..fa08a74 100644 --- a/libphobos/libdruntime/core/sys/windows/ntsecapi.d +++ b/libphobos/libdruntime/core/sys/windows/ntsecapi.d @@ -666,7 +666,7 @@ struct POLICY_DOMAIN_KERBEROS_TICKET_INFO { } alias POLICY_DOMAIN_KERBEROS_TICKET_INFO* PPOLICY_DOMAIN_KERBEROS_TICKET_INFO; -mixin DECLARE_HANDLE!("LSA_HANDLE"); +alias LSA_HANDLE = HANDLE; alias LSA_HANDLE* PLSA_HANDLE; struct TRUSTED_DOMAIN_NAME_INFO { diff --git a/libphobos/libdruntime/core/sys/windows/ole.d b/libphobos/libdruntime/core/sys/windows/ole.d index a844124..b9e55a3 100644 --- a/libphobos/libdruntime/core/sys/windows/ole.d +++ b/libphobos/libdruntime/core/sys/windows/ole.d @@ -155,7 +155,7 @@ enum OLEOPT_UPDATE { // #endif } -mixin DECLARE_HANDLE!("HOBJECT"); +alias HOBJECT = HANDLE; alias LONG_PTR LHSERVER, LHCLIENTDOC, LHSERVERDOC; struct OLEOBJECTVTBL { diff --git a/libphobos/libdruntime/core/sys/windows/prsht.d b/libphobos/libdruntime/core/sys/windows/prsht.d index 92596b5..053b1fa 100644 --- a/libphobos/libdruntime/core/sys/windows/prsht.d +++ b/libphobos/libdruntime/core/sys/windows/prsht.d @@ -247,7 +247,7 @@ struct PROPSHEETPAGEW { alias PROPSHEETPAGEW* LPPROPSHEETPAGEW; alias const(PROPSHEETPAGEW)* LPCPROPSHEETPAGEW; -mixin DECLARE_HANDLE!("HPROPSHEETPAGE"); +alias HPROPSHEETPAGE = HANDLE; struct PROPSHEETHEADERA { DWORD dwSize = PROPSHEETHEADERA.sizeof; diff --git a/libphobos/libdruntime/core/sys/windows/rpcdce.d b/libphobos/libdruntime/core/sys/windows/rpcdce.d index 4f3f3cc..951480b 100644 --- a/libphobos/libdruntime/core/sys/windows/rpcdce.d +++ b/libphobos/libdruntime/core/sys/windows/rpcdce.d @@ -160,8 +160,8 @@ struct RPC_IF_ID_VECTOR { uint Count; RPC_IF_ID*[1] IfId; } -mixin DECLARE_HANDLE!("RPC_AUTH_IDENTITY_HANDLE"); -mixin DECLARE_HANDLE!("RPC_AUTHZ_HANDLE"); +alias RPC_AUTH_IDENTITY_HANDLE = HANDLE; +alias RPC_AUTHZ_HANDLE = HANDLE; struct RPC_SECURITY_QOS { uint Version; diff --git a/libphobos/libdruntime/core/sys/windows/rpcdcep.d b/libphobos/libdruntime/core/sys/windows/rpcdcep.d index 71b82be..421c275 100644 --- a/libphobos/libdruntime/core/sys/windows/rpcdcep.d +++ b/libphobos/libdruntime/core/sys/windows/rpcdcep.d @@ -15,7 +15,7 @@ import core.sys.windows.basetyps; import core.sys.windows.w32api; import core.sys.windows.windef; -mixin DECLARE_HANDLE!("I_RPC_HANDLE"); +alias I_RPC_HANDLE = HANDLE; alias long RPC_STATUS; enum RPC_NCA_FLAGS_DEFAULT=0; diff --git a/libphobos/libdruntime/core/sys/windows/rpcnsi.d b/libphobos/libdruntime/core/sys/windows/rpcnsi.d index 1294d0d..60c7b09 100644 --- a/libphobos/libdruntime/core/sys/windows/rpcnsi.d +++ b/libphobos/libdruntime/core/sys/windows/rpcnsi.d @@ -18,7 +18,7 @@ import core.sys.windows.basetyps, core.sys.windows.rpcdcep, core.sys.windows.rpc core.sys.windows.w32api; import core.sys.windows.windef; // for HANDLE -mixin DECLARE_HANDLE!("RPC_NS_HANDLE"); +alias RPC_NS_HANDLE = HANDLE; enum RPC_C_NS_SYNTAX_DEFAULT=0; enum RPC_C_NS_SYNTAX_DCE=3; diff --git a/libphobos/libdruntime/core/sys/windows/setupapi.d b/libphobos/libdruntime/core/sys/windows/setupapi.d index 7a052cd..da50386 100644 --- a/libphobos/libdruntime/core/sys/windows/setupapi.d +++ b/libphobos/libdruntime/core/sys/windows/setupapi.d @@ -858,7 +858,7 @@ enum : DWORD { alias PVOID HINF; alias PVOID HDSKSPC; -mixin DECLARE_HANDLE!("HDEVINFO"); +alias HDEVINFO = HANDLE; alias PVOID HSPFILEQ; alias PVOID HSPFILELOG; diff --git a/libphobos/libdruntime/core/sys/windows/shellapi.d b/libphobos/libdruntime/core/sys/windows/shellapi.d index fdd9938..2ddf680 100644 --- a/libphobos/libdruntime/core/sys/windows/shellapi.d +++ b/libphobos/libdruntime/core/sys/windows/shellapi.d @@ -188,7 +188,7 @@ enum SHERB_NOPROGRESSUI = 2; enum SHERB_NOSOUND = 4; alias WORD FILEOP_FLAGS, PRINTEROP_FLAGS; -mixin DECLARE_HANDLE!("HDROP"); +alias HDROP = HANDLE; //align(2): // 1 in Win32, default in Win64 diff --git a/libphobos/libdruntime/core/sys/windows/shlwapi.d b/libphobos/libdruntime/core/sys/windows/shlwapi.d index cfabbad..3562003 100644 --- a/libphobos/libdruntime/core/sys/windows/shlwapi.d +++ b/libphobos/libdruntime/core/sys/windows/shlwapi.d @@ -120,7 +120,7 @@ enum URLIS URLIS_HASQUERY } -mixin DECLARE_HANDLE!("HUSKEY"); +alias HUSKEY = HANDLE; alias HUSKEY* PHUSKEY; extern (Windows) diff --git a/libphobos/libdruntime/core/sys/windows/subauth.d b/libphobos/libdruntime/core/sys/windows/subauth.d index a48fb99..8240d9f4 100644 --- a/libphobos/libdruntime/core/sys/windows/subauth.d +++ b/libphobos/libdruntime/core/sys/windows/subauth.d @@ -106,7 +106,7 @@ struct STRING { alias STRING* PSTRING; +/ -mixin DECLARE_HANDLE!("SAM_HANDLE"); +alias SAM_HANDLE = HANDLE; alias SAM_HANDLE* PSAM_HANDLE; struct OLD_LARGE_INTEGER { diff --git a/libphobos/libdruntime/core/sys/windows/vfw.d b/libphobos/libdruntime/core/sys/windows/vfw.d index e8ca74e..c0f22a9 100644 --- a/libphobos/libdruntime/core/sys/windows/vfw.d +++ b/libphobos/libdruntime/core/sys/windows/vfw.d @@ -678,7 +678,7 @@ extern (Windows) { void ICCompressorFree(PCOMPVARS pc); } -mixin DECLARE_HANDLE!("HDRAWDIB"); +alias HDRAWDIB = HANDLE; enum { DDF_0001 = 0x0001, diff --git a/libphobos/libdruntime/core/sys/windows/windef.d b/libphobos/libdruntime/core/sys/windows/windef.d index 4e951f3..105be44 100644 --- a/libphobos/libdruntime/core/sys/windows/windef.d +++ b/libphobos/libdruntime/core/sys/windows/windef.d @@ -74,43 +74,43 @@ alias const(void)* PCVOID, LPCVOID; alias UINT_PTR WPARAM; alias LONG_PTR LPARAM, LRESULT; -mixin DECLARE_HANDLE!("HHOOK"); -mixin DECLARE_HANDLE!("HGLOBAL"); -mixin DECLARE_HANDLE!("HLOCAL"); -mixin DECLARE_HANDLE!("GLOBALHANDLE"); -mixin DECLARE_HANDLE!("LOCALHANDLE"); -mixin DECLARE_HANDLE!("HGDIOBJ"); -mixin DECLARE_HANDLE!("HACCEL"); -mixin DECLARE_HANDLE!("HBITMAP", HGDIOBJ); -mixin DECLARE_HANDLE!("HBRUSH", HGDIOBJ); -mixin DECLARE_HANDLE!("HCOLORSPACE"); -mixin DECLARE_HANDLE!("HDC"); -mixin DECLARE_HANDLE!("HGLRC"); -mixin DECLARE_HANDLE!("HDESK"); -mixin DECLARE_HANDLE!("HENHMETAFILE"); -mixin DECLARE_HANDLE!("HFONT", HGDIOBJ); -mixin DECLARE_HANDLE!("HICON"); -mixin DECLARE_HANDLE!("HINSTANCE"); -mixin DECLARE_HANDLE!("HKEY"); -mixin DECLARE_HANDLE!("HMENU"); -mixin DECLARE_HANDLE!("HMETAFILE"); -mixin DECLARE_HANDLE!("HMODULE"); -mixin DECLARE_HANDLE!("HMONITOR"); -mixin DECLARE_HANDLE!("HPALETTE"); -mixin DECLARE_HANDLE!("HPEN", HGDIOBJ); -mixin DECLARE_HANDLE!("HRGN", HGDIOBJ); -mixin DECLARE_HANDLE!("HRSRC"); -mixin DECLARE_HANDLE!("HSTR"); -mixin DECLARE_HANDLE!("HTASK"); -mixin DECLARE_HANDLE!("HWND"); -mixin DECLARE_HANDLE!("HWINSTA"); -mixin DECLARE_HANDLE!("HKL"); -mixin DECLARE_HANDLE!("HCURSOR"); +alias HHOOK = HANDLE; +alias HGLOBAL = HANDLE; +alias HLOCAL = HANDLE; +alias GLOBALHANDLE = HANDLE; +alias LOCALHANDLE = HANDLE; +alias HGDIOBJ = HANDLE; +alias HACCEL = HANDLE; +alias HBITMAP = HGDIOBJ; +alias HBRUSH = HGDIOBJ; +alias HCOLORSPACE = HANDLE; +alias HDC = HANDLE; +alias HGLRC = HANDLE; +alias HDESK = HANDLE; +alias HENHMETAFILE = HANDLE; +alias HFONT = HGDIOBJ; +alias HICON = HANDLE; +alias HINSTANCE = HANDLE; +alias HKEY = HANDLE; +alias HMENU = HANDLE; +alias HMETAFILE = HANDLE; +alias HMODULE = HANDLE; +alias HMONITOR = HANDLE; +alias HPALETTE = HANDLE; +alias HPEN = HGDIOBJ; +alias HRGN = HGDIOBJ; +alias HRSRC = HANDLE; +alias HSTR = HANDLE; +alias HTASK = HANDLE; +alias HWND = HANDLE; +alias HWINSTA = HANDLE; +alias HKL = HANDLE; +alias HCURSOR = HANDLE; alias HKEY* PHKEY; static if (_WIN32_WINNT >= 0x500) { - mixin DECLARE_HANDLE!("HTERMINAL"); - mixin DECLARE_HANDLE!("HWINEVENTHOOK"); + alias HTERMINAL = HANDLE; + alias HWINEVENTHOOK = HANDLE; } alias extern (Windows) INT_PTR function() nothrow FARPROC, NEARPROC, PROC; diff --git a/libphobos/libdruntime/core/sys/windows/wininet.d b/libphobos/libdruntime/core/sys/windows/wininet.d index 328af50..790d4d0 100644 --- a/libphobos/libdruntime/core/sys/windows/wininet.d +++ b/libphobos/libdruntime/core/sys/windows/wininet.d @@ -740,7 +740,8 @@ enum { INTERNET_CACHE_GROUP_REMOVE = 1 } -mixin DECLARE_HANDLE!("HINTERNET"); // doesn't work - bug +alias HINTERNET = HANDLE; +// mixin DECLARE_HANDLE!("HINTERNET"); // doesn't work - bug /*struct HINTERNET { HANDLE h; alias h this; diff --git a/libphobos/libdruntime/core/sys/windows/winsvc.d b/libphobos/libdruntime/core/sys/windows/winsvc.d index f7f2fa7..e6418ac 100644 --- a/libphobos/libdruntime/core/sys/windows/winsvc.d +++ b/libphobos/libdruntime/core/sys/windows/winsvc.d @@ -184,10 +184,10 @@ struct SERVICE_TABLE_ENTRYW { } alias SERVICE_TABLE_ENTRYW* LPSERVICE_TABLE_ENTRYW; -mixin DECLARE_HANDLE!("SC_HANDLE"); +alias SC_HANDLE = HANDLE; alias SC_HANDLE* LPSC_HANDLE; alias void* SC_LOCK; -mixin DECLARE_HANDLE!("SERVICE_STATUS_HANDLE"); +alias SERVICE_STATUS_HANDLE = HANDLE; extern (Windows) { alias void function(DWORD) LPHANDLER_FUNCTION; diff --git a/libphobos/libdruntime/core/sys/windows/winuser.d b/libphobos/libdruntime/core/sys/windows/winuser.d index 829952d..469e68e 100644 --- a/libphobos/libdruntime/core/sys/windows/winuser.d +++ b/libphobos/libdruntime/core/sys/windows/winuser.d @@ -2495,8 +2495,8 @@ extern (Windows) nothrow { alias NAMEENUMPROCW WINSTAENUMPROCW; } -mixin DECLARE_HANDLE!("HDWP"); -mixin DECLARE_HANDLE!("HDEVNOTIFY"); +alias HDWP = HANDLE; +alias HDEVNOTIFY = HANDLE; struct MENUGETOBJECTINFO { DWORD dwFlags; diff --git a/libphobos/libdruntime/core/sys/windows/wtypes.d b/libphobos/libdruntime/core/sys/windows/wtypes.d index 0206839..881f05a 100644 --- a/libphobos/libdruntime/core/sys/windows/wtypes.d +++ b/libphobos/libdruntime/core/sys/windows/wtypes.d @@ -96,8 +96,8 @@ alias OLECHAR* BSTR; alias FLAGGED_WORD_BLOB* wireBSTR; alias BSTR* LPBSTR; //alias LONG SCODE; // also in winerror -mixin DECLARE_HANDLE!("HCONTEXT"); -mixin DECLARE_HANDLE!("HMETAFILEPICT"); +alias HCONTEXT = HANDLE; +alias HMETAFILEPICT = HANDLE; union CY { struct { diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d index 1b39a27..710f4cc 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -1646,10 +1646,10 @@ class TypeInfo_Class : TypeInfo string name; /// class name void*[] vtbl; /// virtual function pointer table Interface[] interfaces; /// interfaces this class implements - TypeInfo_Class base; /// base class + TypeInfo_Class base; /// base class void* destructor; void function(Object) classInvariant; - enum ClassFlags : uint + enum ClassFlags : ushort { isCOMclass = 0x1, noPointers = 0x2, @@ -1660,11 +1660,14 @@ class TypeInfo_Class : TypeInfo isAbstract = 0x40, isCPPclass = 0x80, hasDtor = 0x100, + hasNameSig = 0x200, } ClassFlags m_flags; - void* deallocator; + ushort depth; /// inheritance distance from Object + void* deallocator; OffsetTypeInfo[] m_offTi; void function(Object) defaultConstructor; // default Constructor + ulong[2] nameSig; /// unique signature for `name` immutable(void)* m_RTInfo; // data for precise GC override @property immutable(void)* rtInfo() const { return m_RTInfo; } diff --git a/libphobos/libdruntime/rt/cast_.d b/libphobos/libdruntime/rt/cast_.d index 925599e..44e0f7a 100644 --- a/libphobos/libdruntime/rt/cast_.d +++ b/libphobos/libdruntime/rt/cast_.d @@ -23,10 +23,12 @@ pure: // but we are trying to implement dynamic cast. extern (D) private bool areClassInfosEqual(scope const ClassInfo a, scope const ClassInfo b) @safe { - if (a is b) - return true; - // take care of potential duplicates across binaries - return a.name == b.name; + // same class if signatures match, works with potential duplicates across binaries + return a is b || + (a.m_flags & TypeInfo_Class.ClassFlags.hasNameSig + ? (a.nameSig[0] == b.nameSig[0] && + a.nameSig[1] == b.nameSig[1]) // new fast way + : (a is b || a.name == b.name)); // old slow way for temporary binary compatibility } /****************************************** @@ -58,7 +60,7 @@ Object _d_toObject(return scope void* p) } /************************************* - * Attempts to cast Object o to class c. + * Attempts to cast interface Object o to class c. * Returns o if successful, null if not. */ void* _d_interface_cast(void* p, ClassInfo c) @@ -70,9 +72,26 @@ void* _d_interface_cast(void* p, ClassInfo c) Interface* pi = **cast(Interface***) p; debug(cast_) printf("\tpi.offset = %d\n", pi.offset); - return _d_dynamic_cast(cast(Object)(p - pi.offset), c); + Object o2 = cast(Object)(p - pi.offset); + void* res = null; + size_t offset = 0; + if (o2 && _d_isbaseof2(typeid(o2), c, offset)) + { + debug(cast_) printf("\toffset = %d\n", offset); + res = cast(void*) o2 + offset; + } + debug(cast_) printf("\tresult = %p\n", res); + return res; } +/***** + * Dynamic cast from a class object `o` to class or interface `c`, where `c` is a subtype of `o`. + * Params: + * o = instance of class + * c = a subclass of o + * Returns: + * null if o is null or c is not a subclass of o. Otherwise, return o. + */ void* _d_dynamic_cast(Object o, ClassInfo c) { debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); @@ -88,6 +107,64 @@ void* _d_dynamic_cast(Object o, ClassInfo c) return res; } +/***** + * Dynamic cast from a class object o to class c, where c is a subclass of o. + * Params: + * o = instance of class + * c = a subclass of o + * Returns: + * null if o is null or c is not a subclass of o. Otherwise, return o. + */ +void* _d_class_cast(Object o, ClassInfo c) +{ + debug(cast_) printf("_d_cast_cast(o = %p, c = '%.*s', level %d)\n", o, c.name, level); + + if (!o) + return null; + + ClassInfo oc = typeid(o); + int delta = oc.depth; + + if (delta && c.depth) + { + delta -= c.depth; + if (delta < 0) + return null; + + while (delta--) + oc = oc.base; + if (areClassInfosEqual(oc, c)) + return cast(void*)o; + return null; + } + + // no depth data - support the old way + do + { + if (areClassInfosEqual(oc, c)) + return cast(void*)o; + oc = oc.base; + } while (oc); + return null; +} + +/** + * Dynamic cast `o` to final class `c` only one level down + * Params: + * o = object that is instance of a class + * c = class to cast it to + * Returns: + * o if it succeeds, null if it fails + */ +void* _d_paint_cast(Object o, ClassInfo c) +{ + /* If o is really an instance of c, just do a paint + */ + auto p = (o && cast(void*)(areClassInfosEqual(typeid(o), c)) ? o : null); + debug assert(cast(void*)p is cast(void*)_d_dynamic_cast(o, c)); + return cast(void*)p; +} + int _d_isbaseof2(scope ClassInfo oc, scope const ClassInfo c, scope ref size_t offset) @safe { if (areClassInfosEqual(oc, c)) diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d index 8a10aac..5ac053c 100644 --- a/libphobos/libdruntime/rt/dmain2.d +++ b/libphobos/libdruntime/rt/dmain2.d @@ -496,6 +496,13 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF { if (rt_init()) { + version(Shared) version(CRuntime_Microsoft) version (DigitalMars) + { + auto exeHandle = handleForAddr(mainFunc); + if (exeHandle) + if (!rt_initSharedModule(exeHandle)) + exeHandle = null; + } auto utResult = runModuleUnitTests(); assert(utResult.passed <= utResult.executed); if (utResult.passed == utResult.executed) @@ -521,6 +528,11 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF cast(int)utResult.executed); result = EXIT_FAILURE; } + version(Shared) version(CRuntime_Microsoft) version (DigitalMars) + { + if (exeHandle) + rt_termSharedModule(exeHandle); + } } else result = EXIT_FAILURE; diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index 103a93f..b29da3b 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -7a6e9568862f5a0d9eb34707d85dcf7ff889c26f +e4d0dd5136be3c539a02cc2f1618cb989a685837 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/bitmanip.d b/libphobos/src/std/bitmanip.d index b84a676..e9f6191 100644 --- a/libphobos/src/std/bitmanip.d +++ b/libphobos/src/std/bitmanip.d @@ -279,10 +279,8 @@ See_Also: $(REF BitFlags, std,typecons) */ string bitfields(T...)() { - import std.conv : to; - static assert(T.length % 3 == 0, - "Wrong number of arguments (" ~ to!string(T.length) ~ "): Must be a multiple of 3"); + "Wrong number of arguments (" ~ T.length.stringof ~ "): Must be a multiple of 3"); static foreach (i, ARG; T) { diff --git a/libphobos/src/std/complex.d b/libphobos/src/std/complex.d index 347e351..60746f9 100644 --- a/libphobos/src/std/complex.d +++ b/libphobos/src/std/complex.d @@ -1892,7 +1892,7 @@ Complex!T pow(T)(const T x, Complex!T n) @trusted pure nothrow @nogc @safe pure nothrow @nogc unittest { import std.meta : AliasSeq; - import std.math : RealFormat, floatTraits; + import std.math.traits : floatTraits, RealFormat; static foreach (T; AliasSeq!(float, double, real)) {{ static if (floatTraits!T.realFormat == RealFormat.ibmExtended) diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d index 23b33c4..5d02df0 100644 --- a/libphobos/src/std/conv.d +++ b/libphobos/src/std/conv.d @@ -1804,7 +1804,7 @@ if (!is(S : T) && isAssociativeArray!S && } static void testFloatingToIntegral(Floating, Integral)() { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; bool convFails(Source, Target, E)(Source src) { @@ -3430,7 +3430,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && Target result = cast(Target) (sign ? -ldval : ldval); // if overflow occurred - import std.math : isFinite; + import std.math.traits : isFinite; enforce(isFinite(result), new ConvException("Range error")); advanceSource(); @@ -3598,7 +3598,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && @system unittest { // @system because strtod is not @safe. - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; static if (floatTraits!real.realFormat == RealFormat.ieeeDouble) { @@ -3682,7 +3682,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && { import core.stdc.errno; import core.stdc.stdlib; - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; errno = 0; // In case it was set by another unittest in a different module. struct longdouble diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d index 5c78685..58a667c 100644 --- a/libphobos/src/std/exception.d +++ b/libphobos/src/std/exception.d @@ -1632,6 +1632,9 @@ class ErrnoException : Exception /// Operating system error code. final @property uint errno() nothrow pure scope @nogc @safe { return _errno; } private uint _errno; + /// Localized error message generated through $(REF strerror_r, core,stdc,string) or $(REF strerror, core,stdc,string). + final @property string errnoMsg() nothrow pure scope @nogc @safe { return _errnoMsg; } + private string _errnoMsg; /// Constructor which takes an error message. The current global $(REF errno, core,stdc,errno) value is used as error code. this(string msg, string file = null, size_t line = 0) @safe { @@ -1642,7 +1645,8 @@ class ErrnoException : Exception this(string msg, int errno, string file = null, size_t line = 0) @safe { _errno = errno; - super(msg ~ " (" ~ errnoString(errno) ~ ")", file, line); + _errnoMsg = errnoString(errno); + super(msg ~ " (" ~ errnoMsg ~ ")", file, line); } } diff --git a/libphobos/src/std/format/internal/floats.d b/libphobos/src/std/format/internal/floats.d index afe0bfa..88b9d22 100644 --- a/libphobos/src/std/format/internal/floats.d +++ b/libphobos/src/std/format/internal/floats.d @@ -28,6 +28,15 @@ if (is(T == float) || is(T == double) return w.data; } +/// Returns: whether `c` is a supported format specifier for floats +package(std.format) bool isFloatSpec(char c) nothrow @nogc pure @safe +{ + return c == 'a' || c == 'A' + || c == 'e' || c == 'E' + || c == 'f' || c == 'F' + || c == 'g' || c == 'G'; +} + package(std.format) void printFloat(Writer, T, Char)(auto ref Writer w, const(T) val, FormatSpec!Char f) if (is(T == float) || is(T == double) || (is(T == real) && (T.mant_dig == double.mant_dig || T.mant_dig == 64))) @@ -43,10 +52,7 @@ if (is(T == float) || is(T == double) if (sgn == "" && f.flPlus) sgn = "+"; if (sgn == "" && f.flSpace) sgn = " "; - assert(f.spec == 'a' || f.spec == 'A' - || f.spec == 'e' || f.spec == 'E' - || f.spec == 'f' || f.spec == 'F' - || f.spec == 'g' || f.spec == 'G', "unsupported format specifier"); + assert(isFloatSpec(f.spec), "unsupported format specifier"); bool is_upper = f.spec == 'A' || f.spec == 'E' || f.spec=='F' || f.spec=='G'; // special treatment for nan and inf diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d index 85954fa..16c7a51 100644 --- a/libphobos/src/std/format/internal/write.d +++ b/libphobos/src/std/format/internal/write.d @@ -570,9 +570,9 @@ void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) obj, scope const ref FormatSpec!Char f) if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) { - import std.algorithm.searching : find; import std.format : enforceFmt; import std.range.primitives : put; + import std.format.internal.floats : printFloat, isFloatSpec; FloatingPointTypeOf!T val = obj; const char spec = f.spec; @@ -597,11 +597,9 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) return; } - enforceFmt(find("fgFGaAeEs", spec).length, - "incompatible format character for floating point argument: %" ~ spec); - FormatSpec!Char fs = f; // fs is copy for change its values. fs.spec = spec == 's' ? 'g' : spec; + enforceFmt(isFloatSpec(fs.spec), "incompatible format character for floating point argument: %" ~ spec); static if (is(T == float) || is(T == double) || (is(T == real) && (T.mant_dig == double.mant_dig || T.mant_dig == 64))) @@ -631,7 +629,6 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) tval = -doubleLowest; } - import std.format.internal.floats : printFloat; printFloat(w, tval, fs); } diff --git a/libphobos/src/std/math/algebraic.d b/libphobos/src/std/math/algebraic.d index 9999071..fd30523 100644 --- a/libphobos/src/std/math/algebraic.d +++ b/libphobos/src/std/math/algebraic.d @@ -308,7 +308,7 @@ if (isFloatingPoint!T) // If both are huge, avoid overflow by scaling by 2^^-N. // If both are tiny, avoid underflow by scaling by 2^^N. import core.math : fabs, sqrt; - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; alias F = floatTraits!T; diff --git a/libphobos/src/std/math/exponential.d b/libphobos/src/std/math/exponential.d index 8290479..5e90f0d 100644 --- a/libphobos/src/std/math/exponential.d +++ b/libphobos/src/std/math/exponential.d @@ -1002,8 +1002,7 @@ float exp(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) exp(ca private T expImpl(T)(T x) @safe pure nothrow @nogc { - import std.math : floatTraits, RealFormat; - import std.math.traits : isNaN; + import std.math.traits : floatTraits, RealFormat, isNaN; import std.math.rounding : floor; import std.math.algebraic : poly; import std.math.constants : LOG2E; @@ -1143,7 +1142,7 @@ private T expImpl(T)(T x) @safe pure nothrow @nogc @safe @nogc nothrow unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.math.operations : NaN, feqrel, isClose; import std.math.constants : E; import std.math.traits : isIdentical; @@ -1517,7 +1516,7 @@ L_largenegative: private T expm1Impl(T)(T x) @safe pure nothrow @nogc { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.math.rounding : floor; import std.math.algebraic : poly; import std.math.constants : LN2; @@ -1909,8 +1908,7 @@ L_was_nan: private T exp2Impl(T)(T x) @nogc @safe pure nothrow { - import std.math : floatTraits, RealFormat; - import std.math.traits : isNaN; + import std.math.traits : floatTraits, RealFormat, isNaN; import std.math.rounding : floor; import std.math.algebraic : poly; @@ -2098,8 +2096,7 @@ private T exp2Impl(T)(T x) @nogc @safe pure nothrow T frexp(T)(const T value, out int exp) @trusted pure nothrow @nogc if (isFloatingPoint!T) { - import std.math : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; - import std.math.traits : isSubnormal; + import std.math.traits : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB, isSubnormal; if (__ctfe) { @@ -2353,8 +2350,7 @@ if (isFloatingPoint!T) @safe unittest { - import std.math : floatTraits, RealFormat; - import std.math.traits : isIdentical; + import std.math.traits : floatTraits, RealFormat, isIdentical; import std.meta : AliasSeq; import std.typecons : tuple, Tuple; @@ -2486,7 +2482,7 @@ if (isFloatingPoint!T) int ilogb(T)(const T x) @trusted pure nothrow @nogc if (isFloatingPoint!T) { - import std.math : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; + import std.math.traits : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; import core.bitop : bsr; alias F = floatTraits!T; @@ -2681,7 +2677,7 @@ alias FP_ILOGBNAN = core.stdc.math.FP_ILOGBNAN; @safe nothrow @nogc unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.math.operations : nextUp; import std.meta : AliasSeq; import std.typecons : Tuple; @@ -2778,7 +2774,7 @@ float ldexp(float n, int exp) @safe pure nothrow @nogc { return core.math.ldex @safe pure nothrow @nogc unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended || floatTraits!(real).realFormat == RealFormat.ieeeExtended53 || @@ -2866,7 +2862,7 @@ private // Coefficients shared across log(), log2(), log10(), log1p(). template LogCoeffs(T) { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; static if (floatTraits!T.realFormat == RealFormat.ieeeQuadruple) { @@ -3179,8 +3175,7 @@ private T logImpl(T, bool LOG1P = false)(T x) @safe pure nothrow @nogc { import std.math.constants : SQRT1_2; import std.math.algebraic : poly; - import std.math.traits : isInfinity, isNaN, signbit; - import std.math : floatTraits, RealFormat; + import std.math.traits : isInfinity, isNaN, signbit, floatTraits, RealFormat; alias coeffs = LogCoeffs!T; alias F = floatTraits!T; @@ -3306,7 +3301,7 @@ private T logImpl(T, bool LOG1P = false)(T x) @safe pure nothrow @nogc @safe @nogc nothrow unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.meta : AliasSeq; static void testLog(T)(T[2][] vals) @@ -3452,8 +3447,7 @@ private T log10Impl(T)(T x) @safe pure nothrow @nogc { import std.math.constants : SQRT1_2; import std.math.algebraic : poly; - import std.math.traits : isNaN, isInfinity, signbit; - import std.math : floatTraits, RealFormat; + import std.math.traits : isNaN, isInfinity, signbit, floatTraits, RealFormat; alias coeffs = LogCoeffs!T; alias F = floatTraits!T; @@ -3558,7 +3552,7 @@ Ldone: @safe @nogc nothrow unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.meta : AliasSeq; static void testLog10(T)(T[2][] vals) @@ -3710,7 +3704,7 @@ private T log1pImpl(T)(T x) @safe pure nothrow @nogc import std.math.traits : isNaN, isInfinity, signbit; import std.math.algebraic : poly; import std.math.constants : SQRT1_2, SQRT2; - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; // Special cases. if (isNaN(x) || x == 0.0) @@ -3746,7 +3740,7 @@ private T log1pImpl(T)(T x) @safe pure nothrow @nogc @safe @nogc nothrow unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.meta : AliasSeq; static void testLog1p(T)(T[2][] vals) @@ -3891,7 +3885,7 @@ private T log2Impl(T)(T x) @safe pure nothrow @nogc import std.math.traits : isNaN, isInfinity, signbit; import std.math.constants : SQRT1_2, LOG2E; import std.math.algebraic : poly; - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; alias coeffs = LogCoeffs!T; alias F = floatTraits!T; @@ -3972,7 +3966,7 @@ Ldone: @safe @nogc nothrow unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.meta : AliasSeq; static void testLog2(T)(T[2][] vals) @@ -4172,7 +4166,7 @@ private T logbImpl(T)(T x) @trusted pure nothrow @nogc @safe @nogc nothrow unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.meta : AliasSeq; static void testLogb(T)(T[2][] vals) diff --git a/libphobos/src/std/math/hardware.d b/libphobos/src/std/math/hardware.d index cb6cb87..c7c5d6e 100644 --- a/libphobos/src/std/math/hardware.d +++ b/libphobos/src/std/math/hardware.d @@ -210,14 +210,12 @@ private: } else version (RISCV_Any) { - mixin(` uint result = void; asm pure nothrow @nogc { "frflags %0" : "=r" (result); } return result; - `); } else version (LoongArch_Any) { @@ -307,13 +305,11 @@ private: } else version (RISCV_Any) { - mixin(` uint newValues = 0x0; asm pure nothrow @nogc { "fsflags %0" : : "r" (newValues); } - `); } else version (LoongArch_Any) { @@ -1039,14 +1035,12 @@ private: } else version (RISCV_Any) { - mixin(` ControlState cont; asm pure nothrow @nogc { "frcsr %0" : "=r" (cont); } return cont; - `); } else version (LoongArch_Any) { @@ -1163,12 +1157,10 @@ private: } else version (RISCV_Any) { - mixin(` asm pure nothrow @nogc { "fscsr %0" : : "r" (newState); } - `); } else version (LoongArch_Any) { diff --git a/libphobos/src/std/math/operations.d b/libphobos/src/std/math/operations.d index 4bf19ee..d456e29 100644 --- a/libphobos/src/std/math/operations.d +++ b/libphobos/src/std/math/operations.d @@ -44,7 +44,7 @@ import std.traits : CommonType, isFloatingPoint, isIntegral, Unqual; */ real NaN(ulong payload) @trusted pure nothrow @nogc { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; alias F = floatTraits!(real); static if (F.realFormat == RealFormat.ieeeExtended || @@ -136,7 +136,7 @@ real NaN(ulong payload) @trusted pure nothrow @nogc @system pure nothrow @nogc unittest // not @safe because taking address of local. { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; static if (floatTraits!(real).realFormat == RealFormat.ieeeDouble) { @@ -159,7 +159,7 @@ real NaN(ulong payload) @trusted pure nothrow @nogc */ ulong getNaNPayload(real x) @trusted pure nothrow @nogc { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; // assert(isNaN(x)); alias F = floatTraits!(real); @@ -283,7 +283,7 @@ debug(UnitTest) */ real nextUp(real x) @trusted pure nothrow @nogc { - import std.math : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; + import std.math.traits : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; alias F = floatTraits!(real); static if (F.realFormat != RealFormat.ieeeDouble) @@ -522,8 +522,7 @@ float nextDown(float x) @safe pure nothrow @nogc @safe pure nothrow @nogc unittest { - import std.math : floatTraits, RealFormat; - import std.math.traits : isIdentical; + import std.math.traits : floatTraits, RealFormat, isIdentical; static if (floatTraits!(real).realFormat == RealFormat.ieeeExtended || floatTraits!(real).realFormat == RealFormat.ieeeDouble || @@ -865,7 +864,7 @@ real fma(real x, real y, real z) @safe pure nothrow @nogc { return (x * y) + z; int feqrel(X)(const X x, const X y) @trusted pure nothrow @nogc if (isFloatingPoint!(X)) { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import core.math : fabs; /* Public Domain. Author: Don Clugston, 18 Aug 2005. @@ -1495,7 +1494,7 @@ private template FloatingPointBaseType(T) int cmp(T)(const(T) x, const(T) y) @nogc @trusted pure nothrow if (isFloatingPoint!T) { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; alias F = floatTraits!T; @@ -1723,7 +1722,7 @@ if (isFloatingPoint!T) FloatingPointBitpattern!T extractBitpattern(T)(const(T) value) @trusted if (isFloatingPoint!T) { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; T val = value; FloatingPointBitpattern!T ret; @@ -1895,7 +1894,7 @@ if (isFloatingPoint!T) @safe pure unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; alias F = floatTraits!real; static if (F.realFormat == RealFormat.ieeeExtended) @@ -1946,7 +1945,7 @@ if (isFloatingPoint!T) @safe pure unittest { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.math.exponential : log2; alias F = floatTraits!real; diff --git a/libphobos/src/std/math/package.d b/libphobos/src/std/math/package.d index 614f4d3..0d1ecc3 100644 --- a/libphobos/src/std/math/package.d +++ b/libphobos/src/std/math/package.d @@ -321,169 +321,3 @@ else static assert(real.mant_dig == 53 || real.mant_dig == 113, "Only 64-bit and 128-bit reals are supported for BigEndian CPUs."); } - -// Underlying format exposed through floatTraits -enum RealFormat -{ - ieeeHalf, - ieeeSingle, - ieeeDouble, - ieeeExtended, // x87 80-bit real - ieeeExtended53, // x87 real rounded to precision of double. - ibmExtended, // IBM 128-bit extended - ieeeQuadruple, -} - -// Constants used for extracting the components of the representation. -// They supplement the built-in floating point properties. -template floatTraits(T) -{ - import std.traits : Unqual; - - // EXPMASK is a ushort mask to select the exponent portion (without sign) - // EXPSHIFT is the number of bits the exponent is left-shifted by in its ushort - // EXPBIAS is the exponent bias - 1 (exp == EXPBIAS yields ×2^-1). - // EXPPOS_SHORT is the index of the exponent when represented as a ushort array. - // SIGNPOS_BYTE is the index of the sign when represented as a ubyte array. - // RECIP_EPSILON is the value such that (smallest_subnormal) * RECIP_EPSILON == T.min_normal - enum Unqual!T RECIP_EPSILON = (1/T.epsilon); - static if (T.mant_dig == 24) - { - // Single precision float - enum ushort EXPMASK = 0x7F80; - enum ushort EXPSHIFT = 7; - enum ushort EXPBIAS = 0x3F00; - enum uint EXPMASK_INT = 0x7F80_0000; - enum uint MANTISSAMASK_INT = 0x007F_FFFF; - enum realFormat = RealFormat.ieeeSingle; - version (LittleEndian) - { - enum EXPPOS_SHORT = 1; - enum SIGNPOS_BYTE = 3; - } - else - { - enum EXPPOS_SHORT = 0; - enum SIGNPOS_BYTE = 0; - } - } - else static if (T.mant_dig == 53) - { - static if (T.sizeof == 8) - { - // Double precision float, or real == double - enum ushort EXPMASK = 0x7FF0; - enum ushort EXPSHIFT = 4; - enum ushort EXPBIAS = 0x3FE0; - enum uint EXPMASK_INT = 0x7FF0_0000; - enum uint MANTISSAMASK_INT = 0x000F_FFFF; // for the MSB only - enum ulong MANTISSAMASK_LONG = 0x000F_FFFF_FFFF_FFFF; - enum realFormat = RealFormat.ieeeDouble; - version (LittleEndian) - { - enum EXPPOS_SHORT = 3; - enum SIGNPOS_BYTE = 7; - } - else - { - enum EXPPOS_SHORT = 0; - enum SIGNPOS_BYTE = 0; - } - } - else static if (T.sizeof == 12) - { - // Intel extended real80 rounded to double - enum ushort EXPMASK = 0x7FFF; - enum ushort EXPSHIFT = 0; - enum ushort EXPBIAS = 0x3FFE; - enum realFormat = RealFormat.ieeeExtended53; - version (LittleEndian) - { - enum EXPPOS_SHORT = 4; - enum SIGNPOS_BYTE = 9; - } - else - { - enum EXPPOS_SHORT = 0; - enum SIGNPOS_BYTE = 0; - } - } - else - static assert(false, "No traits support for " ~ T.stringof); - } - else static if (T.mant_dig == 64) - { - // Intel extended real80 - enum ushort EXPMASK = 0x7FFF; - enum ushort EXPSHIFT = 0; - enum ushort EXPBIAS = 0x3FFE; - enum realFormat = RealFormat.ieeeExtended; - version (LittleEndian) - { - enum EXPPOS_SHORT = 4; - enum SIGNPOS_BYTE = 9; - } - else - { - enum EXPPOS_SHORT = 0; - enum SIGNPOS_BYTE = 0; - } - } - else static if (T.mant_dig == 113) - { - // Quadruple precision float - enum ushort EXPMASK = 0x7FFF; - enum ushort EXPSHIFT = 0; - enum ushort EXPBIAS = 0x3FFE; - enum realFormat = RealFormat.ieeeQuadruple; - version (LittleEndian) - { - enum EXPPOS_SHORT = 7; - enum SIGNPOS_BYTE = 15; - } - else - { - enum EXPPOS_SHORT = 0; - enum SIGNPOS_BYTE = 0; - } - } - else static if (T.mant_dig == 106) - { - // IBM Extended doubledouble - enum ushort EXPMASK = 0x7FF0; - enum ushort EXPSHIFT = 4; - enum realFormat = RealFormat.ibmExtended; - - // For IBM doubledouble the larger magnitude double comes first. - // It's really a double[2] and arrays don't index differently - // between little and big-endian targets. - enum DOUBLEPAIR_MSB = 0; - enum DOUBLEPAIR_LSB = 1; - - // The exponent/sign byte is for most significant part. - version (LittleEndian) - { - enum EXPPOS_SHORT = 3; - enum SIGNPOS_BYTE = 7; - } - else - { - enum EXPPOS_SHORT = 0; - enum SIGNPOS_BYTE = 0; - } - } - else - static assert(false, "No traits support for " ~ T.stringof); -} - -// These apply to all floating-point types -version (LittleEndian) -{ - enum MANTISSA_LSB = 0; - enum MANTISSA_MSB = 1; -} -else -{ - enum MANTISSA_LSB = 1; - enum MANTISSA_MSB = 0; -} diff --git a/libphobos/src/std/math/rounding.d b/libphobos/src/std/math/rounding.d index 7dbe89b..f6654fc 100644 --- a/libphobos/src/std/math/rounding.d +++ b/libphobos/src/std/math/rounding.d @@ -551,7 +551,7 @@ long lrint(real x) @trusted pure nothrow @nogc } else { - import std.math : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; + import std.math.traits : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; alias F = floatTraits!(real); static if (F.realFormat == RealFormat.ieeeDouble) @@ -896,7 +896,7 @@ long rndtol(float x) @safe pure nothrow @nogc { return rndtol(cast(real) x); } // Helper for floor/ceil T floorImpl(T)(const T x) @trusted pure nothrow @nogc { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; alias F = floatTraits!(T); // Take care not to trigger library calls from the compiler, diff --git a/libphobos/src/std/math/traits.d b/libphobos/src/std/math/traits.d index 2841bad..81ab1b7 100644 --- a/libphobos/src/std/math/traits.d +++ b/libphobos/src/std/math/traits.d @@ -137,7 +137,7 @@ if (isFloatingPoint!(X)) */ bool isFinite(X)(X x) @trusted pure nothrow @nogc { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; static if (__traits(isFloating, X)) if (__ctfe) @@ -202,7 +202,7 @@ bool isFinite(X)(X x) @trusted pure nothrow @nogc */ bool isNormal(X)(X x) @trusted pure nothrow @nogc { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; static if (__traits(isFloating, X)) if (__ctfe) @@ -264,7 +264,7 @@ bool isNormal(X)(X x) @trusted pure nothrow @nogc */ bool isSubnormal(X)(X x) @trusted pure nothrow @nogc { - import std.math : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; + import std.math.traits : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; static if (__traits(isFloating, X)) if (__ctfe) @@ -344,7 +344,7 @@ bool isSubnormal(X)(X x) @trusted pure nothrow @nogc bool isInfinity(X)(X x) @nogc @trusted pure nothrow if (isFloatingPoint!(X)) { - import std.math : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; + import std.math.traits : floatTraits, RealFormat, MANTISSA_MSB, MANTISSA_LSB; alias F = floatTraits!(X); static if (F.realFormat == RealFormat.ieeeSingle) @@ -466,7 +466,7 @@ if (isFloatingPoint!(X)) */ bool isIdentical(real x, real y) @trusted pure nothrow @nogc { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; // We're doing a bitwise comparison so the endianness is irrelevant. long* pxs = cast(long *)&x; @@ -510,7 +510,7 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc */ int signbit(X)(X x) @nogc @trusted pure nothrow { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; if (__ctfe) { @@ -594,7 +594,7 @@ Returns: R copysign(R, X)(R to, X from) @trusted pure nothrow @nogc if (isFloatingPoint!(R) && isFloatingPoint!(X)) { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; if (__ctfe) { @@ -851,3 +851,168 @@ if (isNumeric!X) }} } +// Underlying format exposed through floatTraits +enum RealFormat +{ + ieeeHalf, + ieeeSingle, + ieeeDouble, + ieeeExtended, // x87 80-bit real + ieeeExtended53, // x87 real rounded to precision of double. + ibmExtended, // IBM 128-bit extended + ieeeQuadruple, +} + +// Constants used for extracting the components of the representation. +// They supplement the built-in floating point properties. +template floatTraits(T) +{ + import std.traits : Unqual; + + // EXPMASK is a ushort mask to select the exponent portion (without sign) + // EXPSHIFT is the number of bits the exponent is left-shifted by in its ushort + // EXPBIAS is the exponent bias - 1 (exp == EXPBIAS yields ×2^-1). + // EXPPOS_SHORT is the index of the exponent when represented as a ushort array. + // SIGNPOS_BYTE is the index of the sign when represented as a ubyte array. + // RECIP_EPSILON is the value such that (smallest_subnormal) * RECIP_EPSILON == T.min_normal + enum Unqual!T RECIP_EPSILON = (1/T.epsilon); + static if (T.mant_dig == 24) + { + // Single precision float + enum ushort EXPMASK = 0x7F80; + enum ushort EXPSHIFT = 7; + enum ushort EXPBIAS = 0x3F00; + enum uint EXPMASK_INT = 0x7F80_0000; + enum uint MANTISSAMASK_INT = 0x007F_FFFF; + enum realFormat = RealFormat.ieeeSingle; + version (LittleEndian) + { + enum EXPPOS_SHORT = 1; + enum SIGNPOS_BYTE = 3; + } + else + { + enum EXPPOS_SHORT = 0; + enum SIGNPOS_BYTE = 0; + } + } + else static if (T.mant_dig == 53) + { + static if (T.sizeof == 8) + { + // Double precision float, or real == double + enum ushort EXPMASK = 0x7FF0; + enum ushort EXPSHIFT = 4; + enum ushort EXPBIAS = 0x3FE0; + enum uint EXPMASK_INT = 0x7FF0_0000; + enum uint MANTISSAMASK_INT = 0x000F_FFFF; // for the MSB only + enum ulong MANTISSAMASK_LONG = 0x000F_FFFF_FFFF_FFFF; + enum realFormat = RealFormat.ieeeDouble; + version (LittleEndian) + { + enum EXPPOS_SHORT = 3; + enum SIGNPOS_BYTE = 7; + } + else + { + enum EXPPOS_SHORT = 0; + enum SIGNPOS_BYTE = 0; + } + } + else static if (T.sizeof == 12) + { + // Intel extended real80 rounded to double + enum ushort EXPMASK = 0x7FFF; + enum ushort EXPSHIFT = 0; + enum ushort EXPBIAS = 0x3FFE; + enum realFormat = RealFormat.ieeeExtended53; + version (LittleEndian) + { + enum EXPPOS_SHORT = 4; + enum SIGNPOS_BYTE = 9; + } + else + { + enum EXPPOS_SHORT = 0; + enum SIGNPOS_BYTE = 0; + } + } + else + static assert(false, "No traits support for " ~ T.stringof); + } + else static if (T.mant_dig == 64) + { + // Intel extended real80 + enum ushort EXPMASK = 0x7FFF; + enum ushort EXPSHIFT = 0; + enum ushort EXPBIAS = 0x3FFE; + enum realFormat = RealFormat.ieeeExtended; + version (LittleEndian) + { + enum EXPPOS_SHORT = 4; + enum SIGNPOS_BYTE = 9; + } + else + { + enum EXPPOS_SHORT = 0; + enum SIGNPOS_BYTE = 0; + } + } + else static if (T.mant_dig == 113) + { + // Quadruple precision float + enum ushort EXPMASK = 0x7FFF; + enum ushort EXPSHIFT = 0; + enum ushort EXPBIAS = 0x3FFE; + enum realFormat = RealFormat.ieeeQuadruple; + version (LittleEndian) + { + enum EXPPOS_SHORT = 7; + enum SIGNPOS_BYTE = 15; + } + else + { + enum EXPPOS_SHORT = 0; + enum SIGNPOS_BYTE = 0; + } + } + else static if (T.mant_dig == 106) + { + // IBM Extended doubledouble + enum ushort EXPMASK = 0x7FF0; + enum ushort EXPSHIFT = 4; + enum realFormat = RealFormat.ibmExtended; + + // For IBM doubledouble the larger magnitude double comes first. + // It's really a double[2] and arrays don't index differently + // between little and big-endian targets. + enum DOUBLEPAIR_MSB = 0; + enum DOUBLEPAIR_LSB = 1; + + // The exponent/sign byte is for most significant part. + version (LittleEndian) + { + enum EXPPOS_SHORT = 3; + enum SIGNPOS_BYTE = 7; + } + else + { + enum EXPPOS_SHORT = 0; + enum SIGNPOS_BYTE = 0; + } + } + else + static assert(false, "No traits support for " ~ T.stringof); +} + +// These apply to all floating-point types +version (LittleEndian) +{ + enum MANTISSA_LSB = 0; + enum MANTISSA_MSB = 1; +} +else +{ + enum MANTISSA_LSB = 1; + enum MANTISSA_MSB = 0; +} diff --git a/libphobos/src/std/math/trigonometry.d b/libphobos/src/std/math/trigonometry.d index a3d04c6..4f5f5c5 100644 --- a/libphobos/src/std/math/trigonometry.d +++ b/libphobos/src/std/math/trigonometry.d @@ -307,7 +307,7 @@ Lret: private T tanImpl(T)(T x) @safe pure nothrow @nogc { - import std.math : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat; import std.math.constants : PI, PI_4; import std.math.rounding : floor; import std.math.algebraic : poly; @@ -675,8 +675,7 @@ float atan(float x) @safe pure nothrow @nogc { return __ctfe ? cast(float) atan( private T atanImpl(T)(T x) @safe pure nothrow @nogc { - import std.math : floatTraits, RealFormat; - import std.math.traits : copysign, isInfinity, signbit; + import std.math.traits : floatTraits, RealFormat, copysign, isInfinity, signbit; import std.math.constants : PI_2, PI_4; import std.math.algebraic : poly; diff --git a/libphobos/src/std/mmfile.d b/libphobos/src/std/mmfile.d index f8f8a90..b2cab31 100644 --- a/libphobos/src/std/mmfile.d +++ b/libphobos/src/std/mmfile.d @@ -2,10 +2,22 @@ /** * Read and write memory mapped files. + * + * Memory mapped files are a mechanism in operating systems that allows + * file access through virtual memory. After opening a file with `MmFile`, + * the contents can be read from or written to with standard slice / pointer operations. + * Changes to the memory are automatically reflected in the underlying file. + * + * Memory mapping can increase I/O performance of large files, compared to buffered + * read / write operations from `std.file` and `std.stdio`. However, I/O errors are + * not handled as safely: when for example the disk that the file is on gets removed, + * reading from it may result in a segfault. + * * Copyright: Copyright The D Language Foundation 2004 - 2009. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: $(HTTP digitalmars.com, Walter Bright), * Matthew Wilson + * References: $(LINK https://en.wikipedia.org/wiki/Memory-mapped_file) * Source: $(PHOBOSSRC std/mmfile.d) * * $(SCRIPT inhibitQuickIndex = 1;) @@ -612,23 +624,47 @@ private: { static assert(0); } +} + +/// Read an existing file +@system unittest +{ + import std.file; + std.file.write(deleteme, "hello"); // deleteme is a temporary filename + scope(exit) remove(deleteme); + + // Use a scope class so the file will be closed at the end of this function + scope mmfile = new MmFile(deleteme); + + assert(mmfile.length == "hello".length); + + // Access file contents with the slice operator + // This is typed as `void[]`, so cast to `char[]` or `ubyte[]` to use it + const data = cast(const(char)[]) mmfile[]; + + // At this point, the file content may not have been read yet. + // In that case, the following memory access will intentionally + // trigger a page fault, causing the kernel to load the file contents + assert(data[0 .. 5] == "hello"); +} + +/// Write a new file +@system unittest +{ + import std.file; + scope(exit) remove(deleteme); + + scope mmfile = new MmFile(deleteme, MmFile.Mode.readWriteNew, 5, null); + assert(mmfile.length == 5); + + auto data = cast(ubyte[]) mmfile[]; + + // This write to memory will be reflected in the file contents + data[] = '\n'; + + mmfile.flush(); - // Report error, where errno gives the error number - // void errNo() - // { - // version (Windows) - // { - // throw new FileException(filename, GetLastError()); - // } - // else version (linux) - // { - // throw new FileException(filename, errno); - // } - // else - // { - // static assert(0); - // } - // } + assert(std.file.read(deleteme) == "\n\n\n\n\n"); } @system unittest diff --git a/libphobos/src/std/regex/internal/backtracking.d b/libphobos/src/std/regex/internal/backtracking.d index ac73f70..a488e06 100644 --- a/libphobos/src/std/regex/internal/backtracking.d +++ b/libphobos/src/std/regex/internal/backtracking.d @@ -682,7 +682,7 @@ final: while (prevStack()) {} return re.ir[pc].data; default: - debug printBytecode(re.ir[0..$]); + debug(std_regex_debug) printBytecode(re.ir[0..$]); assert(0); L_backtrack: if (!popState()) diff --git a/libphobos/src/std/regex/internal/ir.d b/libphobos/src/std/regex/internal/ir.d index 069d75f..04b902f 100644 --- a/libphobos/src/std/regex/internal/ir.d +++ b/libphobos/src/std/regex/internal/ir.d @@ -403,7 +403,7 @@ struct Group(DataIndex) } //debugging tool, prints out instruction along with opcodes -@trusted string disassemble(in Bytecode[] irb, uint pc, in NamedGroup[] dict=[]) +debug(std_regex_parser) @trusted string disassemble(in Bytecode[] irb, uint pc, in NamedGroup[] dict=[]) { import std.array : appender; import std.format.write : formattedWrite; @@ -467,7 +467,7 @@ struct Group(DataIndex) } //disassemble the whole chunk -@trusted void printBytecode()(in Bytecode[] slice, in NamedGroup[] dict=[]) +debug(std_regex_parser) @trusted void printBytecode()(in Bytecode[] slice, in NamedGroup[] dict=[]) { import std.stdio : writeln; for (uint pc=0; pc<slice.length; pc += slice[pc].length) diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d index 67a1ede..13ae294 100644 --- a/libphobos/src/std/typecons.d +++ b/libphobos/src/std/typecons.d @@ -3256,11 +3256,19 @@ struct Nullable(T) * Params: * value = The value to initialize this `Nullable` with. */ - this(inout T value) inout - { - _value.payload = value; - _isNull = false; - } + static if (isCopyable!T) + this(inout T value) inout + { + _value.payload = value; + _isNull = false; + } + else + this(T value) inout + { + import std.algorithm.mutation : move; + _value.payload = move(value); + _isNull = false; + } static if (hasElaborateDestructor!T) { @@ -3273,6 +3281,9 @@ struct Nullable(T) } } + static if (!isCopyable!T) + @disable this(this); + else static if (__traits(hasPostblit, T)) { this(this) @@ -3511,22 +3522,18 @@ struct Nullable(T) * Params: * value = A value of type `T` to assign to this `Nullable`. */ - Nullable opAssign()(T value) + ref Nullable opAssign()(T value) return { import std.algorithm.mutation : moveEmplace, move; - // the lifetime of the value in copy shall be managed by - // this Nullable, so we must avoid calling its destructor. - auto copy = DontCallDestructorT(value); - if (_isNull) { // trusted since payload is known to be uninitialized. - () @trusted { moveEmplace(copy.payload, _value.payload); }(); + () @trusted { moveEmplace(value, _value.payload); }(); } else { - move(copy.payload, _value.payload); + move(value, _value.payload); } _isNull = false; return this; @@ -3604,12 +3611,14 @@ struct Nullable(T) alias back = front; /// ditto + static if (isCopyable!T) @property inout(typeof(this)) save() inout { return this; } /// ditto + static if (isCopyable!T) inout(typeof(this)) opIndex(size_t[2] dim) inout in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0]) { @@ -4088,16 +4097,12 @@ auto nullable(T)(T t) struct Test { - bool b; - - nothrow invariant { assert(b == true); } - SysTime _st; static bool destroyed; @disable this(); - this(bool b) { this.b = b; } + this(int _dummy) {} ~this() @safe { destroyed = true; } // mustn't call opAssign on Test.init in Nullable!Test, because the invariant @@ -4109,7 +4114,7 @@ auto nullable(T)(T t) { Nullable!Test nt; - nt = Test(true); + nt = Test(1); // destroy value Test.destroyed = false; @@ -10676,6 +10681,21 @@ unittest assert(s2.get().b == 3); } +// https://issues.dlang.org/show_bug.cgi?id=24318 +@system unittest +{ + static struct S + { + @disable this(this); + int i; + } + + Nullable!S s = S(1); + assert(s.get().i == 1); + s = S(2); + assert(s.get().i == 2); +} + /// The old version of $(LREF SafeRefCounted), before $(LREF borrow) existed. /// Old code may be relying on `@safe`ty of some of the member functions which /// cannot be safe in the new scheme, and |