Hi, This patch merges the D runtime library with upstream druntime d37ef985, adding support for FreeBSD/x86 53-bit precision reals, updating bindings for FreeBSD 12.x, and removing all support code and tests for the extern(Pascal) calling convention.
Bootstrapped and regression tested on x86_64-linux-gnu with -mx32/-m32, committed to mainline. Regards Iain. --- libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime d37ef985. * libdruntime/Makefile.am (DRUNTIME_DSOURCES_FREEBSD): Add core/sys/freebsd/config.d * libdruntime/Makefile.in: Regenerate. --- libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/Makefile.am | 20 ++-- libphobos/libdruntime/Makefile.in | 23 ++--- libphobos/libdruntime/core/demangle.d | 15 +-- libphobos/libdruntime/core/internal/convert.d | 11 ++- .../libdruntime/core/sys/freebsd/config.d | 24 +++++ .../libdruntime/core/sys/freebsd/sys/event.d | 35 +++++-- .../libdruntime/core/sys/freebsd/sys/mount.d | 14 ++- libphobos/libdruntime/core/sys/posix/dirent.d | 33 +++++-- .../libdruntime/core/sys/posix/sys/stat.d | 94 ++++++++++++++----- .../libdruntime/core/sys/posix/sys/types.d | 19 +++- libphobos/libdruntime/rt/critical_.d | 2 +- libphobos/libdruntime/rt/dmain2.d | 21 +---- 13 files changed, 214 insertions(+), 99 deletions(-) create mode 100644 libphobos/libdruntime/core/sys/freebsd/config.d diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 91154eebdc9..6b65a44e6d2 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -5e4492c45172110b035591f5961b9f9f5adf6f13 +d37ef985a97eb446371ab4b2315a52b87233fbf3 The first line of this file holds the git revision number of the last merge done from the dlang/druntime repository. diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am index 4136642beeb..4798bdf777d 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -237,16 +237,16 @@ DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \ core/sys/dragonflybsd/sys/mman.d core/sys/dragonflybsd/sys/socket.d \ core/sys/dragonflybsd/time.d -DRUNTIME_DSOURCES_FREEBSD = core/sys/freebsd/dlfcn.d \ - core/sys/freebsd/execinfo.d core/sys/freebsd/netinet/in_.d \ - core/sys/freebsd/pthread_np.d core/sys/freebsd/string.d \ - core/sys/freebsd/sys/_bitset.d core/sys/freebsd/sys/_cpuset.d \ - core/sys/freebsd/sys/cdefs.d core/sys/freebsd/sys/elf.d \ - core/sys/freebsd/sys/elf32.d core/sys/freebsd/sys/elf64.d \ - core/sys/freebsd/sys/elf_common.d core/sys/freebsd/sys/event.d \ - core/sys/freebsd/sys/link_elf.d core/sys/freebsd/sys/mman.d \ - core/sys/freebsd/sys/mount.d core/sys/freebsd/time.d \ - core/sys/freebsd/unistd.d +DRUNTIME_DSOURCES_FREEBSD = core/sys/freebsd/config.d \ + core/sys/freebsd/dlfcn.d core/sys/freebsd/execinfo.d \ + core/sys/freebsd/netinet/in_.d core/sys/freebsd/pthread_np.d \ + core/sys/freebsd/string.d core/sys/freebsd/sys/_bitset.d \ + core/sys/freebsd/sys/_cpuset.d core/sys/freebsd/sys/cdefs.d \ + core/sys/freebsd/sys/elf.d core/sys/freebsd/sys/elf32.d \ + core/sys/freebsd/sys/elf64.d core/sys/freebsd/sys/elf_common.d \ + core/sys/freebsd/sys/event.d core/sys/freebsd/sys/link_elf.d \ + core/sys/freebsd/sys/mman.d core/sys/freebsd/sys/mount.d \ + core/sys/freebsd/time.d core/sys/freebsd/unistd.d DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \ core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \ diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index d0bb3242c4f..0b895142a13 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -299,7 +299,7 @@ am__objects_7 = core/sys/dragonflybsd/dlfcn.lo \ am__objects_9 = core/sys/bionic/fcntl.lo core/sys/bionic/string.lo \ core/sys/bionic/unistd.lo @DRUNTIME_OS_ANDROID_TRUE@am__objects_10 = $(am__objects_9) -am__objects_11 = core/sys/freebsd/dlfcn.lo \ +am__objects_11 = core/sys/freebsd/config.lo core/sys/freebsd/dlfcn.lo \ core/sys/freebsd/execinfo.lo core/sys/freebsd/netinet/in_.lo \ core/sys/freebsd/pthread_np.lo core/sys/freebsd/string.lo \ core/sys/freebsd/sys/_bitset.lo \ @@ -861,16 +861,16 @@ DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \ core/sys/dragonflybsd/sys/mman.d core/sys/dragonflybsd/sys/socket.d \ core/sys/dragonflybsd/time.d -DRUNTIME_DSOURCES_FREEBSD = core/sys/freebsd/dlfcn.d \ - core/sys/freebsd/execinfo.d core/sys/freebsd/netinet/in_.d \ - core/sys/freebsd/pthread_np.d core/sys/freebsd/string.d \ - core/sys/freebsd/sys/_bitset.d core/sys/freebsd/sys/_cpuset.d \ - core/sys/freebsd/sys/cdefs.d core/sys/freebsd/sys/elf.d \ - core/sys/freebsd/sys/elf32.d core/sys/freebsd/sys/elf64.d \ - core/sys/freebsd/sys/elf_common.d core/sys/freebsd/sys/event.d \ - core/sys/freebsd/sys/link_elf.d core/sys/freebsd/sys/mman.d \ - core/sys/freebsd/sys/mount.d core/sys/freebsd/time.d \ - core/sys/freebsd/unistd.d +DRUNTIME_DSOURCES_FREEBSD = core/sys/freebsd/config.d \ + core/sys/freebsd/dlfcn.d core/sys/freebsd/execinfo.d \ + core/sys/freebsd/netinet/in_.d core/sys/freebsd/pthread_np.d \ + core/sys/freebsd/string.d core/sys/freebsd/sys/_bitset.d \ + core/sys/freebsd/sys/_cpuset.d core/sys/freebsd/sys/cdefs.d \ + core/sys/freebsd/sys/elf.d core/sys/freebsd/sys/elf32.d \ + core/sys/freebsd/sys/elf64.d core/sys/freebsd/sys/elf_common.d \ + core/sys/freebsd/sys/event.d core/sys/freebsd/sys/link_elf.d \ + core/sys/freebsd/sys/mman.d core/sys/freebsd/sys/mount.d \ + core/sys/freebsd/time.d core/sys/freebsd/unistd.d DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \ core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \ @@ -1435,6 +1435,7 @@ core/sys/bionic/unistd.lo: core/sys/bionic/$(am__dirstamp) core/sys/freebsd/$(am__dirstamp): @$(MKDIR_P) core/sys/freebsd @: > core/sys/freebsd/$(am__dirstamp) +core/sys/freebsd/config.lo: core/sys/freebsd/$(am__dirstamp) core/sys/freebsd/dlfcn.lo: core/sys/freebsd/$(am__dirstamp) core/sys/freebsd/execinfo.lo: core/sys/freebsd/$(am__dirstamp) core/sys/freebsd/netinet/$(am__dirstamp): diff --git a/libphobos/libdruntime/core/demangle.d b/libphobos/libdruntime/core/demangle.d index 86cfcad4709..4458b70122b 100644 --- a/libphobos/libdruntime/core/demangle.d +++ b/libphobos/libdruntime/core/demangle.d @@ -1009,7 +1009,6 @@ pure @safe: F // D U // C W // Windows - V // Pascal R // C++ FuncAttrs: @@ -1089,10 +1088,6 @@ pure @safe: popFront(); put( "extern (Windows) " ); break; - case 'V': // Pascal - popFront(); - put( "extern (Pascal) " ); - break; case 'R': // C++ popFront(); put( "extern (C++) " ); @@ -2380,15 +2375,14 @@ private template isExternCPP(FT) if (is(FT == function)) private template hasPlainMangling(FT) if (is(FT == function)) { enum lnk = __traits(getLinkage, FT); - // C || Pascal || Windows - enum hasPlainMangling = lnk == "C" || lnk == "Pascal" || lnk == "Windows"; + // C || Windows + enum hasPlainMangling = lnk == "C" || lnk == "Windows"; } @safe pure nothrow unittest { static extern(D) void fooD(); static extern(C) void fooC(); - static extern(Pascal) void fooP(); static extern(Windows) void fooW(); static extern(C++) void fooCPP(); @@ -2399,13 +2393,11 @@ private template hasPlainMangling(FT) if (is(FT == function)) } static assert(check!(typeof(fooD))(true, false, false)); static assert(check!(typeof(fooC))(false, false, true)); - static assert(check!(typeof(fooP))(false, false, true)); static assert(check!(typeof(fooW))(false, false, true)); static assert(check!(typeof(fooCPP))(false, true, false)); static assert(__traits(compiles, mangleFunc!(typeof(&fooD))(""))); static assert(__traits(compiles, mangleFunc!(typeof(&fooC))(""))); - static assert(__traits(compiles, mangleFunc!(typeof(&fooP))(""))); static assert(__traits(compiles, mangleFunc!(typeof(&fooW))(""))); static assert(!__traits(compiles, mangleFunc!(typeof(&fooCPP))(""))); } @@ -2505,7 +2497,8 @@ version (unittest) "pure @safe void testexpansion.s!(testexpansion.s!(int).s(int).Result).s(testexpansion.s!(int).s(int).Result).Result.foo()"], ["_D13testexpansion__T1sTSQw__TQjTiZQoFiZ6ResultZQBbFQBcZQq3fooMFNaNfZv", "pure @safe void testexpansion.s!(testexpansion.s!(int).s(int).Result).s(testexpansion.s!(int).s(int).Result).Result.foo()"], - // ambiguity on 'V', template value argument or pascal function + // formerly ambiguous on 'V', template value argument or pascal function + // pascal functions have now been removed (in v2.095.0) ["_D3std4conv__T7enumRepTyAaTEQBa12experimental9allocator15building_blocks15stats_collector7OptionsVQCti64ZQDnyQDh", "immutable(char[]) std.conv.enumRep!(immutable(char[]), std.experimental.allocator.building_blocks.stats_collector.Options, 64).enumRep"], // symbol back reference to location with symbol back reference diff --git a/libphobos/libdruntime/core/internal/convert.d b/libphobos/libdruntime/core/internal/convert.d index 8010ad773b8..d92204902fa 100644 --- a/libphobos/libdruntime/core/internal/convert.d +++ b/libphobos/libdruntime/core/internal/convert.d @@ -39,7 +39,7 @@ const(ubyte)[] toUbyte(T)(const ref T val) if (is(Unqual!T == float) || is(Unqua { if (__ctfe) { - static if (T.mant_dig == float.mant_dig || T.mant_dig == double.mant_dig) + static if (floatFormat!T == FloatFormat.Float || floatFormat!T == FloatFormat.Double) { static if (is(T : ireal)) // https://issues.dlang.org/show_bug.cgi?id=19932 const f = val.im; @@ -628,7 +628,14 @@ template floatFormat(T) if (is(T:real) || is(T:ireal)) static if (T.mant_dig == 24) enum floatFormat = FloatFormat.Float; else static if (T.mant_dig == 53) - enum floatFormat = FloatFormat.Double; + { + // Double precision, or real == double + static if (T.sizeof == double.sizeof) + enum floatFormat = FloatFormat.Double; + // 80-bit real with rounding precision set to 53 bits. + else static if (T.sizeof == real.sizeof) + enum floatFormat = FloatFormat.Real80; + } else static if (T.mant_dig == 64) enum floatFormat = FloatFormat.Real80; else static if (T.mant_dig == 106) diff --git a/libphobos/libdruntime/core/sys/freebsd/config.d b/libphobos/libdruntime/core/sys/freebsd/config.d new file mode 100644 index 00000000000..4eda066b293 --- /dev/null +++ b/libphobos/libdruntime/core/sys/freebsd/config.d @@ -0,0 +1,24 @@ +/** + * D header file for FreeBSD + * + * Authors: Iain Buclaw + */ +module core.sys.freebsd.config; + +version (FreeBSD): + +public import core.sys.posix.config; + +// https://svnweb.freebsd.org/base/head/sys/sys/param.h?view=markup +// __FreeBSD_version numbers are documented in the Porter's Handbook. +// NOTE: When adding newer versions of FreeBSD, verify all current versioned +// bindings are still compatible with the release. + version (FreeBSD_12) enum __FreeBSD_version = 1202000; +else version (FreeBSD_11) enum __FreeBSD_version = 1104000; +else version (FreeBSD_10) enum __FreeBSD_version = 1004000; +else version (FreeBSD_9) enum __FreeBSD_version = 903000; +else version (FreeBSD_8) enum __FreeBSD_version = 804000; +else static assert(false, "Unsupported version of FreeBSD"); + +// First version of FreeBSD to support 64-bit stat buffer. +enum INO64_FIRST = 1200031; diff --git a/libphobos/libdruntime/core/sys/freebsd/sys/event.d b/libphobos/libdruntime/core/sys/freebsd/sys/event.d index 2ae10b3db27..8ac7c3b4758 100644 --- a/libphobos/libdruntime/core/sys/freebsd/sys/event.d +++ b/libphobos/libdruntime/core/sys/freebsd/sys/event.d @@ -18,6 +18,7 @@ extern (C): nothrow: @nogc: +import core.sys.freebsd.config; import core.stdc.stdint; // intptr_t, uintptr_t import core.sys.posix.time; // timespec @@ -38,19 +39,35 @@ enum EVFILT_SYSCOUNT = 11, } -extern(D) void EV_SET(kevent_t* kevp, typeof(kevent_t.tupleof) args) +static if (__FreeBSD_version >= 1200000) { - *kevp = kevent_t(args); + struct kevent_t + { + uintptr_t ident; + short filter; + ushort flags; + uint fflags; + long data; + void* udata; + ulong[4] ext; + } +} +else +{ + struct kevent_t + { + uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + ushort flags; + uint fflags; + intptr_t data; + void *udata; /* opaque user data identifier */ + } } -struct kevent_t +extern(D) void EV_SET(kevent_t* kevp, typeof(kevent_t.tupleof) args) { - uintptr_t ident; /* identifier for this event */ - short filter; /* filter for event */ - ushort flags; - uint fflags; - intptr_t data; - void *udata; /* opaque user data identifier */ + *kevp = kevent_t(args); } enum diff --git a/libphobos/libdruntime/core/sys/freebsd/sys/mount.d b/libphobos/libdruntime/core/sys/freebsd/sys/mount.d index 66c69a4fd81..e45c4600661 100644 --- a/libphobos/libdruntime/core/sys/freebsd/sys/mount.d +++ b/libphobos/libdruntime/core/sys/freebsd/sys/mount.d @@ -11,6 +11,7 @@ module core.sys.freebsd.sys.mount; version (FreeBSD): +import core.sys.freebsd.config; import core.stdc.config : c_long; import core.sys.posix.sys.stat : stat_t; import core.sys.posix.sys.types : uid_t; @@ -32,8 +33,17 @@ struct fid } enum MFSNAMELEN = 16; -enum MNAMELEN = 88; -enum STATFS_VERSION = 0x20030518; + +static if (__FreeBSD_version >= 1200000) +{ + enum MNAMELEN = 1024; + enum STATFS_VERSION = 0x20140518; +} +else +{ + enum MNAMELEN = 88; + enum STATFS_VERSION = 0x20030518; +} struct statfs_t { diff --git a/libphobos/libdruntime/core/sys/posix/dirent.d b/libphobos/libdruntime/core/sys/posix/dirent.d index cea22d21025..b12d6b157d5 100644 --- a/libphobos/libdruntime/core/sys/posix/dirent.d +++ b/libphobos/libdruntime/core/sys/posix/dirent.d @@ -135,6 +135,8 @@ else version (Darwin) } else version (FreeBSD) { + import core.sys.freebsd.config; + // https://github.com/freebsd/freebsd/blob/master/sys/sys/dirent.h enum { @@ -149,14 +151,31 @@ else version (FreeBSD) DT_WHT = 14 } - align(4) - struct dirent + static if (__FreeBSD_version >= 1200000) { - uint d_fileno; - ushort d_reclen; - ubyte d_type; - ubyte d_namlen; - char[256] d_name = 0; + struct dirent + { + ino_t d_fileno; + off_t d_off; + ushort d_reclen; + ubyte d_type; + ubyte d_pad0; + ushort d_namlen; + ushort d_pad1; + char[256] d_name = 0; + } + } + else + { + align(4) + struct dirent + { + uint d_fileno; + ushort d_reclen; + ubyte d_type; + ubyte d_namlen; + char[256] d_name = 0; + } } alias void* DIR; diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d index b154e1489a6..35b1f1cffee 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/stat.d +++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d @@ -1060,36 +1060,82 @@ else version (Darwin) } else version (FreeBSD) { - // https://github.com/freebsd/freebsd/blob/master/sys/sys/stat.h + import core.sys.freebsd.config; - struct stat_t + // https://github.com/freebsd/freebsd/blob/master/sys/sys/stat.h + static if (__FreeBSD_version >= INO64_FIRST) { - dev_t st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - dev_t st_rdev; + struct stat_t + { + dev_t st_dev; + ino_t st_ino; + nlink_t st_nlink; + mode_t st_mode; + short st_padding0; + uid_t st_uid; + gid_t st_gid; + int st_padding1; + dev_t st_rdev; - time_t st_atime; - c_long __st_atimensec; - time_t st_mtime; - c_long __st_mtimensec; - time_t st_ctime; - c_long __st_ctimensec; + version (X86) int st_atim_ext; + timespec st_atim; - off_t st_size; - blkcnt_t st_blocks; - blksize_t st_blksize; - fflags_t st_flags; - uint st_gen; - int st_lspare; + version (X86) int st_mtim_ext; + timespec st_mtim; + + version (X86) int st_ctim_ext; + timespec st_ctim; - time_t st_birthtime; - c_long st_birthtimensec; + version (X86) int st_btim_ext; + timespec st_birthtim; - ubyte[16 - timespec.sizeof] padding; + off_t st_size; + blkcnt_t st_blocks; + blksize_t st_blksize; + fflags_t st_flags; + ulong st_gen; + ulong[10] st_spare; + + extern(D) @safe @property inout pure nothrow + { + ref inout(time_t) st_atime() return { return st_atim.tv_sec; } + ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; } + ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; } + ref inout(time_t) st_birthtime() return { return st_birthtim.tv_sec; } + } + } + } + else + { + struct stat_t + { + uint st_dev; + uint st_ino; + mode_t st_mode; + ushort st_nlink; + uid_t st_uid; + gid_t st_gid; + uint st_rdev; + timespec st_atim; + timespec st_mtim; + timespec st_ctim; + off_t st_size; + blkcnt_t st_blocks; + blksize_t st_blksize; + fflags_t st_flags; + uint st_gen; + int st_lspare; + timespec st_birthtim; + ubyte[16 - timespec.sizeof] padding; + + extern(D) @safe @property inout pure nothrow + { + ref inout(time_t) st_atime() return { return st_atim.tv_sec; } + ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; } + ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; } + ref inout(time_t) st_birthtime() return { return st_birthtim.tv_sec; } + } + } } enum S_IRUSR = 0x100; // octal 0000400 diff --git a/libphobos/libdruntime/core/sys/posix/sys/types.d b/libphobos/libdruntime/core/sys/posix/sys/types.d index 451c8b4fccc..2d8ef92720e 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/types.d +++ b/libphobos/libdruntime/core/sys/posix/sys/types.d @@ -168,14 +168,27 @@ else version (Darwin) } else version (FreeBSD) { + import core.sys.freebsd.config; + // https://github.com/freebsd/freebsd/blob/master/sys/sys/_types.h alias long blkcnt_t; alias uint blksize_t; - alias uint dev_t; + + static if (__FreeBSD_version >= 1200000) + { + alias ulong dev_t; + alias ulong ino_t; + alias ulong nlink_t; + } + else + { + alias uint dev_t; + alias uint ino_t; + alias ushort nlink_t; + } + alias uint gid_t; - alias uint ino_t; alias ushort mode_t; - alias ushort nlink_t; alias long off_t; alias int pid_t; //size_t (defined in core.stdc.stddef) diff --git a/libphobos/libdruntime/rt/critical_.d b/libphobos/libdruntime/rt/critical_.d index 40030ad35b8..15c460aac6f 100644 --- a/libphobos/libdruntime/rt/critical_.d +++ b/libphobos/libdruntime/rt/critical_.d @@ -43,7 +43,7 @@ extern (C) void _d_criticalenter2(D_CRITICAL_SECTION** pcs) lockMutex(cast(Mutex*)&gcs.mtx); if (atomicLoad!(MemoryOrder.raw)(*cast(shared) pcs) is null) { - auto cs = new shared D_CRITICAL_SECTION; + auto cs = new shared(D_CRITICAL_SECTION); initMutex(cast(Mutex*)&cs.mtx); atomicStore!(MemoryOrder.rel)(*cast(shared) pcs, cs); } diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d index 32635c460b3..3d5ba299863 100644 --- a/libphobos/libdruntime/rt/dmain2.d +++ b/libphobos/libdruntime/rt/dmain2.d @@ -9,9 +9,6 @@ * Source: $(DRUNTIMESRC src/rt/_dmain2.d) */ -/* NOTE: This file has been patched from the original DMD distribution to - * work with the GDC compiler. - */ module rt.dmain2; private @@ -340,15 +337,8 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) version (CRuntime_Microsoft) { // enable full precision for reals - version (GNU) + version (D_InlineAsm_X86_64) { - size_t fpu_cw; - asm { "fstcw %0" : "=m" (fpu_cw); } - fpu_cw |= 0b11_00_111111; // 11: use 64 bit extended-precision - // 111111: mask all FP exceptions - asm { "fldcw %0" : "=m" (fpu_cw); } - } - else version (Win64) asm { push RAX; @@ -358,7 +348,8 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) fldcw word ptr [RSP]; pop RAX; } - else version (Win32) + } + else version (D_InlineAsm_X86) { asm { @@ -455,12 +446,6 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc) { if (IsDebuggerPresent()) trapExceptions = false; - version (GNU) - { - /* IsDebuggerPresent doesn't detect GDC. Would be nice to have - some way of detecting valid console output */ - trapExceptions = true; - } } void tryExec(scope void delegate() dg) -- 2.27.0