diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
commit | e252b51ccde010cbd2a146485d8045103cd99533 (patch) | |
tree | e060f101cdc32bf5e520de8e5275db9d4236b74c /libphobos | |
parent | f10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff) | |
parent | 104c05c5284b7822d770ee51a7d91946c7e56d50 (diff) | |
download | gcc-e252b51ccde010cbd2a146485d8045103cd99533.zip gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2 |
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'libphobos')
98 files changed, 5653 insertions, 3076 deletions
diff --git a/libphobos/ChangeLog b/libphobos/ChangeLog index 235af5b..fa1aef7 100644 --- a/libphobos/ChangeLog +++ b/libphobos/ChangeLog @@ -1,3 +1,223 @@ +2021-09-01 Iain Buclaw <ibuclaw@gdcproject.org> + + * m4/druntime/os.m4: Update comment for DRUNTIME_OS_SOURCES. + +2021-09-01 Iain Buclaw <ibuclaw@gdcproject.org> + + * src/Makefile.am: Don't add zlib when ENABLE_LIBDRUNTIME_ONLY. + * src/Makefile.in: Regenerate. + +2021-08-30 Iain Buclaw <ibuclaw@gdcproject.org> + + * configure: Regenerate. + * m4/autoconf.m4 (AC_LANG_PROGRAM): Declare module name 'object'. + * m4/gcc_support.m4 (WITH_LOCAL_DRUNTIME): Compile tests with + -fno-druntime. + +2021-06-11 Iain Buclaw <ibuclaw@gdcproject.org> + + PR d/100999 + * src/MERGE: Merge upstream phobos 55bb17543. + +2021-05-14 Bernd Edlinger <bernd.edlinger@hotmail.de> + + * src/std/process.d (unittest): Remove tmpname on exit. + * src/MERGE: Merge upstream phobos 63f4caa90. + +2021-05-13 Iain Buclaw <ibuclaw@gdcproject.org> + + * libdruntime/MERGE: Merge upstream druntime 98c6ff0c. + +2021-05-10 Iain Buclaw <ibuclaw@gdcproject.org> + + * src/MERGE: Merge upstream phobos 32cfe9b61. + +2021-04-21 Iain Buclaw <ibuclaw@gdcproject.org> + + * libdruntime/core/thread/osthread.d (callWithStackShell): Statically + generate PPC and PPC64 asm implementations, and conditionally remove + PPC register names on non-Darwin targets. + +2021-04-20 Iain Buclaw <ibuclaw@gdcproject.org> + + PR d/98584 + * libdruntime/gcc/deh.d (scanLSDA): Update calls to read_uleb128 and + read_encoded_value. + (actionTableLookup): Update calls to read_sleb128 and + read_encoded_value_with_base. + * libdruntime/gcc/unwind/pe.d (read_uleb128): Update signature. + (read_sleb128): Update signature. + (read_unaligned): New function. + (read_encoded_value_with_base): Update signature. Call read_unaligned + instead of unsafe pointer dereferencing. + (read_encoded_value): Update signature. + +2021-04-19 Iain Buclaw <ibuclaw@gdcproject.org> + + PR d/98494 + * libdruntime/MERGE: Merge upstream druntime 89f870b7. + * src/MERGE: Merge upstream phobos e6907ff3e. + +2021-04-19 Iain Buclaw <ibuclaw@gdcproject.org> + + PR d/98058 + * configure: Regenerate. + * libdruntime/Makefile.am (DRUNTIME_DSOURCES_DARWIN): Add + core/sys/darwin/config.d + * libdruntime/Makefile.in: Regenerate. + * libdruntime/config/powerpc/switchcontext.S: Implement + fiber_switchContext for __MACH__. + * libdruntime/config/x86/switchcontext.S: Likewise. + * libdruntime/core/sys/darwin/config.d: New file. + * libdruntime/core/thread/fiber.d (Fiber.getThis): Mark noinline. + (UnsafeFiberMigration): Define for OSX/X86 and OSX/X86_64. + * libdruntime/core/thread/osthread.d (callWithStackShell): Add inline + assembler implementation for X86, X86_64, PPC, and PPC64. + * libdruntime/core/thread/threadbase.d (ThreadBase.getThis): Mark + noinline. + * libdruntime/gcc/deh.d (FuncTable): Remove definition. + * m4/druntime/os.m4 (DRUNTIME_OS_MINFO_BRACKETING): Check for right + bracket symbol on darwin* targets. + * testsuite/libphobos.thread/fiber_guard_page.d: Update test to + support ucontext-based Fibers. + +2021-04-19 Iain Buclaw <ibuclaw@gdcproject.org> + + PR d/99794 + * libdruntime/Makefile.am (DRUNTIME_SOURCES_CONFIGURED): Add + config/mingw/msvc.c on DRUNTIME_OS_MINGW. + * libdruntime/Makefile.in: Regenerate. + * libdruntime/config/mingw/msvc.c: New file. + * libdruntime/config/mingw/switchcontext.S (fiber_switchContext): Fix + function definition. + * libdruntime/gcc/deh.d (__gdc_personality_seh0): Fix call to + _GCC_specific_handler. + * libdruntime/gcc/gthread.d (__gthread_once_t): Fix definition. + * libdruntime/gcc/unwind/generic.d (_GCC_specific_handler): Fix + declaration. + * libdruntime/rt/dmain2.d (rt_loadLibrary): Remove function. + (rt_loadLibraryW): Remove function. + (initLibrary): Remove function. + (rt_unloadLibrary): Remove function. + +2021-04-19 Iain Buclaw <ibuclaw@gdcproject.org> + + PR d/99691 + * configure: Regenerate. + * libdruntime/config/common/threadasm.S: Add __OpenBSD__. + * libdruntime/gcc/backtrace.d: Import core.sys.openbsd.dlfcn on + OpenBSD platforms. + * libdruntime/gcc/sections/elf.d (SharedElf): Define on OpenBSD. + (linkMapForHandle): Implement for OpenBSD. + (exeLinkMap): Remove. + (getDependencies): Adjust dlpi_addr on OpenBSD. + (handleForName): Implement for OpenBSD. + (IterateManually): Define on OpenBSD. + * libdruntime/gcc/sections/package.d (SectionsElf): Define on OpenBSD. + * m4/druntime/libraries.m4 (DRUNTIME_LIBRARIES_ATOMIC): Test for + enable_libatomic. + (DRUNTIME_LIBRARIES_BACKTRACE): Test for enable_libbacktrace. + +2021-04-10 Iain Buclaw <ibuclaw@gdcproject.org> + + * Makefile.in: Regenerate. + * configure: Regenerate. + * configure.ac: Call DRUNTIME_SECTION_FLAGS. + * libdruntime/Makefile.am: Add SECTION_FLAGS to AM_DFLAGS. + * libdruntime/Makefile.in: Regenerate. + * m4/druntime.m4 (DRUNTIME_SECTION_FLAGS): New macro. + * src/Makefile.am: Add SECTION_FLAGS to AM_DFLAGS. + * src/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2021-04-10 Iain Buclaw <ibuclaw@gdcproject.org> + + * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Removed + gcc/sections/android.d, elf_shared.d, osx.d, win32.d, and win64.d. + Added gcc/sections/common.d, elf.d macho.d, and pecoff.d. + * libdruntime/Makefile.in: Regenerate. + * libdruntime/core/thread/osthread.d: Update externDFunc FQDN names to + use platform independant section function names. + * libdruntime/gcc/sections/elf_shared.d: Renamed to... + * libdruntime/gcc/sections/elf.d: ...this. Mangle functions for + core.thread interface as if they come from the gcc.sections module. + * libdruntime/gcc/sections/package.d: Update public imports, declare + functions for core.thread interface. + * libdruntime/gcc/sections/android.d: Removed. + * libdruntime/gcc/sections/osx.d: Removed. + * libdruntime/gcc/sections/win32.d: Removed. + * libdruntime/gcc/sections/win64.d: Removed. + * libdruntime/gcc/sections/common.d: New file. + * libdruntime/gcc/sections/macho.d: New file. + * libdruntime/gcc/sections/pecoff.d: New file. + +2021-04-10 Iain Buclaw <ibuclaw@gdcproject.org> + + * testsuite/libphobos.druntime/druntime.exp: Compile all tests with + -static-libphobos. + * testsuite/libphobos.phobos/phobos.exp: Likewise. + +2021-04-10 Iain Buclaw <ibuclaw@gdcproject.org> + + * testsuite/libphobos.druntime/druntime.exp: Remove + is-effective-target static. + * testsuite/libphobos.phobos/phobos.exp: Likewise. + +2021-04-10 Iain Buclaw <ibuclaw@gdcproject.org> + + PR d/99812 + * testsuite/libphobos.druntime_shared/druntime_shared.exp: Re-add + -fno-moduleinfo flag to dg-runtest. + * testsuite/libphobos.phobos_shared/phobos_shared.exp: Likewise. + +2021-04-08 Iain Buclaw <ibuclaw@gdcproject.org> + + * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add + gcc/attributes.d. + * libdruntime/Makefile.in: Regenerate. + * libdruntime/gcc/attribute.d: Deprecate module, publicly import + gcc.attributes. + * libdruntime/gcc/deh.d: Update imports. + * libdruntime/gcc/attributes.d: New file. + +2021-04-06 Iain Buclaw <ibuclaw@gdcproject.org> + + * libdruntime/MERGE: Merge upstream druntime 1134b710. + +2021-04-03 Iain Buclaw <ibuclaw@gdcproject.org> + + * libdruntime/MERGE: Merge upstream druntime 483bc129. + * libdruntime/Makefile.am (DRUNTIME_DSOURCES_DARWIN): Add + core/sys/darwin/fcntl.d. + (DRUNTIME_DSOURCES_OPENBSD): Add core/sys/openbsd/unistd.d. + (DRUNTIME_DSOURCES_WINDOWS): Add core/sys/windows/stdc/malloc.d. + * libdruntime/Makefile.in: Regenerate. + * src/MERGE: Merge upstream phobos f89dc217a. + * src/Makefile.am (PHOBOS_DSOURCES): Add std/regex/internal/tests2.d. + * src/Makefile.in: Regenerate. + * testsuite/libphobos.exceptions/chain.d: Fix format arguments. + * testsuite/libphobos.exceptions/line_trace.d: Likewise. + +2021-03-26 Iain Buclaw <ibuclaw@gdcproject.org> + + * Makefile.in: Regenerate. + * configure: Regenerate. + * configure.ac: Substitute enable_shared, enable_static, and + phobos_lt_pic_flag. + * libdruntime/Makefile.am (AM_DFLAGS): Replace + phobos_compiler_pic_flag with phobos_lt_pic_flags, and + phobos_compiler_shared_flag. + * libdruntime/Makefile.in: Regenerate. + * src/Makefile.am (AM_DFLAGS): Replace phobos_compiler_pic_flag + with phobos_lt_pic_flag, and phobos_compiler_shared_flag. + * src/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + * testsuite/libphobos.druntime_shared/druntime_shared.exp: Remove + -fversion=Shared and -fno-moduleinfo from default extra test flags. + * testsuite/libphobos.phobos_shared/phobos_shared.exp: Likewise. + * testsuite/testsuite_flags.in: Add phobos_compiler_shared_flag to + --gdcflags. + 2021-02-04 Iain Buclaw <ibuclaw@gdcproject.org> PR d/98910 diff --git a/libphobos/Makefile.in b/libphobos/Makefile.in index d422484..a8f7e16 100644 --- a/libphobos/Makefile.in +++ b/libphobos/Makefile.in @@ -271,6 +271,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +SECTION_FLAGS = @SECTION_FLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -298,6 +299,8 @@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ +enable_shared = @enable_shared@ +enable_static = @enable_static@ exec_prefix = @exec_prefix@ gcc_version = @gcc_version@ gdc_include_dir = @gdc_include_dir@ @@ -327,6 +330,7 @@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ phobos_compiler_pic_flag = @phobos_compiler_pic_flag@ phobos_compiler_shared_flag = @phobos_compiler_shared_flag@ +phobos_lt_pic_flag = @phobos_lt_pic_flag@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ diff --git a/libphobos/configure b/libphobos/configure index c940a40..14298a0 100755 --- a/libphobos/configure +++ b/libphobos/configure @@ -700,11 +700,15 @@ DRUNTIME_CPU_ARM_FALSE DRUNTIME_CPU_ARM_TRUE DRUNTIME_CPU_AARCH64_FALSE DRUNTIME_CPU_AARCH64_TRUE +SECTION_FLAGS libphobos_srcdir libphobos_builddir get_gcc_base_ver phobos_compiler_shared_flag phobos_compiler_pic_flag +phobos_lt_pic_flag +enable_static +enable_shared OTOOL64 OTOOL LIPO @@ -5378,7 +5382,7 @@ fi gdc_save_DFLAGS=$GDCFLAGS - GDCFLAGS="-fno-moduleinfo -nostdinc -I $phobos_cv_abs_srcdir/libdruntime $GDCFLAGS" + GDCFLAGS="-fno-druntime -nostdinc -I $phobos_cv_abs_srcdir/libdruntime $GDCFLAGS" ac_ext=d ac_compile='$GDC -c $GDCFLAGS conftest.$ac_ext >&5' @@ -5388,7 +5392,7 @@ ac_compiler_gnu=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking If $GDC can compile D sources" >&5 $as_echo_n "checking If $GDC can compile D sources... " >&6; } cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; extern(C) int main() { @@ -11746,7 +11750,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11749 "configure" +#line 11753 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11852,7 +11856,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11855 "configure" +#line 11859 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12093,7 +12097,7 @@ CC="$lt_save_CC" gdc_save_DFLAGS=$GDCFLAGS - GDCFLAGS="-fno-moduleinfo -nostdinc -I $phobos_cv_abs_srcdir/libdruntime $GDCFLAGS" + GDCFLAGS="-fno-druntime -nostdinc -I $phobos_cv_abs_srcdir/libdruntime $GDCFLAGS" # Source file extension for D test sources. @@ -13997,8 +14001,14 @@ CFLAGS=$lt_save_CFLAGS GDCFLAGS=$gdc_save_DFLAGS + + # libtool variables for Phobos shared and position-independent compiles. # +# Use phobos_lt_pic_flag to designate the automake variable +# used to encapsulate the default libtool approach to creating objects +# with position-independent code. Default: -prefer-pic. +# # Use phobos_compiler_shared_flag to designate the compile-time flags for # creating shared objects. Default: -fversion=Shared. # @@ -14010,26 +14020,23 @@ CFLAGS=$lt_save_CFLAGS # libtool, and so we make it here. How it is handled is that in shared # compilations the `lt_prog_compiler_pic_D' variable is used to instead # ensure that conditional compilation of shared runtime code is compiled in. -# The original PIC flags are then used in the compilation of every object. -# -# Why are objects destined for libgphobos.a compiled with -fPIC? -# Because -fPIC is not harmful to use for objects destined for static -# libraries. In addition, using -fPIC will allow the use of static -# libgphobos.a in the creation of other D shared libraries. if test "$enable_shared" = yes; then + phobos_lt_pic_flag="-prefer-pic" phobos_compiler_pic_flag="$lt_prog_compiler_pic_D" phobos_compiler_shared_flag="-fversion=Shared" else + phobos_lt_pic_flag= phobos_compiler_pic_flag= phobos_compiler_shared_flag= fi + # Override the libtool's pic_flag and pic_mode. # Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT. # NB: this impacts --with-pic and --without-pic. -lt_prog_compiler_pic_D="$phobos_compiler_shared_flag" +lt_prog_compiler_pic_D="$phobos_compiler_pic_flag $phobos_compiler_shared_flag" pic_mode='default' # Determine what GCC version number to use in filesystem paths. @@ -14079,6 +14086,48 @@ fi fi + + + gdc_save_DFLAGS=$GDCFLAGS + GDCFLAGS="-fno-druntime -nostdinc -I $phobos_cv_abs_srcdir/libdruntime -nophoboslib $GDCFLAGS" + + ac_ext=d +ac_compile='$GDC -c $GDCFLAGS conftest.$ac_ext >&5' +ac_link='$GDC -o conftest$ac_exeext $GDCFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=yes + + GDCFLAGS="$GDCFLAGS -g -Werror -ffunction-sections -fdata-sections" + cat > conftest.$ac_ext <<_ACEOF +module object; +int foo; void bar() { } + +extern(C) int main() { + return 0; +} +_ACEOF +if ac_fn_d_try_compile "$LINENO"; then : + ac_fdsections=yes +else + ac_fdsections=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test "x$ac_fdsections" = "xyes"; then + SECTION_FLAGS='-ffunction-sections -fdata-sections' + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_fdsections" >&5 +$as_echo "$ac_fdsections" >&6; } + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + GDCFLAGS=$gdc_save_DFLAGS + + + + druntime_target_cpu_parsed="" case "$target_cpu" in aarch64*) @@ -14373,6 +14422,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -14381,17 +14432,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for minfo section bracketing" >&5 $as_echo_n "checking for minfo section bracketing... " >&6; } + case "$druntime_cv_target_os" in + darwin*) + section="__DATA,__minfodata" + start="section\$start\$__DATA\$__minfodata" + stop="section\$end\$__DATA\$__minfodata" + ;; + *) + section="minfo" + start="__start_minfo" + stop="__stop_minfo" + ;; + esac cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - void* module_info_ptr __attribute__((section ("minfo"))); - extern void* __start_minfo __attribute__((visibility ("hidden"))); - extern void* __stop_minfo __attribute__((visibility ("hidden"))); + void* module_info_ptr __attribute__((section ("$section"))); + extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden"))); + extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden"))); int main() { // Never run, just to prevent compiler from optimizing access - return &__start_minfo == &__stop_minfo; + return (int)(&stop_minfo - &start_minfo); } _ACEOF @@ -14499,7 +14562,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu gdc_save_DFLAGS=$GDCFLAGS - GDCFLAGS="-fno-moduleinfo -nostdinc -I $phobos_cv_abs_srcdir/libdruntime -nophoboslib $GDCFLAGS" + GDCFLAGS="-fno-druntime -nostdinc -I $phobos_cv_abs_srcdir/libdruntime -nophoboslib $GDCFLAGS" ac_ext=d ac_compile='$GDC -c $GDCFLAGS conftest.$ac_ext >&5' @@ -14513,7 +14576,7 @@ if ${ac_cv_search_malloc+:} false; then : else ac_func_search_save_LIBS=$LIBS cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; extern(C) int malloc(); extern(C) int main() { @@ -14559,7 +14622,7 @@ if ${ac_cv_search_pthread_create+:} false; then : else ac_func_search_save_LIBS=$LIBS cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; extern(C) int pthread_create(); extern(C) int main() { @@ -14605,7 +14668,7 @@ if ${ac_cv_search_cosf+:} false; then : else ac_func_search_save_LIBS=$LIBS cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; extern(C) int cosf(); extern(C) int main() { @@ -14651,7 +14714,7 @@ if ${ac_cv_search_clock_gettime+:} false; then : else ac_func_search_save_LIBS=$LIBS cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; extern(C) int clock_gettime(); extern(C) int main() { @@ -14702,7 +14765,7 @@ $as_echo_n "checking for atomic builtins for byte... " >&6; } else cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; import gcc.builtins; extern(C) int main() { @@ -14736,7 +14799,7 @@ $as_echo_n "checking for atomic builtins for short... " >&6; } else cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; import gcc.builtins; extern(C) int main() { @@ -14770,7 +14833,7 @@ $as_echo_n "checking for atomic builtins for int... " >&6; } else cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; import gcc.builtins; extern(C) int main() { @@ -14804,7 +14867,7 @@ $as_echo_n "checking for atomic builtins for long... " >&6; } else cat > conftest.$ac_ext <<_ACEOF -module mod; +module object; import gcc.builtins; extern(C) int main() { @@ -14868,7 +14931,7 @@ fi DCFG_HAVE_LIBATOMIC=false LIBATOMIC= - if test "x$with_libatomic" != "xno"; then : + if test "x$enable_libatomic" != "xno" && test "x$with_libatomic" != "xno"; then : DCFG_HAVE_LIBATOMIC=true LIBATOMIC=../../libatomic/libatomic_convenience.la @@ -14904,7 +14967,7 @@ if test "${with_libbacktrace+set}" = set; then : fi - if test "x$with_libbacktrace" != "xno"; then : + if test "x$enable_libbacktrace" != "xno" && test "x$with_libbacktrace" != "xno"; then : LIBBACKTRACE=../../libbacktrace/libbacktrace.la diff --git a/libphobos/configure.ac b/libphobos/configure.ac index cc9af29..3b5a830 100644 --- a/libphobos/configure.ac +++ b/libphobos/configure.ac @@ -91,9 +91,15 @@ AC_SUBST(CFLAGS_FOR_BUILD) LT_INIT(dlopen) AM_PROG_LIBTOOL WITH_LOCAL_DRUNTIME([LT_LANG([D])], []) +AC_SUBST(enable_shared) +AC_SUBST(enable_static) # libtool variables for Phobos shared and position-independent compiles. # +# Use phobos_lt_pic_flag to designate the automake variable +# used to encapsulate the default libtool approach to creating objects +# with position-independent code. Default: -prefer-pic. +# # Use phobos_compiler_shared_flag to designate the compile-time flags for # creating shared objects. Default: -fversion=Shared. # @@ -105,26 +111,23 @@ WITH_LOCAL_DRUNTIME([LT_LANG([D])], []) # libtool, and so we make it here. How it is handled is that in shared # compilations the `lt_prog_compiler_pic_D' variable is used to instead # ensure that conditional compilation of shared runtime code is compiled in. -# The original PIC flags are then used in the compilation of every object. -# -# Why are objects destined for libgphobos.a compiled with -fPIC? -# Because -fPIC is not harmful to use for objects destined for static -# libraries. In addition, using -fPIC will allow the use of static -# libgphobos.a in the creation of other D shared libraries. if test "$enable_shared" = yes; then + phobos_lt_pic_flag="-prefer-pic" phobos_compiler_pic_flag="$lt_prog_compiler_pic_D" phobos_compiler_shared_flag="-fversion=Shared" else + phobos_lt_pic_flag= phobos_compiler_pic_flag= phobos_compiler_shared_flag= fi +AC_SUBST(phobos_lt_pic_flag) AC_SUBST(phobos_compiler_pic_flag) AC_SUBST(phobos_compiler_shared_flag) # Override the libtool's pic_flag and pic_mode. # Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT. # NB: this impacts --with-pic and --without-pic. -lt_prog_compiler_pic_D="$phobos_compiler_shared_flag" +lt_prog_compiler_pic_D="$phobos_compiler_pic_flag $phobos_compiler_shared_flag" pic_mode='default' # Determine what GCC version number to use in filesystem paths. @@ -134,6 +137,7 @@ GCC_BASE_VER DRUNTIME_CONFIGURE DRUNTIME_MULTILIB DRUNTIME_WERROR +DRUNTIME_SECTION_FLAGS DRUNTIME_CPU_SOURCES DRUNTIME_OS_SOURCES DRUNTIME_OS_THREAD_MODEL diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index a4a9a94..0d554e0 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -0fd4364c4a4eb2ce0ebb8f613092c5bed7a63bf9 +98c6ff0cf1241a0cfac196bf8a0523b1d4ecd3ac 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 945271e..a2e2bff 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -23,8 +23,8 @@ D_EXTRA_DFLAGS=-nostdinc -I $(srcdir) -I . # D flags for compilation AM_DFLAGS= \ - $(phobos_compiler_pic_flag) \ - $(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS) + $(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \ + $(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_DFLAGS) # Flags for other kinds of sources AM_CFLAGS=$(CET_FLAGS) @@ -69,7 +69,8 @@ if DRUNTIME_OS_LINUX DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_LINUX) endif if DRUNTIME_OS_MINGW - DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS) + DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_WINDOWS) \ + config/mingw/msvc.c endif if DRUNTIME_OS_SOLARIS DRUNTIME_SOURCES_CONFIGURED += $(DRUNTIME_DSOURCES_SOLARIS) @@ -184,20 +185,19 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/thread/threadbase.d core/thread/threadgroup.d core/thread/types.d \ core/time.d core/vararg.d core/volatile.d gc/bits.d gc/config.d \ gc/gcinterface.d gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d \ - gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \ - gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \ - gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \ - gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \ - gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \ - gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \ - rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \ - rt/arraycast.d rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d \ - rt/deh.d rt/dmain2.d rt/invariant.d rt/lifetime.d rt/memory.d \ - rt/minfo.d rt/monitor_.d rt/obj.d rt/qsort.d rt/sections.d \ - rt/switch_.d rt/tlsgc.d rt/util/array.d rt/util/container/array.d \ - rt/util/container/common.d rt/util/container/hashtab.d \ - rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \ - rt/util/utf.d + gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/attributes.d \ + gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \ + gcc/sections/common.d gcc/sections/elf.d gcc/sections/macho.d \ + gcc/sections/package.d gcc/sections/pecoff.d gcc/unwind/arm.d \ + gcc/unwind/arm_common.d gcc/unwind/c6x.d gcc/unwind/generic.d \ + gcc/unwind/package.d gcc/unwind/pe.d object.d rt/aApply.d rt/aApplyR.d \ + rt/aaA.d rt/adi.d rt/arrayassign.d rt/arraycast.d rt/arraycat.d \ + rt/cast_.d rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d \ + rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \ + rt/obj.d rt/qsort.d rt/sections.d rt/switch_.d rt/tlsgc.d \ + rt/util/array.d rt/util/container/array.d rt/util/container/common.d \ + rt/util/container/hashtab.d rt/util/container/treap.d rt/util/random.d \ + rt/util/typeinfo.d rt/util/utf.d DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \ core/stdcpp/typeinfo.d @@ -206,9 +206,10 @@ DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \ core/sys/bionic/fcntl.d core/sys/bionic/stdlib.d \ core/sys/bionic/string.d core/sys/bionic/unistd.d -DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \ - core/sys/darwin/dlfcn.d core/sys/darwin/err.d \ - core/sys/darwin/execinfo.d core/sys/darwin/ifaddrs.d \ +DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/config.d \ + core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d \ + core/sys/darwin/err.d core/sys/darwin/execinfo.d \ + core/sys/darwin/fcntl.d core/sys/darwin/ifaddrs.d \ core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \ core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \ core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d \ @@ -275,7 +276,8 @@ DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.d \ core/sys/openbsd/sys/elf.d core/sys/openbsd/sys/elf32.d \ core/sys/openbsd/sys/elf64.d core/sys/openbsd/sys/elf_common.d \ core/sys/openbsd/sys/link_elf.d core/sys/openbsd/sys/mman.d \ - core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d + core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d \ + core/sys/openbsd/unistd.d DRUNTIME_DSOURCES_POSIX = core/sys/posix/aio.d \ core/sys/posix/arpa/inet.d core/sys/posix/config.d \ @@ -382,22 +384,22 @@ DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \ core/sys/windows/sqlext.d core/sys/windows/sqltypes.d \ core/sys/windows/sqlucode.d core/sys/windows/sspi.d \ core/sys/windows/stacktrace.d core/sys/windows/stat.d \ - core/sys/windows/stdc/time.d core/sys/windows/subauth.d \ - core/sys/windows/threadaux.d core/sys/windows/tlhelp32.d \ - core/sys/windows/tmschema.d core/sys/windows/unknwn.d \ - core/sys/windows/uuid.d core/sys/windows/vfw.d \ - core/sys/windows/w32api.d core/sys/windows/winbase.d \ - core/sys/windows/winber.d core/sys/windows/wincon.d \ - core/sys/windows/wincrypt.d core/sys/windows/windef.d \ - core/sys/windows/windows.d core/sys/windows/winerror.d \ - core/sys/windows/wingdi.d core/sys/windows/winhttp.d \ - core/sys/windows/wininet.d core/sys/windows/winioctl.d \ - core/sys/windows/winldap.d core/sys/windows/winnetwk.d \ - core/sys/windows/winnls.d core/sys/windows/winnt.d \ - core/sys/windows/winperf.d core/sys/windows/winreg.d \ - core/sys/windows/winsock2.d core/sys/windows/winspool.d \ - core/sys/windows/winsvc.d core/sys/windows/winuser.d \ - core/sys/windows/winver.d core/sys/windows/wtsapi32.d \ - core/sys/windows/wtypes.d + core/sys/windows/stdc/malloc.d core/sys/windows/stdc/time.d \ + core/sys/windows/subauth.d core/sys/windows/threadaux.d \ + core/sys/windows/tlhelp32.d core/sys/windows/tmschema.d \ + core/sys/windows/unknwn.d core/sys/windows/uuid.d \ + core/sys/windows/vfw.d core/sys/windows/w32api.d \ + core/sys/windows/winbase.d core/sys/windows/winber.d \ + core/sys/windows/wincon.d core/sys/windows/wincrypt.d \ + core/sys/windows/windef.d core/sys/windows/windows.d \ + core/sys/windows/winerror.d core/sys/windows/wingdi.d \ + core/sys/windows/winhttp.d core/sys/windows/wininet.d \ + core/sys/windows/winioctl.d core/sys/windows/winldap.d \ + core/sys/windows/winnetwk.d core/sys/windows/winnls.d \ + core/sys/windows/winnt.d core/sys/windows/winperf.d \ + core/sys/windows/winreg.d core/sys/windows/winsock2.d \ + core/sys/windows/winspool.d core/sys/windows/winsvc.d \ + core/sys/windows/winuser.d core/sys/windows/winver.d \ + core/sys/windows/wtsapi32.d core/sys/windows/wtypes.d DRUNTIME_DISOURCES = __entrypoint.di __main.di diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index 06c0296..cb2e372 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -117,7 +117,9 @@ target_triplet = @target@ @DRUNTIME_OS_NETBSD_TRUE@am__append_6 = $(DRUNTIME_DSOURCES_NETBSD) @DRUNTIME_OS_OPENBSD_TRUE@am__append_7 = $(DRUNTIME_DSOURCES_OPENBSD) @DRUNTIME_OS_LINUX_TRUE@am__append_8 = $(DRUNTIME_DSOURCES_LINUX) -@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS) +@DRUNTIME_OS_MINGW_TRUE@am__append_9 = $(DRUNTIME_DSOURCES_WINDOWS) \ +@DRUNTIME_OS_MINGW_TRUE@ config/mingw/msvc.c + @DRUNTIME_OS_SOLARIS_TRUE@am__append_10 = $(DRUNTIME_DSOURCES_SOLARIS) # CPU specific sources @DRUNTIME_CPU_AARCH64_TRUE@am__append_11 = config/aarch64/switchcontext.S @@ -209,11 +211,11 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \ core/thread/types.lo core/time.lo core/vararg.lo \ core/volatile.lo gc/bits.lo gc/config.lo gc/gcinterface.lo \ gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \ - gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \ - gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \ - gcc/sections/android.lo gcc/sections/elf_shared.lo \ - gcc/sections/osx.lo gcc/sections/package.lo \ - gcc/sections/win32.lo gcc/sections/win64.lo gcc/unwind/arm.lo \ + gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/attributes.lo \ + gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo gcc/emutls.lo \ + gcc/gthread.lo gcc/sections/common.lo gcc/sections/elf.lo \ + gcc/sections/macho.lo gcc/sections/package.lo \ + gcc/sections/pecoff.lo gcc/unwind/arm.lo \ gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \ gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \ object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \ @@ -254,9 +256,10 @@ am__objects_3 = core/sys/posix/aio.lo core/sys/posix/arpa/inet.lo \ core/sys/posix/time.lo core/sys/posix/ucontext.lo \ core/sys/posix/unistd.lo core/sys/posix/utime.lo @DRUNTIME_OS_POSIX_TRUE@am__objects_4 = $(am__objects_3) -am__objects_5 = core/sys/darwin/crt_externs.lo \ - core/sys/darwin/dlfcn.lo core/sys/darwin/err.lo \ - core/sys/darwin/execinfo.lo core/sys/darwin/ifaddrs.lo \ +am__objects_5 = core/sys/darwin/config.lo \ + core/sys/darwin/crt_externs.lo core/sys/darwin/dlfcn.lo \ + core/sys/darwin/err.lo core/sys/darwin/execinfo.lo \ + core/sys/darwin/fcntl.lo core/sys/darwin/ifaddrs.lo \ core/sys/darwin/mach/dyld.lo core/sys/darwin/mach/getsect.lo \ core/sys/darwin/mach/kern_return.lo \ core/sys/darwin/mach/loader.lo core/sys/darwin/mach/nlist.lo \ @@ -322,7 +325,8 @@ am__objects_15 = core/sys/openbsd/dlfcn.lo core/sys/openbsd/err.lo \ core/sys/openbsd/sys/elf32.lo core/sys/openbsd/sys/elf64.lo \ core/sys/openbsd/sys/elf_common.lo \ core/sys/openbsd/sys/link_elf.lo core/sys/openbsd/sys/mman.lo \ - core/sys/openbsd/sys/sysctl.lo core/sys/openbsd/time.lo + core/sys/openbsd/sys/sysctl.lo core/sys/openbsd/time.lo \ + core/sys/openbsd/unistd.lo @DRUNTIME_OS_OPENBSD_TRUE@am__objects_16 = $(am__objects_15) am__objects_17 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \ core/sys/linux/elf.lo core/sys/linux/epoll.lo \ @@ -408,24 +412,26 @@ am__objects_19 = core/sys/windows/accctrl.lo \ core/sys/windows/sql.lo core/sys/windows/sqlext.lo \ core/sys/windows/sqltypes.lo core/sys/windows/sqlucode.lo \ core/sys/windows/sspi.lo core/sys/windows/stacktrace.lo \ - core/sys/windows/stat.lo core/sys/windows/stdc/time.lo \ - core/sys/windows/subauth.lo core/sys/windows/threadaux.lo \ - core/sys/windows/tlhelp32.lo core/sys/windows/tmschema.lo \ - core/sys/windows/unknwn.lo core/sys/windows/uuid.lo \ - core/sys/windows/vfw.lo core/sys/windows/w32api.lo \ - core/sys/windows/winbase.lo core/sys/windows/winber.lo \ - core/sys/windows/wincon.lo core/sys/windows/wincrypt.lo \ - core/sys/windows/windef.lo core/sys/windows/windows.lo \ - core/sys/windows/winerror.lo core/sys/windows/wingdi.lo \ - core/sys/windows/winhttp.lo core/sys/windows/wininet.lo \ - core/sys/windows/winioctl.lo core/sys/windows/winldap.lo \ - core/sys/windows/winnetwk.lo core/sys/windows/winnls.lo \ - core/sys/windows/winnt.lo core/sys/windows/winperf.lo \ - core/sys/windows/winreg.lo core/sys/windows/winsock2.lo \ - core/sys/windows/winspool.lo core/sys/windows/winsvc.lo \ - core/sys/windows/winuser.lo core/sys/windows/winver.lo \ - core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo -@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19) + core/sys/windows/stat.lo core/sys/windows/stdc/malloc.lo \ + core/sys/windows/stdc/time.lo core/sys/windows/subauth.lo \ + core/sys/windows/threadaux.lo core/sys/windows/tlhelp32.lo \ + core/sys/windows/tmschema.lo core/sys/windows/unknwn.lo \ + core/sys/windows/uuid.lo core/sys/windows/vfw.lo \ + core/sys/windows/w32api.lo core/sys/windows/winbase.lo \ + core/sys/windows/winber.lo core/sys/windows/wincon.lo \ + core/sys/windows/wincrypt.lo core/sys/windows/windef.lo \ + core/sys/windows/windows.lo core/sys/windows/winerror.lo \ + core/sys/windows/wingdi.lo core/sys/windows/winhttp.lo \ + core/sys/windows/wininet.lo core/sys/windows/winioctl.lo \ + core/sys/windows/winldap.lo core/sys/windows/winnetwk.lo \ + core/sys/windows/winnls.lo core/sys/windows/winnt.lo \ + core/sys/windows/winperf.lo core/sys/windows/winreg.lo \ + core/sys/windows/winsock2.lo core/sys/windows/winspool.lo \ + core/sys/windows/winsvc.lo core/sys/windows/winuser.lo \ + core/sys/windows/winver.lo core/sys/windows/wtsapi32.lo \ + core/sys/windows/wtypes.lo +@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19) \ +@DRUNTIME_OS_MINGW_TRUE@ config/mingw/libgdruntime_la-msvc.lo am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \ core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \ core/sys/solaris/libelf.lo core/sys/solaris/link.lo \ @@ -460,24 +466,26 @@ am_libgdruntime_la_OBJECTS = $(am__objects_33) libgdruntime_la_OBJECTS = $(am_libgdruntime_la_OBJECTS) am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__objects_34 = core/stdc/libgdruntime_convenience_la-errno_.lo -@DRUNTIME_CPU_AARCH64_TRUE@am__objects_35 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo -@DRUNTIME_CPU_ARM_TRUE@am__objects_36 = config/arm/libgdruntime_convenience_la-switchcontext.lo -@DRUNTIME_CPU_MIPS_TRUE@am__objects_37 = config/mips/libgdruntime_convenience_la-switchcontext.lo -@DRUNTIME_CPU_POWERPC_TRUE@am__objects_38 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo -@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_39 = config/mingw/libgdruntime_convenience_la-switchcontext.lo -@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_40 = config/x86/libgdruntime_convenience_la-switchcontext.lo -@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_41 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo -@DRUNTIME_CPU_S390_TRUE@am__objects_42 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo -am__objects_43 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \ +@DRUNTIME_OS_MINGW_TRUE@am__objects_35 = $(am__objects_19) \ +@DRUNTIME_OS_MINGW_TRUE@ config/mingw/libgdruntime_convenience_la-msvc.lo +@DRUNTIME_CPU_AARCH64_TRUE@am__objects_36 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo +@DRUNTIME_CPU_ARM_TRUE@am__objects_37 = config/arm/libgdruntime_convenience_la-switchcontext.lo +@DRUNTIME_CPU_MIPS_TRUE@am__objects_38 = config/mips/libgdruntime_convenience_la-switchcontext.lo +@DRUNTIME_CPU_POWERPC_TRUE@am__objects_39 = config/powerpc/libgdruntime_convenience_la-switchcontext.lo +@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_TRUE@am__objects_40 = config/mingw/libgdruntime_convenience_la-switchcontext.lo +@DRUNTIME_CPU_X86_TRUE@@DRUNTIME_OS_MINGW_FALSE@am__objects_41 = config/x86/libgdruntime_convenience_la-switchcontext.lo +@DRUNTIME_CPU_SYSTEMZ_TRUE@am__objects_42 = config/systemz/libgdruntime_convenience_la-get_tls_offset.lo +@DRUNTIME_CPU_S390_TRUE@am__objects_43 = config/s390/libgdruntime_convenience_la-get_tls_offset.lo +am__objects_44 = $(am__objects_4) $(am__objects_6) $(am__objects_8) \ $(am__objects_10) $(am__objects_12) $(am__objects_14) \ - $(am__objects_16) $(am__objects_18) $(am__objects_20) \ - $(am__objects_22) $(am__objects_35) $(am__objects_36) \ - $(am__objects_37) $(am__objects_38) $(am__objects_39) \ - $(am__objects_40) $(am__objects_41) $(am__objects_42) -am__objects_44 = $(am__objects_1) $(am__objects_34) $(am__objects_43) \ + $(am__objects_16) $(am__objects_18) $(am__objects_35) \ + $(am__objects_22) $(am__objects_36) $(am__objects_37) \ + $(am__objects_38) $(am__objects_39) $(am__objects_40) \ + $(am__objects_41) $(am__objects_42) $(am__objects_43) +am__objects_45 = $(am__objects_1) $(am__objects_34) $(am__objects_44) \ $(am__objects_32) -am__objects_45 = $(am__objects_44) -am_libgdruntime_convenience_la_OBJECTS = $(am__objects_45) +am__objects_46 = $(am__objects_45) +am_libgdruntime_convenience_la_OBJECTS = $(am__objects_46) libgdruntime_convenience_la_OBJECTS = \ $(am_libgdruntime_convenience_la_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) @@ -632,6 +640,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +SECTION_FLAGS = @SECTION_FLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -659,6 +668,8 @@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ +enable_shared = @enable_shared@ +enable_static = @enable_static@ exec_prefix = @exec_prefix@ gcc_version = @gcc_version@ gdc_include_dir = @gdc_include_dir@ @@ -688,6 +699,7 @@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ phobos_compiler_pic_flag = @phobos_compiler_pic_flag@ phobos_compiler_shared_flag = @phobos_compiler_shared_flag@ +phobos_lt_pic_flag = @phobos_lt_pic_flag@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ @@ -720,8 +732,8 @@ D_EXTRA_DFLAGS = -nostdinc -I $(srcdir) -I . # D flags for compilation AM_DFLAGS = \ - $(phobos_compiler_pic_flag) \ - $(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS) + $(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \ + $(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_DFLAGS) # Flags for other kinds of sources @@ -810,20 +822,19 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/thread/threadbase.d core/thread/threadgroup.d core/thread/types.d \ core/time.d core/vararg.d core/volatile.d gc/bits.d gc/config.d \ gc/gcinterface.d gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d \ - gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/backtrace.d \ - gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \ - gcc/sections/android.d gcc/sections/elf_shared.d gcc/sections/osx.d \ - gcc/sections/package.d gcc/sections/win32.d gcc/sections/win64.d \ - gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \ - gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \ - rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d \ - rt/arraycast.d rt/arraycat.d rt/cast_.d rt/config.d rt/critical_.d \ - rt/deh.d rt/dmain2.d rt/invariant.d rt/lifetime.d rt/memory.d \ - rt/minfo.d rt/monitor_.d rt/obj.d rt/qsort.d rt/sections.d \ - rt/switch_.d rt/tlsgc.d rt/util/array.d rt/util/container/array.d \ - rt/util/container/common.d rt/util/container/hashtab.d \ - rt/util/container/treap.d rt/util/random.d rt/util/typeinfo.d \ - rt/util/utf.d + gc/pooltable.d gc/proxy.d gcc/attribute.d gcc/attributes.d \ + gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \ + gcc/sections/common.d gcc/sections/elf.d gcc/sections/macho.d \ + gcc/sections/package.d gcc/sections/pecoff.d gcc/unwind/arm.d \ + gcc/unwind/arm_common.d gcc/unwind/c6x.d gcc/unwind/generic.d \ + gcc/unwind/package.d gcc/unwind/pe.d object.d rt/aApply.d rt/aApplyR.d \ + rt/aaA.d rt/adi.d rt/arrayassign.d rt/arraycast.d rt/arraycat.d \ + rt/cast_.d rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d \ + rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \ + rt/obj.d rt/qsort.d rt/sections.d rt/switch_.d rt/tlsgc.d \ + rt/util/array.d rt/util/container/array.d rt/util/container/common.d \ + rt/util/container/hashtab.d rt/util/container/treap.d rt/util/random.d \ + rt/util/typeinfo.d rt/util/utf.d DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \ core/stdcpp/typeinfo.d @@ -832,9 +843,10 @@ DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \ core/sys/bionic/fcntl.d core/sys/bionic/stdlib.d \ core/sys/bionic/string.d core/sys/bionic/unistd.d -DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \ - core/sys/darwin/dlfcn.d core/sys/darwin/err.d \ - core/sys/darwin/execinfo.d core/sys/darwin/ifaddrs.d \ +DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/config.d \ + core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d \ + core/sys/darwin/err.d core/sys/darwin/execinfo.d \ + core/sys/darwin/fcntl.d core/sys/darwin/ifaddrs.d \ core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \ core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \ core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d \ @@ -901,7 +913,8 @@ DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.d \ core/sys/openbsd/sys/elf.d core/sys/openbsd/sys/elf32.d \ core/sys/openbsd/sys/elf64.d core/sys/openbsd/sys/elf_common.d \ core/sys/openbsd/sys/link_elf.d core/sys/openbsd/sys/mman.d \ - core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d + core/sys/openbsd/sys/sysctl.d core/sys/openbsd/time.d \ + core/sys/openbsd/unistd.d DRUNTIME_DSOURCES_POSIX = core/sys/posix/aio.d \ core/sys/posix/arpa/inet.d core/sys/posix/config.d \ @@ -1008,23 +1021,23 @@ DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \ core/sys/windows/sqlext.d core/sys/windows/sqltypes.d \ core/sys/windows/sqlucode.d core/sys/windows/sspi.d \ core/sys/windows/stacktrace.d core/sys/windows/stat.d \ - core/sys/windows/stdc/time.d core/sys/windows/subauth.d \ - core/sys/windows/threadaux.d core/sys/windows/tlhelp32.d \ - core/sys/windows/tmschema.d core/sys/windows/unknwn.d \ - core/sys/windows/uuid.d core/sys/windows/vfw.d \ - core/sys/windows/w32api.d core/sys/windows/winbase.d \ - core/sys/windows/winber.d core/sys/windows/wincon.d \ - core/sys/windows/wincrypt.d core/sys/windows/windef.d \ - core/sys/windows/windows.d core/sys/windows/winerror.d \ - core/sys/windows/wingdi.d core/sys/windows/winhttp.d \ - core/sys/windows/wininet.d core/sys/windows/winioctl.d \ - core/sys/windows/winldap.d core/sys/windows/winnetwk.d \ - core/sys/windows/winnls.d core/sys/windows/winnt.d \ - core/sys/windows/winperf.d core/sys/windows/winreg.d \ - core/sys/windows/winsock2.d core/sys/windows/winspool.d \ - core/sys/windows/winsvc.d core/sys/windows/winuser.d \ - core/sys/windows/winver.d core/sys/windows/wtsapi32.d \ - core/sys/windows/wtypes.d + core/sys/windows/stdc/malloc.d core/sys/windows/stdc/time.d \ + core/sys/windows/subauth.d core/sys/windows/threadaux.d \ + core/sys/windows/tlhelp32.d core/sys/windows/tmschema.d \ + core/sys/windows/unknwn.d core/sys/windows/uuid.d \ + core/sys/windows/vfw.d core/sys/windows/w32api.d \ + core/sys/windows/winbase.d core/sys/windows/winber.d \ + core/sys/windows/wincon.d core/sys/windows/wincrypt.d \ + core/sys/windows/windef.d core/sys/windows/windows.d \ + core/sys/windows/winerror.d core/sys/windows/wingdi.d \ + core/sys/windows/winhttp.d core/sys/windows/wininet.d \ + core/sys/windows/winioctl.d core/sys/windows/winldap.d \ + core/sys/windows/winnetwk.d core/sys/windows/winnls.d \ + core/sys/windows/winnt.d core/sys/windows/winperf.d \ + core/sys/windows/winreg.d core/sys/windows/winsock2.d \ + core/sys/windows/winspool.d core/sys/windows/winsvc.d \ + core/sys/windows/winuser.d core/sys/windows/winver.d \ + core/sys/windows/wtsapi32.d core/sys/windows/wtypes.d DRUNTIME_DISOURCES = __entrypoint.di __main.di all: all-am @@ -1201,6 +1214,7 @@ gcc/$(am__dirstamp): @$(MKDIR_P) gcc @: > gcc/$(am__dirstamp) gcc/attribute.lo: gcc/$(am__dirstamp) +gcc/attributes.lo: gcc/$(am__dirstamp) gcc/backtrace.lo: gcc/$(am__dirstamp) gcc/builtins.lo: gcc/$(am__dirstamp) gcc/deh.lo: gcc/$(am__dirstamp) @@ -1209,12 +1223,11 @@ gcc/gthread.lo: gcc/$(am__dirstamp) gcc/sections/$(am__dirstamp): @$(MKDIR_P) gcc/sections @: > gcc/sections/$(am__dirstamp) -gcc/sections/android.lo: gcc/sections/$(am__dirstamp) -gcc/sections/elf_shared.lo: gcc/sections/$(am__dirstamp) -gcc/sections/osx.lo: gcc/sections/$(am__dirstamp) +gcc/sections/common.lo: gcc/sections/$(am__dirstamp) +gcc/sections/elf.lo: gcc/sections/$(am__dirstamp) +gcc/sections/macho.lo: gcc/sections/$(am__dirstamp) gcc/sections/package.lo: gcc/sections/$(am__dirstamp) -gcc/sections/win32.lo: gcc/sections/$(am__dirstamp) -gcc/sections/win64.lo: gcc/sections/$(am__dirstamp) +gcc/sections/pecoff.lo: gcc/sections/$(am__dirstamp) gcc/unwind/$(am__dirstamp): @$(MKDIR_P) gcc/unwind @: > gcc/unwind/$(am__dirstamp) @@ -1339,10 +1352,12 @@ core/sys/posix/utime.lo: core/sys/posix/$(am__dirstamp) core/sys/darwin/$(am__dirstamp): @$(MKDIR_P) core/sys/darwin @: > core/sys/darwin/$(am__dirstamp) +core/sys/darwin/config.lo: core/sys/darwin/$(am__dirstamp) core/sys/darwin/crt_externs.lo: core/sys/darwin/$(am__dirstamp) core/sys/darwin/dlfcn.lo: core/sys/darwin/$(am__dirstamp) core/sys/darwin/err.lo: core/sys/darwin/$(am__dirstamp) core/sys/darwin/execinfo.lo: core/sys/darwin/$(am__dirstamp) +core/sys/darwin/fcntl.lo: core/sys/darwin/$(am__dirstamp) core/sys/darwin/ifaddrs.lo: core/sys/darwin/$(am__dirstamp) core/sys/darwin/mach/$(am__dirstamp): @$(MKDIR_P) core/sys/darwin/mach @@ -1507,6 +1522,7 @@ core/sys/openbsd/sys/link_elf.lo: \ core/sys/openbsd/sys/mman.lo: core/sys/openbsd/sys/$(am__dirstamp) core/sys/openbsd/sys/sysctl.lo: core/sys/openbsd/sys/$(am__dirstamp) core/sys/openbsd/time.lo: core/sys/openbsd/$(am__dirstamp) +core/sys/openbsd/unistd.lo: core/sys/openbsd/$(am__dirstamp) core/sys/linux/$(am__dirstamp): @$(MKDIR_P) core/sys/linux @: > core/sys/linux/$(am__dirstamp) @@ -1687,6 +1703,8 @@ core/sys/windows/stat.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/stdc/$(am__dirstamp): @$(MKDIR_P) core/sys/windows/stdc @: > core/sys/windows/stdc/$(am__dirstamp) +core/sys/windows/stdc/malloc.lo: \ + core/sys/windows/stdc/$(am__dirstamp) core/sys/windows/stdc/time.lo: core/sys/windows/stdc/$(am__dirstamp) core/sys/windows/subauth.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/threadaux.lo: core/sys/windows/$(am__dirstamp) @@ -1720,6 +1738,10 @@ core/sys/windows/winuser.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/winver.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/wtsapi32.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/wtypes.lo: core/sys/windows/$(am__dirstamp) +config/mingw/$(am__dirstamp): + @$(MKDIR_P) config/mingw + @: > config/mingw/$(am__dirstamp) +config/mingw/libgdruntime_la-msvc.lo: config/mingw/$(am__dirstamp) core/sys/solaris/$(am__dirstamp): @$(MKDIR_P) core/sys/solaris @: > core/sys/solaris/$(am__dirstamp) @@ -1769,9 +1791,6 @@ config/powerpc/$(am__dirstamp): @: > config/powerpc/$(am__dirstamp) config/powerpc/libgdruntime_la-switchcontext.lo: \ config/powerpc/$(am__dirstamp) -config/mingw/$(am__dirstamp): - @$(MKDIR_P) config/mingw - @: > config/mingw/$(am__dirstamp) config/mingw/libgdruntime_la-switchcontext.lo: \ config/mingw/$(am__dirstamp) config/x86/$(am__dirstamp): @@ -1796,6 +1815,8 @@ libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EX $(AM_V_GEN)$(libgdruntime_la_LINK) -rpath $(toolexeclibdir) $(libgdruntime_la_OBJECTS) $(libgdruntime_la_LIBADD) $(LIBS) core/stdc/libgdruntime_convenience_la-errno_.lo: \ core/stdc/$(am__dirstamp) +config/mingw/libgdruntime_convenience_la-msvc.lo: \ + config/mingw/$(am__dirstamp) config/aarch64/libgdruntime_convenience_la-switchcontext.lo: \ config/aarch64/$(am__dirstamp) config/arm/libgdruntime_convenience_la-switchcontext.lo: \ @@ -1991,9 +2012,15 @@ config/s390/libgdruntime_convenience_la-get_tls_offset.lo: config/s390/get_tls_o core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c +config/mingw/libgdruntime_la-msvc.lo: config/mingw/msvc.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c + core/stdc/libgdruntime_convenience_la-errno_.lo: core/stdc/errno_.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_convenience_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c +config/mingw/libgdruntime_convenience_la-msvc.lo: config/mingw/msvc.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_convenience_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c + mostlyclean-libtool: -rm -f *.lo diff --git a/libphobos/libdruntime/config/common/threadasm.S b/libphobos/libdruntime/config/common/threadasm.S index 1e9bc76..3546217 100644 --- a/libphobos/libdruntime/config/common/threadasm.S +++ b/libphobos/libdruntime/config/common/threadasm.S @@ -22,7 +22,7 @@ a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ -#if (__linux__ || __FreeBSD__ || __NetBSD__ || __DragonFly__) && __ELF__ +#if (__linux__ || __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__) && __ELF__ /* * Mark the resulting object file as not requiring execution permissions on * stack memory. The absence of this section would mark the whole resulting diff --git a/libphobos/libdruntime/config/mingw/msvc.c b/libphobos/libdruntime/config/mingw/msvc.c new file mode 100644 index 0000000..da40718 --- /dev/null +++ b/libphobos/libdruntime/config/mingw/msvc.c @@ -0,0 +1,169 @@ +/* Windows support code to wrap differences between different + versions of the Microsoft C libaries. + Copyright (C) 2021 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#ifdef __MINGW32__ +#include <_mingw.h> +#endif +#include <stdio.h> + +/* The D runtime library defines stdin, stdout, and stderr as extern(C) symbols + in the core.stdc.stdio module, and require initializing at start-up. */ +__attribute__((weakref ("stdin"))) +static FILE *core_stdc_stdin; + +__attribute__((weakref ("stdout"))) +static FILE *core_stdc_stdout; + +__attribute__((weakref ("stderr"))) +static FILE *core_stdc_stderr; + +/* Set to 1 if runtime is using libucrt.dll. */ +unsigned char msvcUsesUCRT; + +void +init_msvc (void) +{ + core_stdc_stdin = stdin; + core_stdc_stdout = stdout; + core_stdc_stderr = stderr; + +#if __MSVCRT_VERSION__ >= 0xE00 + msvcUsedUCRT = 1; +#endif +} + +/* Phobos std.stdio module assumes these functions are present at link time, + and not absent or macros. */ +#ifdef _fgetc_nolock +#undef _fgetc_nolock + +int +_fgetc_nolock (FILE *fp) +{ + fp->_cnt--; + if (fp->_cnt >= 0) + { + const int c = *fp->_ptr; + fp->_ptr++; + return c & 0xff; + } + else + return _filbuf (fp); +} + +#endif /* _fgetc_nolock */ + +#ifdef _fputc_nolock +#undef _fputc_nolock + +int +_fputc_nolock (int c, FILE *fp) +{ + fp->_cnt--; + if (fp->_cnt >= 0) + { + *fp->_ptr = (char) c; + fp->_ptr++; + return c & 0xff; + } + else + return _flsbuf (c, fp); +} + +#endif /* _fputc_nolock */ + +#ifdef rewind +#undef rewind + +void +rewind (FILE *fp) +{ + fseek (fp, 0, SEEK_SET); + fp->_flag &= ~_IOERR; +} + +#endif /* rewind */ + +#ifdef clearerr +#undef clearerr + +void +clearerr (FILE *fp) +{ + fp->_flag &= ~(_IOERR | _IOEOF); +} + +#endif /* clearerr */ + +#ifdef feof +#undef feof + +int +feof (FILE *fp) +{ + return fp->_flag & _IOEOF; +} + +#endif /* feof */ + +#ifdef ferror +#undef ferror + +int +ferror (FILE *fp) +{ + return fp->_flag & _IOERR; +} + +#endif /* ferror */ + +#ifdef fileno +#undef fileno + +int +fileno (FILE *fp) +{ + return fp->_file; +} + +#endif /* fileno */ + +/* Phobos std.stdio module has a dependency on the UCRT library, so provide + stubs that forward to the nearest equivalent. */ +#if __MSVCRT_VERSION__ < 0x800 + +wint_t +_fgetwc_nolock (FILE *fp) +{ + return fgetwc (fp); +} + +wint_t +_fputwc_nolock (wchar_t c, FILE *fp) +{ + return fputwc(c, fp); +} + +#endif /* __MSVCRT_VERSION__ < 0x800*/ diff --git a/libphobos/libdruntime/config/mingw/switchcontext.S b/libphobos/libdruntime/config/mingw/switchcontext.S index 6592ff6..0cb8b01 100644 --- a/libphobos/libdruntime/config/mingw/switchcontext.S +++ b/libphobos/libdruntime/config/mingw/switchcontext.S @@ -28,7 +28,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see .text .globl CSYM(fiber_switchContext) - .type CSYM(fiber_switchContext), @function + .def CSYM(fiber_switchContext) + .scl 2 + .type 32 + .endef .align 16 CSYM(fiber_switchContext): .cfi_startproc @@ -63,13 +66,15 @@ CSYM(fiber_switchContext): popq %RCX; jmp *%RCX; .cfi_endproc - .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext) #elif defined(_X86_) .text .globl CSYM(fiber_switchContext) - .type CSYM(fiber_switchContext), @function + .def CSYM(fiber_switchContext) + .scl 2 + .type 32 + .endef .align 16 CSYM(fiber_switchContext): .cfi_startproc @@ -104,6 +109,5 @@ CSYM(fiber_switchContext): // 'return' to complete switch ret; .cfi_endproc - .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext) #endif diff --git a/libphobos/libdruntime/config/powerpc/switchcontext.S b/libphobos/libdruntime/config/powerpc/switchcontext.S index d4ea577..74395b0 100644 --- a/libphobos/libdruntime/config/powerpc/switchcontext.S +++ b/libphobos/libdruntime/config/powerpc/switchcontext.S @@ -24,7 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "../common/threadasm.S" -#if !defined(__PPC64__) +#if !defined(__PPC64__) && !defined(__MACH__) /** * Performs a context switch. @@ -151,4 +151,278 @@ CSYM(fiber_switchContext): .cfi_endproc .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext) -#endif /* !defined(__PPC64__) */ +#elif defined(__MACH__) + +/* Implementation for Darwin/macOS preserving callee-saved regs. + + FIXME : There is no unwind frame. + FIXME : not sure if we should save the vsave reg (perhaps using the slot we have + r11 in at present). */ + +/* Darwin has a red zone (220 bytes for PPC 288 for PPC64) which we can write + to before the stack is updated without worrying about it being clobbered by + signals or hardware interrupts. + + The stack will be 16byte aligned on entry with: + PPC PPC64 + SP-> +---------------------------------------+ + | back chain to caller | 0 0 + +---------------------------------------+ + | slot to save CR | 4 8 + +---------------------------------------+ + | slot to save LR | 8 16 + +---------------------------------------+ + | etc.. etc.. as per C calling conv. | */ + +# if __PPC64__ +# define LD ld +# define ST std +# define STU stdu +# define SZ 8 +# define MACHINE ppc64 +# define RED_ZONE 288 +# else +# define LD lwz +# define ST stw +# define STU stwu +# define SZ 4 +# define MACHINE ppc7400 +# define RED_ZONE 220 +# endif + +# define SAVE_VECTORS 0 +/** + * Performs a context switch. + * + * r3 - old context pointer + * r4 - new context pointer + * + */ + .machine MACHINE + .text + .globl CSYM(fiber_switchContext) + .align 2 +CSYM(fiber_switchContext): +LFB0: + /* Get the link reg. */ + mflr r0 + /* Get the callee-saved crs (well all of them, actually). */ + mfcr r12 + + /* Save GPRs, we save the static chain here too although it is not clear if we need to. */ + ST r31, ( -1 * SZ)(r1) + ST r30, ( -2 * SZ)(r1) + ST r29, ( -3 * SZ)(r1) + ST r28, ( -4 * SZ)(r1) + ST r27, ( -5 * SZ)(r1) + ST r26, ( -6 * SZ)(r1) + ST r25, ( -7 * SZ)(r1) + ST r24, ( -8 * SZ)(r1) + ST r23, ( -9 * SZ)(r1) + ST r22, (-10 * SZ)(r1) + ST r21, (-11 * SZ)(r1) + ST r20, (-12 * SZ)(r1) + ST r19, (-13 * SZ)(r1) + ST r18, (-14 * SZ)(r1) + ST r17, (-15 * SZ)(r1) + ST r16, (-16 * SZ)(r1) + ST r15, (-17 * SZ)(r1) + ST r14, (-18 * SZ)(r1) + ST r13, (-19 * SZ)(r1) + + /* Save the lr and cr into the normal function linkage area. */ + ST r0, 2*SZ(r1) + ST r12, SZ(r1) + + /* We update the stack pointer here, since we do not want the GC to + scan the floating point registers. We are still 16-byte aligned. */ + STU r11, (-20 * SZ)(r1) + + /* Update the stack pointer in the old context as per comment above. */ + ST r1, 0(r3) + + /* Save FPRs - same for PPC and PPC64 */ + stfd f14, (-18 * 8)(r1) + stfd f15, (-17 * 8)(r1) + stfd f16, (-16 * 8)(r1) + stfd f17, (-15 * 8)(r1) + stfd f18, (-14 * 8)(r1) + stfd f19, (-13 * 8)(r1) + stfd f20, (-12 * 8)(r1) + stfd f21, (-11 * 8)(r1) + stfd f22, (-10 * 8)(r1) + stfd f23, ( -9 * 8)(r1) + stfd f24, ( -8 * 8)(r1) + stfd f25, ( -7 * 8)(r1) + stfd f26, ( -6 * 8)(r1) + stfd f27, ( -5 * 8)(r1) + stfd f28, ( -4 * 8)(r1) + stfd f29, ( -3 * 8)(r1) + stfd f30, ( -2 * 8)(r1) + stfd f31, ( -1 * 8)(r1) + +#if SAVE_VECTORS + /* We are still 16byte aligned - so we are ok for vector saves. + but the combined size of the vectors (12 x 16) + the FPRs (144) exceeds the + red zone size so we need to adjust the stack again - note this means careful + ordering is needed on the restore. */ + + addi r1, r1, -(12*16+18*8) + li r11, 0 + stvx v20,r11,r1 + addi r11, r11, 16 + stvx v21,r11,r1 + addi r11, r11, 16 + stvx v22,r11,r1 + addi r11, r11, 16 + stvx v23,r11,r1 + addi r11, r11, 16 + stvx v24,r11,r1 + addi r11, r11, 16 + stvx v25,r11,r1 + addi r11, r11, 16 + stvx v26,r11,r1 + addi r11, r11, 16 + stvx v27,r11,r1 + addi r11, r11, 16 + stvx v28,r11,r1 + addi r11, r11, 16 + stvx v29,r11,r1 + addi r11, r11, 16 + stvx v30,r11,r1 + addi r11, r11, 16 + stvx v31,r11,r1 + + /* Now do the same thing in reverse - starting with r4 pointing to + the block of GPRs - stage 1 point to the saved vectors and fprs. */ + + addi r1, r4, -(12*16+18*8) + li r11, 0 + lvx v20,r11,r1 + addi r11, r11, 16 + lvx v21,r11,r1 + addi r11, r11, 16 + lvx v22,r11,r1 + addi r11, r11, 16 + lvx v23,r11,r1 + addi r11, r11, 16 + lvx v24,r11,r1 + addi r11, r11, 16 + lvx v25,r11,r1 + addi r11, r11, 16 + lvx v26,r11,r1 + addi r11, r11, 16 + lvx v27,r11,r1 + addi r11, r11, 16 + lvx v28,r11,r1 + addi r11, r11, 16 + lvx v29,r11,r1 + addi r11, r11, 16 + lvx v30,r11,r1 + addi r11, r11, 16 + lvx v31,r11,r1 +#endif + + /* Now it is safe to update the stack pointer since the combined + size of the GPRs and FPRs will not exceed the red zone. */ + + addi r1, r4, 20 * SZ + + /* Restore FPRs */ + lfd f14, (-18 * 8)(r4) + lfd f15, (-17 * 8)(r4) + lfd f16, (-16 * 8)(r4) + lfd f17, (-15 * 8)(r4) + lfd f18, (-14 * 8)(r4) + lfd f19, (-13 * 8)(r4) + lfd f20, (-12 * 8)(r4) + lfd f21, (-11 * 8)(r4) + lfd f22, (-10 * 8)(r4) + lfd f23, ( -9 * 8)(r4) + lfd f24, ( -8 * 8)(r4) + lfd f25, ( -7 * 8)(r4) + lfd f26, ( -6 * 8)(r4) + lfd f27, ( -5 * 8)(r4) + lfd f28, ( -4 * 8)(r4) + lfd f29, ( -3 * 8)(r4) + lfd f30, ( -2 * 8)(r4) + lfd f31, ( -1 * 8)(r4) + + /* Pick up lr and cr */ + LD r0, 2*SZ(r1) + LD r12, SZ(r1) + + /* Restore GPRs */ + LD r11, (-20 * SZ)(r1) + LD r13, (-19 * SZ)(r1) + LD r14, (-18 * SZ)(r1) + LD r15, (-17 * SZ)(r1) + LD r16, (-16 * SZ)(r1) + LD r17, (-15 * SZ)(r1) + LD r18, (-14 * SZ)(r1) + LD r19, (-13 * SZ)(r1) + LD r20, (-12 * SZ)(r1) + LD r21, (-11 * SZ)(r1) + LD r22, (-10 * SZ)(r1) + LD r23, ( -9 * SZ)(r1) + LD r24, ( -8 * SZ)(r1) + LD r25, ( -7 * SZ)(r1) + LD r26, ( -6 * SZ)(r1) + LD r27, ( -5 * SZ)(r1) + LD r28, ( -4 * SZ)(r1) + LD r29, ( -3 * SZ)(r1) + LD r30, ( -2 * SZ)(r1) + LD r31, ( -1 * SZ)(r1) + + /* Set cr and lr */ + mtcr r12 + mtlr r0 + + /* Return and switch context */ + blr +LFE0: + +/* Minimal CFI / FDE which does not describe the stacking of the GPRs - but only that + the routine has been entered/exited. */ + +# if __PPC64__ +# define DATA_ALIGN 0x78 +# define ALIGN_SIZE 3 +# define ADDRD .quad +# else +# define DATA_ALIGN 0x7c +# define ALIGN_SIZE 3 +# define ADDRD .long +# endif + + .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EH_frame1: + .set L$set$0,LECIE1-LSCIE1 + .long L$set$0 ; Length of Common Information Entry +LSCIE1: + .long 0 ; CIE Identifier Tag + .byte 0x3 ; CIE Version + .ascii "zR\0" ; CIE Augmentation + .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor + .byte DATA_ALIGN ; sleb128 -4/-8; CIE Data Alignment Factor + .byte 0x41 ; uleb128 0x41; CIE RA Column + .byte 0x1 ; uleb128 0x1; Augmentation size + .byte 0x10 ; FDE Encoding (pcrel) + .byte 0xc ; DW_CFA_def_cfa + .byte 0x1 ; uleb128 0x1 + .byte 0 ; uleb128 0 + .p2align ALIGN_SIZE,0 +LECIE1: +LSFDE1: + .set L$set$1,LEFDE1-LASFDE1 + .long L$set$1 ; FDE Length +LASFDE1: + .long LASFDE1-EH_frame1 ; FDE CIE offset + ADDRD LFB0-. ; FDE initial location + .set L$set$2,LFE0-LFB0 + ADDRD L$set$2 ; FDE address range + .byte 0 ; uleb128 0; Augmentation size + .p2align ALIGN_SIZE,0 +LEFDE1: + +#endif /* defined(__MACH__) */ diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S index 82420c6..9f4befd 100644 --- a/libphobos/libdruntime/config/x86/switchcontext.S +++ b/libphobos/libdruntime/config/x86/switchcontext.S @@ -29,7 +29,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see # include <cet.h> #endif -#if defined(__i386__) && !defined(__CET__) +#if !defined(__CET__) + +# if defined(__ELF__) + +# if defined(__i386__) .text .globl CSYM(fiber_switchContext) @@ -63,7 +67,9 @@ CSYM(fiber_switchContext): .cfi_endproc .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext) -#elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__) +# endif /* defined(__ELF__) && defined(__i386__) */ + +# if defined(__x86_64__) && !defined(__ILP32__) .text .globl CSYM(fiber_switchContext) @@ -98,4 +104,151 @@ CSYM(fiber_switchContext): .cfi_endproc .size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext) -#endif +# endif /* defined(__ELF__) && defined(__x86_64__) && !defined(__ILP32__) */ + +# endif /* defined(__ELF__) */ + +# if defined(__MACH__) + +# if defined(__i386__) + + .text + .globl CSYM(fiber_switchContext) + .p2align 4 +CSYM(fiber_switchContext): +LFB0: + // save current stack state + push %ebp + mov %esp, %ebp + push %edi + push %esi + push %ebx + push %eax + + // store oldp again with more accurate address + mov 8(%ebp), %eax + mov %esp, (%eax) + // load newp to begin context switch + mov 12(%ebp), %esp + + // load saved state from new stack + pop %eax + pop %ebx + pop %esi + pop %edi + pop %ebp + + // 'return' to complete switch + ret +LFE0: + +/* CFI */ + .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EH_frame1: + .set L$set$0,LECIE1-LSCIE1 + .long L$set$0 # Length of Common Information Entry +LSCIE1: + .long 0 # CIE Identifier Tag + .byte 0x1 # CIE Version + .ascii "zR\0" # CIE Augmentation + .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor + .byte 0x7c # sleb128 -4; CIE Data Alignment Factor + .byte 0x8 # CIE RA Column + .byte 0x1 # uleb128 0x1; Augmentation size + .byte 0x10 # FDE Encoding (pcrel) + .byte 0xc # DW_CFA_def_cfa + .byte 0x5 # uleb128 0x5 + .byte 0x4 # uleb128 0x4 + .byte 0x88 # DW_CFA_offset, column 0x8 + .byte 0x1 # uleb128 0x1 + .p2align 2,0 +LECIE1: + +/* minimal FDE - does not record the stack frame changes. */ +LSFDE1: + .set L$set$1,LEFDE1-LASFDE1 + .long L$set$1 # FDE Length +LASFDE1: + .long LASFDE1-EH_frame1 # FDE CIE offset + .long LFB0-. # FDE initial location + .set L$set$2,LFE0-LFB0 + .long L$set$2 # FDE address range + .byte 0 # uleb128 0; Augmentation size + .p2align 2,0 +LEFDE1: + +# endif /* defined(__MACH__) && defined(__i386__) */ + +# if defined(__x86_64__) && !defined(__ILP32__) + + .text + .globl CSYM(fiber_switchContext) + .p2align 4 +CSYM(fiber_switchContext): +LFB0: + // Save current stack state.save current stack state + push %rbp + mov %rsp, %rbp + push %r15 + push %r14 + push %r13 + push %r12 + push %rbx + + // store oldp again with more accurate address + mov %rsp, (%rdi) + // load newp to begin context switch + mov %rsi, %rsp + + // load saved state from new stack + pop %rbx + pop %r12 + pop %r13 + pop %r14 + pop %r15 + pop %rbp + + // 'return' to complete switch + ret +LFE0: + +/* CFI */ + .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EH_frame1: + .set L$set$0,LECIE1-LSCIE1 + .long L$set$0 # Length of Common Information Entry +LSCIE1: + .long 0 # CIE Identifier Tag + .byte 0x1 # CIE Version + .ascii "zR\0" # CIE Augmentation + .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor + .byte 0x78 # sleb128 -8; CIE Data Alignment Factor + .byte 0x10 # CIE RA Column + .byte 0x1 # uleb128 0x1; Augmentation size + .byte 0x10 # FDE Encoding (pcrel) + .byte 0xc # DW_CFA_def_cfa + .byte 0x7 # uleb128 0x7 + .byte 0x8 # uleb128 0x8 + .byte 0x90 # DW_CFA_offset, column 0x10 + .byte 0x1 # uleb128 0x1 + .p2align 3,0 +LECIE1: + +/* minimal FDE - does not record the stack frame changes. */ +LSFDE1: + .set L$set$1,LEFDE1-LASFDE1 + .long L$set$1 # FDE Length +LASFDE1: + .long LASFDE1-EH_frame1 # FDE CIE offset + .quad LFB0-. # FDE initial location + .set L$set$2,LFE0-LFB0 + .quad L$set$2 # FDE address range + .byte 0 # uleb128 0; Augmentation size + .p2align 3,0 +LEFDE1: + +# endif /* defined(__MACH__) && defined(__x86_64__) && !defined(__ILP32__) */ + +# endif /* defined (__MACH__) */ + +#endif /* !defined(__CET__) */ diff --git a/libphobos/libdruntime/core/stdc/complex.d b/libphobos/libdruntime/core/stdc/complex.d index d878366..b84651f 100644 --- a/libphobos/libdruntime/core/stdc/complex.d +++ b/libphobos/libdruntime/core/stdc/complex.d @@ -19,163 +19,97 @@ extern (C): nothrow: @nogc: -/// +// @@@DEPRECATED_2.105@@@ +deprecated: alias creal complex; -/// alias ireal imaginary; -/// cdouble cacos(cdouble z); -/// cfloat cacosf(cfloat z); -/// creal cacosl(creal z); -/// cdouble casin(cdouble z); -/// cfloat casinf(cfloat z); -/// creal casinl(creal z); -/// cdouble catan(cdouble z); -/// cfloat catanf(cfloat z); -/// creal catanl(creal z); -/// cdouble ccos(cdouble z); -/// cfloat ccosf(cfloat z); -/// creal ccosl(creal z); -/// cdouble csin(cdouble z); -/// cfloat csinf(cfloat z); -/// creal csinl(creal z); -/// cdouble ctan(cdouble z); -/// cfloat ctanf(cfloat z); -/// creal ctanl(creal z); -/// cdouble cacosh(cdouble z); -/// cfloat cacoshf(cfloat z); -/// creal cacoshl(creal z); -/// cdouble casinh(cdouble z); -/// cfloat casinhf(cfloat z); -/// creal casinhl(creal z); -/// cdouble catanh(cdouble z); -/// cfloat catanhf(cfloat z); -/// creal catanhl(creal z); -/// cdouble ccosh(cdouble z); -/// cfloat ccoshf(cfloat z); -/// creal ccoshl(creal z); -/// cdouble csinh(cdouble z); -/// cfloat csinhf(cfloat z); -/// creal csinhl(creal z); -/// cdouble ctanh(cdouble z); -/// cfloat ctanhf(cfloat z); -/// creal ctanhl(creal z); -/// cdouble cexp(cdouble z); -/// cfloat cexpf(cfloat z); -/// creal cexpl(creal z); -/// cdouble clog(cdouble z); -/// cfloat clogf(cfloat z); -/// creal clogl(creal z); -/// double cabs(cdouble z); - /// float cabsf(cfloat z); - /// real cabsl(creal z); - /// cdouble cpow(cdouble x, cdouble y); -/// cfloat cpowf(cfloat x, cfloat y); -/// creal cpowl(creal x, creal y); -/// cdouble csqrt(cdouble z); -/// cfloat csqrtf(cfloat z); -/// creal csqrtl(creal z); -/// double carg(cdouble z); - /// float cargf(cfloat z); - /// real cargl(creal z); -/// pragma(inline, true) double cimag(cdouble z) { return z.im; } -/// pragma(inline, true) float cimagf(cfloat z) { return z.im; } -/// pragma(inline, true) real cimagl(creal z) { return z.im; } -/// cdouble conj(cdouble z); -/// cfloat conjf(cfloat z); -/// creal conjl(creal z); -/// cdouble cproj(cdouble z); -/// cfloat cprojf(cfloat z); -/// creal cprojl(creal z); // Note: `creal` is a keyword in D and so this function is inaccessible, use `creald` instead //pragma(inline, true) double creal(cdouble z) { return z.re; } -/// pragma(inline, true) double creald(cdouble z) { return z.re; } -/// pragma(inline, true) float crealf(cfloat z) { return z.re; } -/// pragma(inline, true) real creall(creal z) { return z.re; } diff --git a/libphobos/libdruntime/core/stdc/config.d b/libphobos/libdruntime/core/stdc/config.d index cdb987f..44bb707 100644 --- a/libphobos/libdruntime/core/stdc/config.d +++ b/libphobos/libdruntime/core/stdc/config.d @@ -34,6 +34,7 @@ version (StdDdoc) alias ddoc_long = int; alias ddoc_ulong = uint; } + struct ddoc_complex(T) { T re; T im; }; } /*** @@ -89,6 +90,24 @@ version (StdDdoc) * C++ compiler's `ptrdiff_t` type. */ alias cpp_ptrdiff_t = ptrdiff_t; + + /*** + * Used for a complex floating point type that corresponds in size and ABI to the associated + * C compiler's `_Complex float` type. + */ + alias c_complex_float = ddoc_complex!float; + + /*** + * Used for a complex floating point type that corresponds in size and ABI to the associated + * C compiler's `_Complex double` type. + */ + alias c_complex_double = ddoc_complex!double; + + /*** + * Used for a complex floating point type that corresponds in size and ABI to the associated + * C compiler's `_Complex long double` type. + */ + alias c_complex_real = ddoc_complex!real; } else { @@ -167,7 +186,18 @@ else version (Posix) } } -version (CRuntime_Microsoft) +version (GNU) + alias c_long_double = real; +else version (LDC) + alias c_long_double = real; // 64-bit real for MSVC targets +else version (SDC) +{ + version (X86) + alias c_long_double = real; + else version (X86_64) + alias c_long_double = real; +} +else version (CRuntime_Microsoft) { /* long double is 64 bits, not 80 bits, but is mangled differently * than double. To distinguish double from long double, create a wrapper to represent @@ -203,17 +233,6 @@ else version (DigitalMars) alias real c_long_double; } } -else version (GNU) - alias real c_long_double; -else version (LDC) - alias real c_long_double; -else version (SDC) -{ - version (X86) - alias real c_long_double; - else version (X86_64) - alias real c_long_double; -} static assert(is(c_long_double), "c_long_double needs to be declared for this platform/architecture."); @@ -230,4 +249,19 @@ else alias cpp_size_t = size_t; alias cpp_ptrdiff_t = ptrdiff_t; } + +// ABI layout of native complex types. +private struct _Complex(T) +{ + T re; + T im; +} + +enum __c_complex_float : _Complex!float; +enum __c_complex_double : _Complex!double; +enum __c_complex_real : _Complex!c_long_double; + +alias c_complex_float = __c_complex_float; +alias c_complex_double = __c_complex_double; +alias c_complex_real = __c_complex_real; } diff --git a/libphobos/libdruntime/core/stdc/errno.d b/libphobos/libdruntime/core/stdc/errno.d index 31f7d11..57bc15d 100644 --- a/libphobos/libdruntime/core/stdc/errno.d +++ b/libphobos/libdruntime/core/stdc/errno.d @@ -156,15 +156,9 @@ else version (Haiku) else { /// - @property int errno() { return getErrno(); } + extern(C) pragma(mangle, "getErrno") @property int errno(); /// - @property int errno(int n) { return setErrno(n); } - - extern (C) - { - private int getErrno(); // for internal use - private int setErrno(int); // for internal use - } + extern(C) pragma(mangle, "setErrno") @property int errno(int n); } extern (C): @@ -1532,7 +1526,11 @@ else version (OpenBSD) enum EIDRM = 89; /// Identifier removed enum ENOMSG = 90; /// No message of desired type enum ENOTSUP = 91; /// Not supported - enum ELAST = 91; /// Must be equal largest errno + enum EBADMSG = 92; /// Bad message + enum ENOTRECOVERABLE = 93; /// State not recoverable + enum EOWNERDEAD = 94; /// Previous owner died + enum EPROTO = 95; /// Protocol error + enum ELAST = 95; /// Must be equal largest errno } else version (DragonFlyBSD) { diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d index e8d1fa8..2de6e57 100644 --- a/libphobos/libdruntime/core/stdc/math.d +++ b/libphobos/libdruntime/core/stdc/math.d @@ -319,16 +319,12 @@ version (CRuntime_DigitalMars) { //int fpclassify(real-floating x); /// - pure int fpclassify(float x) { return __fpclassify_f(x); } + extern(C) pragma(mangle, "__fpclassify_f") pure int fpclassify(float x); /// - pure int fpclassify(double x) { return __fpclassify_d(x); } + extern(C) pragma(mangle, "__fpclassify_d") pure int fpclassify(double x); /// - pure int fpclassify(real x) - { - return (real.sizeof == double.sizeof) - ? __fpclassify_d(x) - : __fpclassify_ld(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify_d" : "__fpclassify_ld") + pure int fpclassify(real x); //int isfinite(real-floating x); /// @@ -428,98 +424,177 @@ else version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) o pure int _fpclass(double x); } + version (MinGW) + { enum { /// - FP_SUBNORMAL = -2, + FP_NAN = 0x0100, /// - FP_NORMAL = -1, + FP_NORMAL = 0x0400, /// - FP_ZERO = 0, + FP_INFINITE = FP_NAN | FP_NORMAL, /// - FP_INFINITE = 1, + FP_ZERO = 0x0400, /// - FP_NAN = 2, + FP_SUBNORMAL = FP_NORMAL | FP_ZERO } - pure private short _fdclass(float x); - pure private short _dclass(double x); + pure int __fpclassifyf(float x); + pure int __fpclassify(double x); + pure int __fpclassifyl(real x); - pure private int _fdsign(float x); - pure private int _dsign(double x); + pure int __isnanf(float x); + pure int __isnan(double x); + pure int __isnanl(real x); - extern(D) - { - //int fpclassify(real-floating x); - /// - pure int fpclassify()(float x) { return _fdclass(x); } - /// - pure int fpclassify()(double x) { return _dclass(x); } - /// - pure int fpclassify()(real x) + pure int __signbitf(float x); + pure int __signbit(double x); + pure int __signbitl(real x); + + extern (D) { - static if (real.sizeof == double.sizeof) - return _dclass(cast(double) x); - else - static assert(false, "fpclassify(real) not supported by MS C runtime"); - } + //int fpclassify(real-floating x); + /// + extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x); + /// + extern(C) pragma(mangle, "__fpclassify") pure int fpclassify(double x); + /// + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl") + pure int fpclassify(real x); - //int isfinite(real-floating x); - /// - pure int isfinite()(float x) { return fpclassify(x) <= 0; } - /// - pure int isfinite()(double x) { return fpclassify(x) <= 0; } - /// - pure int isfinite()(real x) { return fpclassify(x) <= 0; } + //int isfinite(real-floating x); + /// + pure int isfinite(float x) { return (fpclassify(x) & FP_NORMAL) == 0; } + /// + pure int isfinite(double x) { return (fpclassify(x) & FP_NORMAL) == 0; } + /// + pure int isfinite(real x) { return (fpclassify(x) & FP_NORMAL) == 0; } - //int isinf(real-floating x); - /// - pure int isinf()(float x) { return fpclassify(x) == FP_INFINITE; } - /// - pure int isinf()(double x) { return fpclassify(x) == FP_INFINITE; } - /// - pure int isinf()(real x) { return fpclassify(x) == FP_INFINITE; } + //int isinf(real-floating x); + /// + pure int isinf(float x) { return fpclassify(x) == FP_INFINITE; } + /// + pure int isinf(double x) { return fpclassify(x) == FP_INFINITE; } + /// + pure int isinf(real x) { return fpclassify(x) == FP_INFINITE; } - //int isnan(real-floating x); - version (none) // requires MSVCRT 12+ (VS 2013) - { + //int isnan(real-floating x); + /// + extern(C) pragma(mangle, "__isnanf") pure int isnan(float x); + /// + extern(C) pragma(mangle, "__isnan") pure int isnan(double x); + /// + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl") + pure int isnan(real x); + + //int isnormal(real-floating x); + /// + int isnormal(float x) { return fpclassify(x) == FP_NORMAL; } + /// + int isnormal(double x) { return fpclassify(x) == FP_NORMAL; } + /// + int isnormal(real x) { return fpclassify(x) == FP_NORMAL; } + + //int signbit(real-floating x); /// - pure int isnan(float x) { return fpclassify(x) == FP_NAN; } + extern(C) pragma(mangle, "__signbitf") pure int signbit(float x); /// - pure int isnan(double x) { return fpclassify(x) == FP_NAN; } + extern(C) pragma(mangle, "__signbit") pure int signbit(double x); /// - pure int isnan(real x) { return fpclassify(x) == FP_NAN; } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl") + int signbit(real x); } - else // for backward compatibility with older runtimes + } + else + { + enum { /// - pure int isnan(float x) { version (Win64) return _isnanf(x); else return _isnan(cast(double) x); } + FP_SUBNORMAL = -2, + /// + FP_NORMAL = -1, /// - pure int isnan(double x) { return _isnan(x); } + FP_ZERO = 0, /// - pure int isnan(real x) { return _isnan(cast(double) x); } + FP_INFINITE = 1, + /// + FP_NAN = 2, } - //int isnormal(real-floating x); - /// - pure int isnormal()(float x) { return fpclassify(x) == FP_NORMAL; } - /// - pure int isnormal()(double x) { return fpclassify(x) == FP_NORMAL; } - /// - pure int isnormal()(real x) { return fpclassify(x) == FP_NORMAL; } - - //int signbit(real-floating x); - /// - pure int signbit()(float x) { return _fdsign(x); } - /// - pure int signbit()(double x) { return _dsign(x); } - /// - pure int signbit()(real x) + extern(D) { - static if (real.sizeof == double.sizeof) - return _dsign(cast(double) x); - else - return (cast(short*)&(x))[4] & 0x8000; + //int fpclassify(real-floating x); + /// + extern(C) pragma(mangle, "_fdclass") pure int fpclassify(float x); + /// + extern(C) pragma(mangle, "_dclass") pure int fpclassify(double x); + /// + pure int fpclassify()(real x) + { + static if (real.sizeof == double.sizeof) + return fpclassify(cast(double) x); + else + static assert(false, "fpclassify(real) not supported by MS C runtime"); + } + + //int isfinite(real-floating x); + /// + pure int isfinite()(float x) { return fpclassify(x) <= 0; } + /// + pure int isfinite()(double x) { return fpclassify(x) <= 0; } + /// + pure int isfinite()(real x) { return fpclassify(x) <= 0; } + + //int isinf(real-floating x); + /// + pure int isinf()(float x) { return fpclassify(x) == FP_INFINITE; } + /// + pure int isinf()(double x) { return fpclassify(x) == FP_INFINITE; } + /// + pure int isinf()(real x) { return fpclassify(x) == FP_INFINITE; } + + //int isnan(real-floating x); + version (none) // requires MSVCRT 12+ (VS 2013) + { + /// + pure int isnan(float x) { return fpclassify(x) == FP_NAN; } + /// + pure int isnan(double x) { return fpclassify(x) == FP_NAN; } + /// + pure int isnan(real x) { return fpclassify(x) == FP_NAN; } + } + else // for backward compatibility with older runtimes + { + /// + pure int isnan(float x) { version (Win64) return _isnanf(x); else return _isnan(cast(double) x); } + /// + extern(C) pragma(mangle, "_isnan") pure int isnan(double x); + /// + pure int isnan(real x) { return _isnan(cast(double) x); } + } + + //int isnormal(real-floating x); + /// + pure int isnormal()(float x) { return fpclassify(x) == FP_NORMAL; } + /// + pure int isnormal()(double x) { return fpclassify(x) == FP_NORMAL; } + /// + pure int isnormal()(real x) { return fpclassify(x) == FP_NORMAL; } + + //int signbit(real-floating x); + /// + extern(C) pragma(mangle, "_fdsign") pure int signbit(float x); + /// + extern(C) pragma(mangle, "_dsign") pure int signbit(double x); + /// + pure int signbit()(real x) + { + static if (real.sizeof == double.sizeof) + return signbit(cast(double) x); + else + return (cast(short*)&(x))[4] & 0x8000; + } } } } @@ -573,55 +648,39 @@ else version (CRuntime_Glibc) { //int fpclassify(real-floating x); /// - pure int fpclassify(float x) { return __fpclassifyf(x); } + extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x); /// - pure int fpclassify(double x) { return __fpclassify(x); } + extern(C) pragma(mangle, "__fpclassify") pure int fpclassify(double x); /// - pure int fpclassify(real x) - { - return (real.sizeof == double.sizeof) - ? __fpclassify(x) - : __fpclassifyl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl") + pure int fpclassify(real x); //int isfinite(real-floating x); /// - pure int isfinite(float x) { return __finitef(x); } + extern(C) pragma(mangle, "__finitef") pure int isfinite(float x); /// - pure int isfinite(double x) { return __finite(x); } + extern(C) pragma(mangle, "__finite") pure int isfinite(double x); /// - pure int isfinite(real x) - { - return (real.sizeof == double.sizeof) - ? __finite(x) - : __finitel(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__finite" : "__finitel") + pure int isfinite(real x); //int isinf(real-floating x); /// - pure int isinf(float x) { return __isinff(x); } + extern(C) pragma(mangle, "__isinff") pure int isinf(float x); /// - pure int isinf(double x) { return __isinf(x); } + extern(C) pragma(mangle, "__isinf") pure int isinf(double x); /// - pure int isinf(real x) - { - return (real.sizeof == double.sizeof) - ? __isinf(x) - : __isinfl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isinf" : "__isinfl") + pure int isinf(real x); //int isnan(real-floating x); /// - pure int isnan(float x) { return __isnanf(x); } + extern(C) pragma(mangle, "__isnanf") pure int isnan(float x); /// - pure int isnan(double x) { return __isnan(x); } + extern(C) pragma(mangle, "__isnan") pure int isnan(double x); /// - pure int isnan(real x) - { - return (real.sizeof == double.sizeof) - ? __isnan(x) - : __isnanl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl") + pure int isnan(real x); //int isnormal(real-floating x); /// @@ -633,16 +692,12 @@ else version (CRuntime_Glibc) //int signbit(real-floating x); /// - pure int signbit(float x) { return __signbitf(x); } + extern(C) pragma(mangle, "__signbitf") pure int signbit(float x); /// - pure int signbit(double x) { return __signbit(x); } + extern(C) pragma(mangle, "__signbit") pure int signbit(double x); /// - pure int signbit(real x) - { - return (real.sizeof == double.sizeof) - ? __signbit(x) - : __signbitl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl") + pure int signbit(real x); } } else version (CRuntime_Musl) @@ -685,16 +740,12 @@ else version (CRuntime_Musl) { //int fpclassify(real-floating x); /// - int fpclassify(float x) { return __fpclassifyf(x); } + extern(C) pragma(mangle, "__fpclassifyf") int fpclassify(float x); /// - int fpclassify(double x) { return __fpclassify(x); } + extern(C) pragma(mangle, "__fpclassify") int fpclassify(double x); /// - int fpclassify(real x) - { - return (real.sizeof == double.sizeof) - ? __fpclassify(x) - : __fpclassifyl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl") + int fpclassify(real x); private uint __FLOAT_BITS(float __f) { union __u_t { @@ -765,16 +816,12 @@ else version (CRuntime_Musl) //int signbit(real-floating x); /// - int signbit(float x) { return __signbitf(x); } + extern(C) pragma(mangle, "__signbitf") int signbit(float x); /// - int signbit(double x) { return __signbit(x); } + extern(C) pragma(mangle, "__signbit") int signbit(double x); /// - int signbit(real x) - { - return (real.sizeof == double.sizeof) - ? __signbit(x) - : __signbitl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl") + int signbit(real x); } } else version (CRuntime_UClibc) @@ -826,146 +873,37 @@ else version (CRuntime_UClibc) extern (D) { /// - int fpclassify(float x) { return __fpclassifyf(x); } - /// - int fpclassify(double x) { return __fpclassify(x); } - /// - int fpclassify(real x) - { - return (real.sizeof == double.sizeof) - ? __fpclassify(x) - : __fpclassifyl(x); - } - - /// - int isfinite(float x) { return __finitef(x); } - /// - int isfinite(double x) { return __finite(x); } - /// - int isfinite(real x) - { - return (real.sizeof == double.sizeof) - ? __finite(x) - : __finitel(x); - } - - /// - int isinf(float x) { return __isinff(x); } - /// - int isinf(double x) { return __isinf(x); } - /// - int isinf(real x) - { - return (real.sizeof == double.sizeof) - ? __isinf(x) - : __isinfl(x); - } - - /// - int isnan(float x) { return __isnanf(x); } - /// - int isnan(double x) { return __isnan(x); } - /// - int isnan(real x) - { - return (real.sizeof == double.sizeof) - ? __isnan(x) - : __isnanl(x); - } - - /// - int isnormal(float x) { return fpclassify(x) == FP_NORMAL; } - /// - int isnormal(double x) { return fpclassify(x) == FP_NORMAL; } - /// - int isnormal(real x) { return fpclassify(x) == FP_NORMAL; } - - /// - int signbit(float x) { return __signbitf(x); } - /// - int signbit(double x) { return __signbit(x); } - /// - int signbit(real x) - { - return (real.sizeof == double.sizeof) - ? __signbit(x) - : __signbitl(x); - } - } -} -else version (MinGW) -{ - enum - { - /// - FP_NAN = 0x0100, - /// - FP_NORMAL = 0x0400, - /// - FP_INFINITE = FP_NAN | FP_NORMAL, - /// - FP_ZERO = 0x0400, - /// - FP_SUBNORMAL = FP_NORMAL | FP_ZERO - } - - pure int __fpclassifyf(float x); - pure int __fpclassify(double x); - pure int __fpclassifyl(real x); - - pure int __isnanf(float x); - pure int __isnan(double x); - pure int __isnanl(real x); - - pure int __signbitf(float x); - pure int __signbit(double x); - pure int __signbitl(real x); - - extern (D) - { - //int fpclassify(real-floating x); - /// - pure int fpclassify(float x) { return __fpclassifyf(x); } + extern(C) pragma(mangle, "__fpclassifyf") int fpclassify(float x); /// - pure int fpclassify(double x) { return __fpclassify(x); } + extern(C) pragma(mangle, "__fpclassify") int fpclassify(double x); /// - pure int fpclassify(real x) - { - return (real.sizeof == double.sizeof) - ? __fpclassify(x) - : __fpclassifyl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassify" : "__fpclassifyl") + int fpclassify(real x); - //int isfinite(real-floating x); /// - pure int isfinite(float x) { return (fpclassify(x) & FP_NORMAL) == 0; } + extern(C) pragma(mangle, "__finitef") int isfinite(float x); /// - pure int isfinite(double x) { return (fpclassify(x) & FP_NORMAL) == 0; } + extern(C) pragma(mangle, "__finite") int isfinite(double x); /// - pure int isfinite(real x) { return (fpclassify(x) & FP_NORMAL) == 0; } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__finite" : "__finitel") + int isfinite(real x); - //int isinf(real-floating x); /// - pure int isinf(float x) { return fpclassify(x) == FP_INFINITE; } + extern(C) pragma(mangle, "__isinff") int isinf(float x); /// - pure int isinf(double x) { return fpclassify(x) == FP_INFINITE; } + extern(C) pragma(mangle, "__isinf") int isinf(double x); /// - pure int isinf(real x) { return fpclassify(x) == FP_INFINITE; } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isinf" : "__isinfl") + int isinf(real x); - //int isnan(real-floating x); /// - pure int isnan(float x) { return __isnanf(x); } + extern(C) pragma(mangle, "__isnanf") int isnan(float x); /// - pure int isnan(double x) { return __isnan(x); } + extern(C) pragma(mangle, "__isnan") int isnan(double x); /// - pure int isnan(real x) - { - return (real.sizeof == double.sizeof) - ? __isnan(x) - : __isnanl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl") + int isnan(real x); - //int isnormal(real-floating x); /// int isnormal(float x) { return fpclassify(x) == FP_NORMAL; } /// @@ -973,18 +911,13 @@ else version (MinGW) /// int isnormal(real x) { return fpclassify(x) == FP_NORMAL; } - //int signbit(real-floating x); /// - int signbit(float x) { return __signbitf(x); } + extern(C) pragma(mangle, "__signbitf") int signbit(float x); /// - int signbit(double x) { return __signbit(x); } + extern(C) pragma(mangle, "__signbit") int signbit(double x); /// - int signbit(real x) - { - return (real.sizeof == double.sizeof) - ? __signbit(x) - : __signbitl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__signbit" : "__signbitl") + int signbit(real x); } } else version (Darwin) @@ -1070,35 +1003,35 @@ else version (Darwin) { //int fpclassify(real-floating x); /// - pure int fpclassify(float x) { return __fpclassifyf(x); } + extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x); /// - pure int fpclassify(double x) { return __fpclassifyd(x); } + extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x); /// - pure int fpclassify(real x) { return __fpclassifyl(x); } + extern(C) pragma(mangle, __fpclassifyl.mangleof) pure int fpclassify(real x); //int isfinite(real-floating x); /// - pure int isfinite(float x) { return __isfinitef(x); } + extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x); /// - pure int isfinite(double x) { return __isfinited(x); } + extern(C) pragma(mangle, "__isfinited") pure int isfinite(double x); /// - pure int isfinite(real x) { return __isfinitel(x); } + extern(C) pragma(mangle, __isfinitel.mangleof) pure int isfinite(real x); //int isinf(real-floating x); /// - pure int isinf(float x) { return __isinff(x); } + extern(C) pragma(mangle, "__isinff") pure int isinf(float x); /// - pure int isinf(double x) { return __isinfd(x); } + extern(C) pragma(mangle, "__isinfd") pure int isinf(double x); /// - pure int isinf(real x) { return __isinfl(x); } + extern(C) pragma(mangle, __isinfl.mangleof) pure int isinf(real x); //int isnan(real-floating x); /// - pure int isnan(float x) { return __isnanf(x); } + extern(C) pragma(mangle, "__isnanf") pure int isnan(float x); /// - pure int isnan(double x) { return __isnand(x); } + extern(C) pragma(mangle, "__isnand") pure int isnan(double x); /// - pure int isnan(real x) { return __isnanl(x); } + extern(C) pragma(mangle, __isnanl.mangleof) pure int isnan(real x); //int isnormal(real-floating x); /// @@ -1110,11 +1043,11 @@ else version (Darwin) //int signbit(real-floating x); /// - pure int signbit(float x) { return __signbitf(x); } + extern(C) pragma(mangle, "__signbitf") pure int signbit(float x); /// - pure int signbit(double x) { return __signbitd(x); } + extern(C) pragma(mangle, "__signbitd") pure int signbit(double x); /// - pure int signbit(real x) { return __signbitl(x); } + extern(C) pragma(mangle, "__signbitl") pure int signbit(real x); } } else version (FreeBSD) @@ -1163,27 +1096,27 @@ else version (FreeBSD) { //int fpclassify(real-floating x); /// - pure int fpclassify(float x) { return __fpclassifyf(x); } + extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x); /// - pure int fpclassify(double x) { return __fpclassifyd(x); } + extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x); /// - pure int fpclassify(real x) { return __fpclassifyl(x); } + extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x); //int isfinite(real-floating x); /// - pure int isfinite(float x) { return __isfinitef(x); } + extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x); /// - pure int isfinite(double x) { return __isfinite(x); } + extern(C) pragma(mangle, "__isfinite") pure int isfinite(double x); /// - pure int isfinite(real x) { return __isfinitel(x); } + extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x); //int isinf(real-floating x); /// - pure int isinf(float x) { return __isinff(x); } + extern(C) pragma(mangle, "__isinff") pure int isinf(float x); /// pure int isinf(double x) { return __isinfl(x); } /// - pure int isinf(real x) { return __isinfl(x); } + extern(C) pragma(mangle, "__isinfl") pure int isinf(real x); //int isnan(real-floating x); /// @@ -1191,21 +1124,21 @@ else version (FreeBSD) /// pure int isnan(double x) { return __isnanl(x); } /// - pure int isnan(real x) { return __isnanl(x); } + extern(C) pragma(mangle, "__isnanl") pure int isnan(real x); //int isnormal(real-floating x); /// - pure int isnormal(float x) { return __isnormalf(x); } + extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x); /// - pure int isnormal(double x) { return __isnormal(x); } + extern(C) pragma(mangle, "__isnormal") pure int isnormal(double x); /// - pure int isnormal(real x) { return __isnormall(x); } + extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x); //int signbit(real-floating x); /// - pure int signbit(float x) { return __signbitf(x); } + extern(C) pragma(mangle, "__signbitf") pure int signbit(float x); /// - pure int signbit(double x) { return __signbit(x); } + extern(C) pragma(mangle, "__signbit") pure int signbit(double x); /// pure int signbit(real x) { return __signbit(x); } } @@ -1236,7 +1169,7 @@ else version (OpenBSD) FP_FAST_FMAL = 1, } - pure int __fpclassifyd(double); + pure int __fpclassify(double); pure int __fpclassifyf(float); pure int __fpclassifyl(real); pure int __isfinitef(float); @@ -1256,27 +1189,27 @@ else version (OpenBSD) { //int fpclassify(real-floating x); /// - pure int fpclassify(float x) { return __fpclassifyf(x); } + extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x); /// - pure int fpclassify(double x) { return __fpclassifyd(x); } + extern(C) pragma(mangle, "__fpclassify") pure int fpclassify(double x); /// - pure int fpclassify(real x) { return __fpclassifyl(x); } + extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x); //int isfinite(real-floating x); /// - pure int isfinite(float x) { return __isfinitef(x); } + extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x); /// - pure int isfinite(double x) { return __isfinite(x); } + extern(C) pragma(mangle, "__isfinite") pure int isfinite(double x); /// - pure int isfinite(real x) { return __isfinitel(x); } + extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x); //int isinf(real-floating x); /// - pure int isinf(float x) { return __isinff(x); } + extern(C) pragma(mangle, "__isinff") pure int isinf(float x); /// pure int isinf(double x) { return __isinfl(x); } /// - pure int isinf(real x) { return __isinfl(x); } + extern(C) pragma(mangle, "__isinfl") pure int isinf(real x); //int isnan(real-floating x); /// @@ -1284,21 +1217,21 @@ else version (OpenBSD) /// pure int isnan(double x) { return __isnanl(x); } /// - pure int isnan(real x) { return __isnanl(x); } + extern(C) pragma(mangle, "__isnanl") pure int isnan(real x); //int isnormal(real-floating x); /// - pure int isnormal(float x) { return __isnormalf(x); } + extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x); /// - pure int isnormal(double x) { return __isnormal(x); } + extern(C) pragma(mangle, "__isnormal") pure int isnormal(double x); /// - pure int isnormal(real x) { return __isnormall(x); } + extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x); //int signbit(real-floating x); /// - pure int signbit(float x) { return __signbitf(x); } + extern(C) pragma(mangle, "__signbitf") pure int signbit(float x); /// - pure int signbit(double x) { return __signbit(x); } + extern(C) pragma(mangle, "__signbit") pure int signbit(double x); /// pure int signbit(real x) { return __signbit(x); } } @@ -1337,16 +1270,12 @@ else version (NetBSD) { //int fpclassify(real-floating x); /// - pure int fpclassify(float x) { return __fpclassifyf(x); } + extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x); /// - pure int fpclassify(double x) { return __fpclassifyd(x); } + extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x); /// - pure int fpclassify(real x) - { - return (real.sizeof == double.sizeof) - ? __fpclassifyd(x) - : __fpclassifyl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__fpclassifyd" : "__fpclassifyl") + pure int fpclassify(real x); //int isfinite(real-floating x); /// @@ -1433,29 +1362,29 @@ else version (DragonFlyBSD) extern (D) { - pure int fpclassify(float x) { return __fpclassifyf(x); } - pure int fpclassify(double x) { return __fpclassifyd(x); } - pure int fpclassify(real x) { return __fpclassifyl(x); } + extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x); + extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x); + extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x); - pure int isfinite(float x) { return __isfinitef(x); } - pure int isfinite(double x) { return __isfinite(x); } - pure int isfinite(real x) { return __isfinitel(x); } + extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x); + extern(C) pragma(mangle, "__isfinite") pure int isfinite(double x); + extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x); - pure int isinf(float x) { return __isinff(x); } - pure int isinf(double x) { return __isinf(x); } - pure int isinf(real x) { return __isinfl(x); } + extern(C) pragma(mangle, "__isinff") pure int isinf(float x); + extern(C) pragma(mangle, "__isinf") pure int isinf(double x); + extern(C) pragma(mangle, "__isinfl") pure int isinf(real x); - pure int isnan(float x) { return __isnanf(x); } - pure int isnan(double x) { return __isnan(x); } - pure int isnan(real x) { return __isnanl(x); } + extern(C) pragma(mangle, "__isnanf") pure int isnan(float x); + extern(C) pragma(mangle, "__isnan") pure int isnan(double x); + extern(C) pragma(mangle, "__isnanl") pure int isnan(real x); - pure int isnormal(float x) { return __isnormalf(x); } - pure int isnormal(double x) { return __isnormal(x); } - pure int isnormal(real x) { return __isnormall(x); } + extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x); + extern(C) pragma(mangle, "__isnormal") pure int isnormal(double x); + extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x); - pure int signbit(float x) { return __signbitf(x); } - pure int signbit(double x) { return __signbit(x); } - pure int signbit(real x) { return __signbitl(x); } + extern(C) pragma(mangle, "__signbitf") pure int signbit(float x); + extern(C) pragma(mangle, "__signbit") pure int signbit(double x); + extern(C) pragma(mangle, "__signbitl") pure int signbit(real x); } } else version (Solaris) @@ -1468,16 +1397,12 @@ else version (Solaris) { //int isnan(real-floating x); /// - pure int isnan(float x) { return __isnanf(x); } + extern(C) pragma(mangle, "__isnanf") pure int isnan(float x); /// - pure int isnan(double x) { return __isnan(x); } + extern(C) pragma(mangle, "__isnan") pure int isnan(double x); /// - pure int isnan(real x) - { - return (real.sizeof == double.sizeof) - ? __isnan(x) - : __isnanl(x); - } + extern(C) pragma(mangle, real.sizeof == double.sizeof ? "__isnan" : "__isnanl") + pure int isnan(real x); } } else version (CRuntime_Bionic) @@ -1527,49 +1452,49 @@ else version (CRuntime_Bionic) { //int fpclassify(real-floating x); /// - pure int fpclassify(float x) { return __fpclassifyf(x); } + extern(C) pragma(mangle, "__fpclassifyf") pure int fpclassify(float x); /// - pure int fpclassify(double x) { return __fpclassifyd(x); } + extern(C) pragma(mangle, "__fpclassifyd") pure int fpclassify(double x); /// - pure int fpclassify(real x) { return __fpclassifyl(x); } + extern(C) pragma(mangle, "__fpclassifyl") pure int fpclassify(real x); //int isfinite(real-floating x); /// - pure int isfinite(float x) { return __isfinitef(x); } + extern(C) pragma(mangle, "__isfinitef") pure int isfinite(float x); /// - pure int isfinite(double x) { return __isfinite(x); } + extern(C) pragma(mangle, "__isfinite") pure int isfinite(double x); /// - pure int isfinite(real x) { return __isfinitel(x); } + extern(C) pragma(mangle, "__isfinitel") pure int isfinite(real x); //int isinf(real-floating x); /// - pure int isinf(float x) { return __isinff(x); } + extern(C) pragma(mangle, "__isinff") pure int isinf(float x); /// - pure int isinf(double x) { return __isinf(x); } + extern(C) pragma(mangle, "__isinf") pure int isinf(double x); /// - pure int isinf(real x) { return __isinfl(x); } + extern(C) pragma(mangle, "__isinfl") pure int isinf(real x); //int isnan(real-floating x); /// - pure int isnan(float x) { return isnanf(x); } + extern(C) pragma(mangle, "isnanf") pure int isnan(float x); /// - pure int isnan(real x) { return __isnanl(x); } + extern(C) pragma(mangle, "__isnanl") pure int isnan(real x); //int isnormal(real-floating x); /// - pure int isnormal(float x) { return __isnormalf(x); } + extern(C) pragma(mangle, "__isnormalf") pure int isnormal(float x); /// - pure int isnormal(double x) { return __isnormal(x); } + extern(C) pragma(mangle, "__isnormal") pure int isnormal(double x); /// - pure int isnormal(real x) { return __isnormall(x); } + extern(C) pragma(mangle, "__isnormall") pure int isnormal(real x); //int signbit(real-floating x); /// - pure int signbit(float x) { return __signbitf(x); } + extern(C) pragma(mangle, "__signbitf") pure int signbit(float x); /// - pure int signbit(double x) { return __signbit(x); } + extern(C) pragma(mangle, "__signbit") pure int signbit(double x); /// - pure int signbit(real x) { return __signbitl(x); } + extern(C) pragma(mangle, "__signbitl") pure int signbit(real x); } } @@ -1841,14 +1766,12 @@ version (CRuntime_Microsoft) // fully supported since MSVCRT 12 (VS 2013) only /// extern(D) pure real fabsl()(real x) { return fabs(cast(double) x); } - private double _hypot(double x, double y); - private float _hypotf(float x, float y); /// - extern(D) double hypot(double x, double y) { return _hypot(x, y); } + extern(C) pragma(mangle, "_hypot") double hypot(double x, double y); /// - extern(D) float hypotf(float x, float y) { return _hypotf(x, y); } + extern(C) pragma(mangle, "_hypotf") float hypotf(float x, float y); /// - extern(D) real hypotl(real x, real y) { return _hypot(cast(double) x, cast(double) y); } + extern(D) real hypotl(real x, real y) { return hypot(cast(double) x, cast(double) y); } /// double pow(double x, double y); diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d index 6701159..c76b922 100644 --- a/libphobos/libdruntime/core/stdc/stdio.d +++ b/libphobos/libdruntime/core/stdc/stdio.d @@ -1166,61 +1166,73 @@ version (MinGW) // Prefer the MinGW versions over the MSVC ones, as the latter don't handle // reals at all. /// + pragma(printf) int __mingw_fprintf(FILE* stream, scope const char* format, scope const ...); /// alias __mingw_fprintf fprintf; /// + pragma(scanf) int __mingw_fscanf(FILE* stream, scope const char* format, scope ...); /// alias __mingw_fscanf fscanf; /// + pragma(printf) int __mingw_sprintf(scope char* s, scope const char* format, scope const ...); /// alias __mingw_sprintf sprintf; /// + pragma(scanf) int __mingw_sscanf(scope const char* s, scope const char* format, scope ...); /// alias __mingw_sscanf sscanf; /// + pragma(printf) int __mingw_vfprintf(FILE* stream, scope const char* format, va_list arg); /// alias __mingw_vfprintf vfprintf; /// + pragma(scanf) int __mingw_vfscanf(FILE* stream, scope const char* format, va_list arg); /// alias __mingw_vfscanf vfscanf; /// + pragma(printf) int __mingw_vsprintf(scope char* s, scope const char* format, va_list arg); /// alias __mingw_vsprintf vsprintf; /// + pragma(scanf) int __mingw_vsscanf(scope const char* s, scope const char* format, va_list arg); /// alias __mingw_vsscanf vsscanf; /// + pragma(printf) int __mingw_vprintf(scope const char* format, va_list arg); /// alias __mingw_vprintf vprintf; /// + pragma(scanf) int __mingw_vscanf(scope const char* format, va_list arg); /// alias __mingw_vscanf vscanf; /// + pragma(printf) int __mingw_printf(scope const char* format, scope const ...); /// alias __mingw_printf printf; /// + pragma(scanf) int __mingw_scanf(scope const char* format, scope ...); /// alias __mingw_scanf scanf; @@ -1228,28 +1240,40 @@ version (MinGW) else { /// + pragma(printf) int fprintf(FILE* stream, scope const char* format, scope const ...); /// + pragma(scanf) int fscanf(FILE* stream, scope const char* format, scope ...); /// + pragma(printf) int sprintf(scope char* s, scope const char* format, scope const ...); /// + pragma(scanf) int sscanf(scope const char* s, scope const char* format, scope ...); /// + pragma(printf) int vfprintf(FILE* stream, scope const char* format, va_list arg); /// + pragma(scanf) int vfscanf(FILE* stream, scope const char* format, va_list arg); /// + pragma(printf) int vsprintf(scope char* s, scope const char* format, va_list arg); /// + pragma(scanf) int vsscanf(scope const char* s, scope const char* format, va_list arg); /// + pragma(printf) int vprintf(scope const char* format, va_list arg); /// + pragma(scanf) int vscanf(scope const char* format, va_list arg); /// + pragma(printf) int printf(scope const char* format, scope const ...); /// + pragma(scanf) int scanf(scope const char* format, scope ...); } @@ -1278,13 +1302,14 @@ extern (D) @trusted int getchar()() { return getc(stdin); } /// int putchar()(int c) { return putc(c,stdout); } - /// - int getc()(FILE* stream) { return fgetc(stream); } - /// - int putc()(int c, FILE* stream) { return fputc(c,stream); } } /// +alias getc = fgetc; +/// +alias putc = fputc; + +/// @trusted int ungetc(int c, FILE* stream); // No unsafe pointer manipulation. /// @@ -1322,15 +1347,37 @@ version (CRuntime_DigitalMars) /// pure int fileno()(FILE* stream) { return stream._file; } } - /// + /// + pragma(printf) int _snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...); /// alias _snprintf snprintf; /// + pragma(printf) int _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); /// alias _vsnprintf vsnprintf; + + // + // Digital Mars under-the-hood C I/O functions. Uses _iobuf* for the + // unshared version of FILE*, usable when the FILE is locked. + // + + /// + int _fputc_nlock(int c, _iobuf* fp); + /// + int _fputwc_nlock(int c, _iobuf* fp); + /// + int _fgetc_nlock(_iobuf* fp); + /// + int _fgetwc_nlock(_iobuf* fp); + /// + int __fp_lock(FILE* fp); + /// + void __fp_unlock(FILE* fp); + /// + int setmode(int fd, int mode); } else version (CRuntime_Microsoft) { @@ -1351,6 +1398,7 @@ else version (CRuntime_Microsoft) version (MinGW) { + pragma(printf) int __mingw_snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...); /// alias __mingw_snprintf _snprintf; @@ -1358,6 +1406,7 @@ else version (CRuntime_Microsoft) alias __mingw_snprintf snprintf; /// + pragma(printf) int __mingw_vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); /// alias __mingw_vsnprintf _vsnprintf; @@ -1367,26 +1416,45 @@ else version (CRuntime_Microsoft) else { /// + pragma(printf) int _snprintf(scope char* s, size_t n, scope const char* format, scope const ...); /// + 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); /// + pragma(printf) int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } + // + // Microsoft under-the-hood C I/O functions. Uses _iobuf* for the unshared + // version of FILE*, usable when the FILE is locked. + // + import core.stdc.stddef : wchar_t; + import core.stdc.wchar_ : wint_t; + /// - int _fputc_nolock(int c, FILE *fp); + int _fputc_nolock(int c, _iobuf* fp); /// - int _fgetc_nolock(FILE *fp); - + int _fgetc_nolock(_iobuf* fp); /// - int _lock_file(FILE *fp); + wint_t _fputwc_nolock(wchar_t c, _iobuf* fp); /// - int _unlock_file(FILE *fp); - + wint_t _fgetwc_nolock(_iobuf* fp); + /// + void _lock_file(FILE* fp); + /// + void _unlock_file(FILE* fp); + /// + int _setmode(int fd, int mode); + /// + int _fseeki64(FILE* stream, long offset, int origin); + /// + long _ftelli64(FILE* stream); /// intptr_t _get_osfhandle(int fd); /// @@ -1410,9 +1478,28 @@ else version (CRuntime_Glibc) } /// + 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 (Darwin) { @@ -1432,8 +1519,10 @@ else version (Darwin) } /// + 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); } else version (FreeBSD) @@ -1454,8 +1543,10 @@ else version (FreeBSD) } /// + 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); } else version (NetBSD) @@ -1476,8 +1567,10 @@ else version (NetBSD) } /// + pragma(printf) int snprintf(char* s, size_t n, const scope char* format, scope const ...); /// + pragma(printf) int vsnprintf(char* s, size_t n, const scope char* format, va_list arg); } else version (OpenBSD) @@ -1567,8 +1660,10 @@ else version (OpenBSD) } /// + 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); } else version (DragonFlyBSD) @@ -1599,7 +1694,9 @@ else version (DragonFlyBSD) enum __SALC = 0x4000; enum __SIGN = 0x8000; + 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); } else version (Solaris) @@ -1620,8 +1717,10 @@ else version (Solaris) } /// + 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); } else version (CRuntime_Bionic) @@ -1642,8 +1741,10 @@ else version (CRuntime_Bionic) } /// + 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); } else version (CRuntime_Musl) @@ -1663,8 +1764,10 @@ else version (CRuntime_Musl) } /// + 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); } else version (CRuntime_UClibc) @@ -1685,8 +1788,10 @@ else version (CRuntime_UClibc) } /// + 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); } else @@ -1854,6 +1959,22 @@ version (Windows) O_TEXT = _O_TEXT, /// _O_BINARY = 0x8000, /// O_BINARY = _O_BINARY, /// + _O_WTEXT = 0x10000, /// + _O_U16TEXT = 0x20000, /// + _O_U8TEXT = 0x40000, /// + _O_ACCMODE = (_O_RDONLY|_O_WRONLY|_O_RDWR), /// + O_ACCMODE = _O_ACCMODE, /// + _O_RAW = _O_BINARY, /// + O_RAW = _O_BINARY, /// + _O_NOINHERIT = 0x0080, /// + O_NOINHERIT = _O_NOINHERIT, /// + _O_TEMPORARY = 0x0040, /// + O_TEMPORARY = _O_TEMPORARY, /// + _O_SHORT_LIVED = 0x1000, /// + _O_SEQUENTIAL = 0x0020, /// + O_SEQUENTIAL = _O_SEQUENTIAL, /// + _O_RANDOM = 0x0010, /// + O_RANDOM = _O_RANDOM, /// } enum diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d index 7caef4c..35e81a2 100644 --- a/libphobos/libdruntime/core/stdc/stdlib.d +++ b/libphobos/libdruntime/core/stdc/stdlib.d @@ -121,19 +121,22 @@ ulong strtoull(scope inout(char)* nptr, scope inout(char)** endptr, int base); version (CRuntime_Microsoft) { - // strtold exists starting from VS2013, so we give it D linkage to avoid link errors - /// - extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr) - { // Fake it 'till we make it - return strtod(nptr, endptr); + version (MinGW) + { + /// + real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr); + /// + alias __mingw_strtold strtold; + } + else + { + // strtold exists starting from VS2013, so we give it D linkage to avoid link errors + /// + extern (D) real strtold(scope inout(char)* nptr, inout(char)** endptr) + { // Fake it 'till we make it + return strtod(nptr, endptr); + } } -} -else version (MinGW) -{ - /// - real __mingw_strtold(scope inout(char)* nptr, scope inout(char)** endptr); - /// - alias __mingw_strtold strtold; } else { @@ -164,13 +167,13 @@ void* realloc(void* ptr, size_t size); void free(void* ptr); /// -void abort() @safe; +noreturn abort() @safe; /// -void exit(int status); +noreturn exit(int status); /// int atexit(void function() func); /// -void _Exit(int status); +noreturn _Exit(int status); /// char* getenv(scope const char* name); diff --git a/libphobos/libdruntime/core/stdc/tgmath.d b/libphobos/libdruntime/core/stdc/tgmath.d index 4dd1b3c..2d1a198 100644 --- a/libphobos/libdruntime/core/stdc/tgmath.d +++ b/libphobos/libdruntime/core/stdc/tgmath.d @@ -32,12 +32,10 @@ version (NetBSD) /// alias core.stdc.math.acosl acos; - /// - alias core.stdc.complex.cacos acos; - /// - alias core.stdc.complex.cacosf acos; - /// - alias core.stdc.complex.cacosl acos; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cacos acos; + deprecated alias core.stdc.complex.cacosf acos; + deprecated alias core.stdc.complex.cacosl acos; /// alias core.stdc.math.asin asin; @@ -46,12 +44,10 @@ version (NetBSD) /// alias core.stdc.math.asinl asin; - /// - alias core.stdc.complex.casin asin; - /// - alias core.stdc.complex.casinf asin; - /// - alias core.stdc.complex.casinl asin; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.casin asin; + deprecated alias core.stdc.complex.casinf asin; + deprecated alias core.stdc.complex.casinl asin; /// alias core.stdc.math.atan atan; @@ -60,12 +56,10 @@ version (NetBSD) /// alias core.stdc.math.atanl atan; - /// - alias core.stdc.complex.catan atan; - /// - alias core.stdc.complex.catanf atan; - /// - alias core.stdc.complex.catanl atan; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.catan atan; + deprecated alias core.stdc.complex.catanf atan; + deprecated alias core.stdc.complex.catanl atan; /// alias core.stdc.math.atan2 atan2; @@ -81,12 +75,10 @@ version (NetBSD) /// alias core.stdc.math.cosl cos; - /// - alias core.stdc.complex.ccos cos; - /// - alias core.stdc.complex.ccosf cos; - /// - alias core.stdc.complex.ccosl cos; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ccos cos; + deprecated alias core.stdc.complex.ccosf cos; + deprecated alias core.stdc.complex.ccosl cos; /// alias core.stdc.math.sin sin; @@ -95,12 +87,10 @@ version (NetBSD) /// alias core.stdc.math.sinl sin; - /// - alias core.stdc.complex.csin csin; - /// - alias core.stdc.complex.csinf csin; - /// - alias core.stdc.complex.csinl csin; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csin csin; + deprecated alias core.stdc.complex.csinf csin; + deprecated alias core.stdc.complex.csinl csin; /// alias core.stdc.math.tan tan; @@ -109,12 +99,10 @@ version (NetBSD) /// alias core.stdc.math.tanl tan; - /// - alias core.stdc.complex.ctan tan; - /// - alias core.stdc.complex.ctanf tan; - /// - alias core.stdc.complex.ctanl tan; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ctan tan; + deprecated alias core.stdc.complex.ctanf tan; + deprecated alias core.stdc.complex.ctanl tan; /// alias core.stdc.math.acosh acosh; @@ -123,12 +111,10 @@ version (NetBSD) /// alias core.stdc.math.acoshl acosh; - /// - alias core.stdc.complex.cacosh acosh; - /// - alias core.stdc.complex.cacoshf acosh; - /// - alias core.stdc.complex.cacoshl acosh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cacosh acosh; + deprecated alias core.stdc.complex.cacoshf acosh; + deprecated alias core.stdc.complex.cacoshl acosh; /// alias core.stdc.math.asinh asinh; @@ -137,12 +123,10 @@ version (NetBSD) /// alias core.stdc.math.asinhl asinh; - /// - alias core.stdc.complex.casinh asinh; - /// - alias core.stdc.complex.casinhf asinh; - /// - alias core.stdc.complex.casinhl asinh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.casinh asinh; + deprecated alias core.stdc.complex.casinhf asinh; + deprecated alias core.stdc.complex.casinhl asinh; /// alias core.stdc.math.atanh atanh; @@ -151,12 +135,10 @@ version (NetBSD) /// alias core.stdc.math.atanhl atanh; - /// - alias core.stdc.complex.catanh atanh; - /// - alias core.stdc.complex.catanhf atanh; - /// - alias core.stdc.complex.catanhl atanh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.catanh atanh; + deprecated alias core.stdc.complex.catanhf atanh; + deprecated alias core.stdc.complex.catanhl atanh; /// alias core.stdc.math.cosh cosh; @@ -165,12 +147,10 @@ version (NetBSD) /// alias core.stdc.math.coshl cosh; - /// - alias core.stdc.complex.ccosh cosh; - /// - alias core.stdc.complex.ccoshf cosh; - /// - alias core.stdc.complex.ccoshl cosh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ccosh cosh; + deprecated alias core.stdc.complex.ccoshf cosh; + deprecated alias core.stdc.complex.ccoshl cosh; /// alias core.stdc.math.sinh sinh; @@ -179,12 +159,10 @@ version (NetBSD) /// alias core.stdc.math.sinhl sinh; - /// - alias core.stdc.complex.csinh sinh; - /// - alias core.stdc.complex.csinhf sinh; - /// - alias core.stdc.complex.csinhl sinh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csinh sinh; + deprecated alias core.stdc.complex.csinhf sinh; + deprecated alias core.stdc.complex.csinhl sinh; /// alias core.stdc.math.tanh tanh; @@ -193,12 +171,10 @@ version (NetBSD) /// alias core.stdc.math.tanhl tanh; - /// - alias core.stdc.complex.ctanh tanh; - /// - alias core.stdc.complex.ctanhf tanh; - /// - alias core.stdc.complex.ctanhl tanh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ctanh tanh; + deprecated alias core.stdc.complex.ctanhf tanh; + deprecated alias core.stdc.complex.ctanhl tanh; /// alias core.stdc.math.exp exp; @@ -207,12 +183,10 @@ version (NetBSD) /// alias core.stdc.math.expl exp; - /// - alias core.stdc.complex.cexp exp; - /// - alias core.stdc.complex.cexpf exp; - /// - alias core.stdc.complex.cexpl exp; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cexp exp; + deprecated alias core.stdc.complex.cexpf exp; + deprecated alias core.stdc.complex.cexpl exp; /// alias core.stdc.math.exp2 exp2; @@ -256,12 +230,10 @@ version (NetBSD) /// alias core.stdc.math.logl log; - /// - alias core.stdc.complex.clog log; - /// - alias core.stdc.complex.clogf log; - /// - alias core.stdc.complex.clogl log; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.clog log; + deprecated alias core.stdc.complex.clogf log; + deprecated alias core.stdc.complex.clogl log; /// alias core.stdc.math.log10 log10; @@ -325,12 +297,10 @@ version (NetBSD) /// alias core.stdc.math.fabsl fabs; - /// - alias core.stdc.complex.cabs fabs; - /// - alias core.stdc.complex.cabsf fabs; - /// - alias core.stdc.complex.cabsl fabs; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cabs fabs; + deprecated alias core.stdc.complex.cabsf fabs; + deprecated alias core.stdc.complex.cabsl fabs; /// alias core.stdc.math.hypot hypot; @@ -346,12 +316,10 @@ version (NetBSD) /// alias core.stdc.math.powl pow; - /// - alias core.stdc.complex.cpow pow; - /// - alias core.stdc.complex.cpowf pow; - /// - alias core.stdc.complex.cpowl pow; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cpow pow; + deprecated alias core.stdc.complex.cpowf pow; + deprecated alias core.stdc.complex.cpowl pow; /// alias core.stdc.math.sqrt sqrt; @@ -360,12 +328,10 @@ version (NetBSD) /// alias core.stdc.math.sqrtl sqrt; - /// - alias core.stdc.complex.csqrt sqrt; - /// - alias core.stdc.complex.csqrtf sqrt; - /// - alias core.stdc.complex.csqrtl sqrt; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csqrt sqrt; + deprecated alias core.stdc.complex.csqrtf sqrt; + deprecated alias core.stdc.complex.csqrtl sqrt; /// alias core.stdc.math.erf erf; @@ -539,37 +505,23 @@ version (NetBSD) /// alias core.stdc.math.fmal fma; - /// - alias core.stdc.complex.carg carg; - /// - alias core.stdc.complex.cargf carg; - /// - alias core.stdc.complex.cargl carg; - - /// - alias core.stdc.complex.cimag cimag; - /// - alias core.stdc.complex.cimagf cimag; - /// - alias core.stdc.complex.cimagl cimag; - - /// - alias core.stdc.complex.conj conj; - /// - alias core.stdc.complex.conjf conj; - /// - alias core.stdc.complex.conjl conj; - - /// - alias core.stdc.complex.cproj cproj; - /// - alias core.stdc.complex.cprojf cproj; - /// - alias core.stdc.complex.cprojl cproj; - -// alias core.stdc.complex.creal creal; -// alias core.stdc.complex.crealf creal; -// alias core.stdc.complex.creall creal; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.carg carg; + deprecated alias core.stdc.complex.cargf carg; + deprecated alias core.stdc.complex.cargl carg; + deprecated alias core.stdc.complex.cimag cimag; + deprecated alias core.stdc.complex.cimagf cimag; + deprecated alias core.stdc.complex.cimagl cimag; + deprecated alias core.stdc.complex.conj conj; + deprecated alias core.stdc.complex.conjf conj; + deprecated alias core.stdc.complex.conjl conj; + deprecated alias core.stdc.complex.cproj cproj; + deprecated alias core.stdc.complex.cprojf cproj; + deprecated alias core.stdc.complex.cprojl cproj; + +// deprecated alias core.stdc.complex.creal creal; +// deprecated alias core.stdc.complex.crealf creal; +// deprecated alias core.stdc.complex.creall creal; } else version (OpenBSD) { @@ -580,12 +532,10 @@ else version (OpenBSD) /// alias core.stdc.math.acosl acos; - /// - alias core.stdc.complex.cacos acos; - /// - alias core.stdc.complex.cacosf acos; - /// - alias core.stdc.complex.cacosl acos; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cacos acos; + deprecated alias core.stdc.complex.cacosf acos; + deprecated alias core.stdc.complex.cacosl acos; /// alias core.stdc.math.asin asin; @@ -594,12 +544,10 @@ else version (OpenBSD) /// alias core.stdc.math.asinl asin; - /// - alias core.stdc.complex.casin asin; - /// - alias core.stdc.complex.casinf asin; - /// - alias core.stdc.complex.casinl asin; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.casin asin; + deprecated alias core.stdc.complex.casinf asin; + deprecated alias core.stdc.complex.casinl asin; /// alias core.stdc.math.atan atan; @@ -608,12 +556,10 @@ else version (OpenBSD) /// alias core.stdc.math.atanl atan; - /// - alias core.stdc.complex.catan atan; - /// - alias core.stdc.complex.catanf atan; - /// - alias core.stdc.complex.catanl atan; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.catan atan; + deprecated alias core.stdc.complex.catanf atan; + deprecated alias core.stdc.complex.catanl atan; /// alias core.stdc.math.atan2 atan2; @@ -629,12 +575,10 @@ else version (OpenBSD) /// alias core.stdc.math.cosl cos; - /// - alias core.stdc.complex.ccos cos; - /// - alias core.stdc.complex.ccosf cos; - /// - alias core.stdc.complex.ccosl cos; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ccos cos; + deprecated alias core.stdc.complex.ccosf cos; + deprecated alias core.stdc.complex.ccosl cos; /// alias core.stdc.math.sin sin; @@ -643,12 +587,10 @@ else version (OpenBSD) /// alias core.stdc.math.sinl sin; - /// - alias core.stdc.complex.csin csin; - /// - alias core.stdc.complex.csinf csin; - /// - alias core.stdc.complex.csinl csin; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csin csin; + deprecated alias core.stdc.complex.csinf csin; + deprecated alias core.stdc.complex.csinl csin; /// alias core.stdc.math.tan tan; @@ -657,12 +599,10 @@ else version (OpenBSD) /// alias core.stdc.math.tanl tan; - /// - alias core.stdc.complex.ctan tan; - /// - alias core.stdc.complex.ctanf tan; - /// - alias core.stdc.complex.ctanl tan; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ctan tan; + deprecated alias core.stdc.complex.ctanf tan; + deprecated alias core.stdc.complex.ctanl tan; /// alias core.stdc.math.acosh acosh; @@ -671,12 +611,10 @@ else version (OpenBSD) /// alias core.stdc.math.acoshl acosh; - /// - alias core.stdc.complex.cacosh acosh; - /// - alias core.stdc.complex.cacoshf acosh; - /// - alias core.stdc.complex.cacoshl acosh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cacosh acosh; + deprecated alias core.stdc.complex.cacoshf acosh; + deprecated alias core.stdc.complex.cacoshl acosh; /// alias core.stdc.math.asinh asinh; @@ -685,12 +623,10 @@ else version (OpenBSD) /// alias core.stdc.math.asinhl asinh; - /// - alias core.stdc.complex.casinh asinh; - /// - alias core.stdc.complex.casinhf asinh; - /// - alias core.stdc.complex.casinhl asinh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.casinh asinh; + deprecated alias core.stdc.complex.casinhf asinh; + deprecated alias core.stdc.complex.casinhl asinh; /// alias core.stdc.math.atanh atanh; @@ -699,12 +635,10 @@ else version (OpenBSD) /// alias core.stdc.math.atanhl atanh; - /// - alias core.stdc.complex.catanh atanh; - /// - alias core.stdc.complex.catanhf atanh; - /// - alias core.stdc.complex.catanhl atanh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.catanh atanh; + deprecated alias core.stdc.complex.catanhf atanh; + deprecated alias core.stdc.complex.catanhl atanh; /// alias core.stdc.math.cosh cosh; @@ -713,12 +647,10 @@ else version (OpenBSD) /// alias core.stdc.math.coshl cosh; - /// - alias core.stdc.complex.ccosh cosh; - /// - alias core.stdc.complex.ccoshf cosh; - /// - alias core.stdc.complex.ccoshl cosh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ccosh cosh; + deprecated alias core.stdc.complex.ccoshf cosh; + deprecated alias core.stdc.complex.ccoshl cosh; /// alias core.stdc.math.sinh sinh; @@ -727,12 +659,10 @@ else version (OpenBSD) /// alias core.stdc.math.sinhl sinh; - /// - alias core.stdc.complex.csinh sinh; - /// - alias core.stdc.complex.csinhf sinh; - /// - alias core.stdc.complex.csinhl sinh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csinh sinh; + deprecated alias core.stdc.complex.csinhf sinh; + deprecated alias core.stdc.complex.csinhl sinh; /// alias core.stdc.math.tanh tanh; @@ -741,12 +671,10 @@ else version (OpenBSD) /// alias core.stdc.math.tanhl tanh; - /// - alias core.stdc.complex.ctanh tanh; - /// - alias core.stdc.complex.ctanhf tanh; - /// - alias core.stdc.complex.ctanhl tanh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ctanh tanh; + deprecated alias core.stdc.complex.ctanhf tanh; + deprecated alias core.stdc.complex.ctanhl tanh; /// alias core.stdc.math.exp exp; @@ -755,12 +683,10 @@ else version (OpenBSD) /// alias core.stdc.math.expl exp; - /// - alias core.stdc.complex.cexp exp; - /// - alias core.stdc.complex.cexpf exp; - /// - alias core.stdc.complex.cexpl exp; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cexp exp; + deprecated alias core.stdc.complex.cexpf exp; + deprecated alias core.stdc.complex.cexpl exp; /// alias core.stdc.math.exp2 exp2; @@ -804,12 +730,10 @@ else version (OpenBSD) /// alias core.stdc.math.logl log; - /// - alias core.stdc.complex.clog log; - /// - alias core.stdc.complex.clogf log; - /// - alias core.stdc.complex.clogl log; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.clog log; + deprecated alias core.stdc.complex.clogf log; + deprecated alias core.stdc.complex.clogl log; /// alias core.stdc.math.log10 log10; @@ -874,12 +798,10 @@ else version (OpenBSD) /// alias core.stdc.math.fabsl fabs; - /// - alias core.stdc.complex.cabs fabs; - /// - alias core.stdc.complex.cabsf fabs; - /// - alias core.stdc.complex.cabsl fabs; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cabs fabs; + deprecated alias core.stdc.complex.cabsf fabs; + deprecated alias core.stdc.complex.cabsl fabs; /// alias core.stdc.math.hypot hypot; @@ -895,12 +817,10 @@ else version (OpenBSD) /// alias core.stdc.math.powl pow; - /// - alias core.stdc.complex.cpow pow; - /// - alias core.stdc.complex.cpowf pow; - /// - alias core.stdc.complex.cpowl pow; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cpow pow; + deprecated alias core.stdc.complex.cpowf pow; + deprecated alias core.stdc.complex.cpowl pow; /// alias core.stdc.math.sqrt sqrt; @@ -909,12 +829,10 @@ else version (OpenBSD) /// alias core.stdc.math.sqrtl sqrt; - /// - alias core.stdc.complex.csqrt sqrt; - /// - alias core.stdc.complex.csqrtf sqrt; - /// - alias core.stdc.complex.csqrtl sqrt; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csqrt sqrt; + deprecated alias core.stdc.complex.csqrtf sqrt; + deprecated alias core.stdc.complex.csqrtl sqrt; /// alias core.stdc.math.erf erf; @@ -1077,37 +995,23 @@ else version (OpenBSD) /// alias core.stdc.math.fmal fma; - /// - alias core.stdc.complex.carg carg; - /// - alias core.stdc.complex.cargf carg; - /// - alias core.stdc.complex.cargl carg; - - /// - alias core.stdc.complex.cimag cimag; - /// - alias core.stdc.complex.cimagf cimag; - /// - alias core.stdc.complex.cimagl cimag; - - /// - alias core.stdc.complex.conj conj; - /// - alias core.stdc.complex.conjf conj; - /// - alias core.stdc.complex.conjl conj; - - /// - alias core.stdc.complex.cproj cproj; - /// - alias core.stdc.complex.cprojf cproj; - /// - alias core.stdc.complex.cprojl cproj; - -// alias core.stdc.complex.creal creal; -// alias core.stdc.complex.crealf creal; -// alias core.stdc.complex.creall creal; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.carg carg; + deprecated alias core.stdc.complex.cargf carg; + deprecated alias core.stdc.complex.cargl carg; + deprecated alias core.stdc.complex.cimag cimag; + deprecated alias core.stdc.complex.cimagf cimag; + deprecated alias core.stdc.complex.cimagl cimag; + deprecated alias core.stdc.complex.conj conj; + deprecated alias core.stdc.complex.conjf conj; + deprecated alias core.stdc.complex.conjl conj; + deprecated alias core.stdc.complex.cproj cproj; + deprecated alias core.stdc.complex.cprojf cproj; + deprecated alias core.stdc.complex.cprojl cproj; + +// deprecated alias core.stdc.complex.creal creal; +// deprecated alias core.stdc.complex.crealf creal; +// deprecated alias core.stdc.complex.creall creal; } else { @@ -1118,12 +1022,10 @@ else /// alias core.stdc.math.acosl acos; - /// - alias core.stdc.complex.cacos acos; - /// - alias core.stdc.complex.cacosf acos; - /// - alias core.stdc.complex.cacosl acos; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cacos acos; + deprecated alias core.stdc.complex.cacosf acos; + deprecated alias core.stdc.complex.cacosl acos; /// alias core.stdc.math.asin asin; @@ -1132,12 +1034,10 @@ else /// alias core.stdc.math.asinl asin; - /// - alias core.stdc.complex.casin asin; - /// - alias core.stdc.complex.casinf asin; - /// - alias core.stdc.complex.casinl asin; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.casin asin; + deprecated alias core.stdc.complex.casinf asin; + deprecated alias core.stdc.complex.casinl asin; /// alias core.stdc.math.atan atan; @@ -1146,12 +1046,10 @@ else /// alias core.stdc.math.atanl atan; - /// - alias core.stdc.complex.catan atan; - /// - alias core.stdc.complex.catanf atan; - /// - alias core.stdc.complex.catanl atan; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.catan atan; + deprecated alias core.stdc.complex.catanf atan; + deprecated alias core.stdc.complex.catanl atan; /// alias core.stdc.math.atan2 atan2; @@ -1167,12 +1065,10 @@ else /// alias core.stdc.math.cosl cos; - /// - alias core.stdc.complex.ccos cos; - /// - alias core.stdc.complex.ccosf cos; - /// - alias core.stdc.complex.ccosl cos; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ccos cos; + deprecated alias core.stdc.complex.ccosf cos; + deprecated alias core.stdc.complex.ccosl cos; /// alias core.stdc.math.sin sin; @@ -1181,12 +1077,10 @@ else /// alias core.stdc.math.sinl sin; - /// - alias core.stdc.complex.csin csin; - /// - alias core.stdc.complex.csinf csin; - /// - alias core.stdc.complex.csinl csin; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csin csin; + deprecated alias core.stdc.complex.csinf csin; + deprecated alias core.stdc.complex.csinl csin; /// alias core.stdc.math.tan tan; @@ -1195,12 +1089,10 @@ else /// alias core.stdc.math.tanl tan; - /// - alias core.stdc.complex.ctan tan; - /// - alias core.stdc.complex.ctanf tan; - /// - alias core.stdc.complex.ctanl tan; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ctan tan; + deprecated alias core.stdc.complex.ctanf tan; + deprecated alias core.stdc.complex.ctanl tan; /// alias core.stdc.math.acosh acosh; @@ -1209,12 +1101,10 @@ else /// alias core.stdc.math.acoshl acosh; - /// - alias core.stdc.complex.cacosh acosh; - /// - alias core.stdc.complex.cacoshf acosh; - /// - alias core.stdc.complex.cacoshl acosh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cacosh acosh; + deprecated alias core.stdc.complex.cacoshf acosh; + deprecated alias core.stdc.complex.cacoshl acosh; /// alias core.stdc.math.asinh asinh; @@ -1223,12 +1113,10 @@ else /// alias core.stdc.math.asinhl asinh; - /// - alias core.stdc.complex.casinh asinh; - /// - alias core.stdc.complex.casinhf asinh; - /// - alias core.stdc.complex.casinhl asinh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.casinh asinh; + deprecated alias core.stdc.complex.casinhf asinh; + deprecated alias core.stdc.complex.casinhl asinh; /// alias core.stdc.math.atanh atanh; @@ -1237,12 +1125,10 @@ else /// alias core.stdc.math.atanhl atanh; - /// - alias core.stdc.complex.catanh atanh; - /// - alias core.stdc.complex.catanhf atanh; - /// - alias core.stdc.complex.catanhl atanh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.catanh atanh; + deprecated alias core.stdc.complex.catanhf atanh; + deprecated alias core.stdc.complex.catanhl atanh; /// alias core.stdc.math.cosh cosh; @@ -1251,12 +1137,10 @@ else /// alias core.stdc.math.coshl cosh; - /// - alias core.stdc.complex.ccosh cosh; - /// - alias core.stdc.complex.ccoshf cosh; - /// - alias core.stdc.complex.ccoshl cosh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ccosh cosh; + deprecated alias core.stdc.complex.ccoshf cosh; + deprecated alias core.stdc.complex.ccoshl cosh; /// alias core.stdc.math.sinh sinh; @@ -1265,12 +1149,10 @@ else /// alias core.stdc.math.sinhl sinh; - /// - alias core.stdc.complex.csinh sinh; - /// - alias core.stdc.complex.csinhf sinh; - /// - alias core.stdc.complex.csinhl sinh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csinh sinh; + deprecated alias core.stdc.complex.csinhf sinh; + deprecated alias core.stdc.complex.csinhl sinh; /// alias core.stdc.math.tanh tanh; @@ -1279,12 +1161,10 @@ else /// alias core.stdc.math.tanhl tanh; - /// - alias core.stdc.complex.ctanh tanh; - /// - alias core.stdc.complex.ctanhf tanh; - /// - alias core.stdc.complex.ctanhl tanh; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.ctanh tanh; + deprecated alias core.stdc.complex.ctanhf tanh; + deprecated alias core.stdc.complex.ctanhl tanh; /// alias core.stdc.math.exp exp; @@ -1293,12 +1173,10 @@ else /// alias core.stdc.math.expl exp; - /// - alias core.stdc.complex.cexp exp; - /// - alias core.stdc.complex.cexpf exp; - /// - alias core.stdc.complex.cexpl exp; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cexp exp; + deprecated alias core.stdc.complex.cexpf exp; + deprecated alias core.stdc.complex.cexpl exp; /// alias core.stdc.math.exp2 exp2; @@ -1342,12 +1220,10 @@ else /// alias core.stdc.math.logl log; - /// - alias core.stdc.complex.clog log; - /// - alias core.stdc.complex.clogf log; - /// - alias core.stdc.complex.clogl log; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.clog log; + deprecated alias core.stdc.complex.clogf log; + deprecated alias core.stdc.complex.clogl log; /// alias core.stdc.math.log10 log10; @@ -1409,6 +1285,13 @@ else alias core.stdc.math.fabs fabs; version (CRuntime_Microsoft) { + version (MinGW) + { + /// + alias core.stdc.math.fabsf fabs; + /// + alias core.stdc.math.fabsl fabs; + } } else { @@ -1418,12 +1301,10 @@ else alias core.stdc.math.fabsl fabs; } - /// - alias core.stdc.complex.cabs fabs; - /// - alias core.stdc.complex.cabsf fabs; - /// - alias core.stdc.complex.cabsl fabs; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cabs fabs; + deprecated alias core.stdc.complex.cabsf fabs; + deprecated alias core.stdc.complex.cabsl fabs; /// alias core.stdc.math.hypot hypot; @@ -1439,12 +1320,10 @@ else /// alias core.stdc.math.powl pow; - /// - alias core.stdc.complex.cpow pow; - /// - alias core.stdc.complex.cpowf pow; - /// - alias core.stdc.complex.cpowl pow; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.cpow pow; + deprecated alias core.stdc.complex.cpowf pow; + deprecated alias core.stdc.complex.cpowl pow; /// alias core.stdc.math.sqrt sqrt; @@ -1453,12 +1332,10 @@ else /// alias core.stdc.math.sqrtl sqrt; - /// - alias core.stdc.complex.csqrt sqrt; - /// - alias core.stdc.complex.csqrtf sqrt; - /// - alias core.stdc.complex.csqrtl sqrt; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.csqrt sqrt; + deprecated alias core.stdc.complex.csqrtf sqrt; + deprecated alias core.stdc.complex.csqrtl sqrt; /// alias core.stdc.math.erf erf; @@ -1635,35 +1512,20 @@ else /// alias core.stdc.math.fmal fma; - /// - alias core.stdc.complex.carg carg; - /// - alias core.stdc.complex.cargf carg; - /// - alias core.stdc.complex.cargl carg; - - /// - alias core.stdc.complex.cimag cimag; - /// - alias core.stdc.complex.cimagf cimag; - /// - alias core.stdc.complex.cimagl cimag; - - /// - alias core.stdc.complex.conj conj; - /// - alias core.stdc.complex.conjf conj; - /// - alias core.stdc.complex.conjl conj; - - /// - alias core.stdc.complex.cproj cproj; - /// - alias core.stdc.complex.cprojf cproj; - /// - alias core.stdc.complex.cprojl cproj; - -// alias core.stdc.complex.creal creal; -// alias core.stdc.complex.crealf creal; -// alias core.stdc.complex.creall creal; + // @@@DEPRECATED_2.105@@@ + deprecated alias core.stdc.complex.carg carg; + deprecated alias core.stdc.complex.cargf carg; + deprecated alias core.stdc.complex.cargl carg; + deprecated alias core.stdc.complex.cimag cimag; + deprecated alias core.stdc.complex.cimagf cimag; + deprecated alias core.stdc.complex.cimagl cimag; + deprecated alias core.stdc.complex.conj conj; + deprecated alias core.stdc.complex.conjf conj; + deprecated alias core.stdc.complex.conjl conj; + deprecated alias core.stdc.complex.cproj cproj; + deprecated alias core.stdc.complex.cprojf cproj; + deprecated alias core.stdc.complex.cprojl cproj; +// deprecated alias core.stdc.complex.creal creal; +// deprecated alias core.stdc.complex.crealf creal; +// deprecated alias core.stdc.complex.creall creal; } diff --git a/libphobos/libdruntime/core/stdc/wchar_.d b/libphobos/libdruntime/core/stdc/wchar_.d index eecc8ef..6da5618 100644 --- a/libphobos/libdruntime/core/stdc/wchar_.d +++ b/libphobos/libdruntime/core/stdc/wchar_.d @@ -173,12 +173,13 @@ extern (D) @trusted wint_t getwchar() { return fgetwc(stdin); } /// wint_t putwchar(wchar_t c) { return fputwc(c,stdout); } - /// - wint_t getwc(FILE* stream) { return fgetwc(stream); } - /// - wint_t putwc(wchar_t c, FILE* stream) { return fputwc(c, stream); } } +/// +alias getwc = fgetwc; +/// +alias putwc = fputwc; + // No unsafe pointer manipulation. @trusted { diff --git a/libphobos/libdruntime/core/sys/darwin/config.d b/libphobos/libdruntime/core/sys/darwin/config.d new file mode 100644 index 0000000..87f3fd4 --- /dev/null +++ b/libphobos/libdruntime/core/sys/darwin/config.d @@ -0,0 +1,53 @@ +/** + * D header file for Darwin. + * + * Copyright: Copyright (c) 2021 D Language Foundation + * Authors: Iain Buclaw + */ +module core.sys.darwin.config; + +version (OSX) + version = Darwin; +else version (iOS) + version = Darwin; +else version (TVOS) + version = Darwin; +else version (WatchOS) + version = Darwin; + +version (Darwin): + +public import core.sys.posix.config; + +enum __MAC_10_0 = 100000; +enum __MAC_10_1 = 100100; +enum __MAC_10_2 = 100200; +enum __MAC_10_3 = 100300; +enum __MAC_10_4 = 100400; +enum __MAC_10_5 = 100500; +enum __MAC_10_6 = 100600; +enum __MAC_10_7 = 100700; +enum __MAC_10_8 = 100800; +enum __MAC_10_9 = 100900; +enum __MAC_10_10 = 101000; +enum __MAC_10_10_2 = 101002; +enum __MAC_10_10_3 = 101003; +enum __MAC_10_11 = 101100; +enum __MAC_10_11_2 = 101102; +enum __MAC_10_11_3 = 101103; +enum __MAC_10_11_4 = 101104; +enum __MAC_10_12 = 101200; +enum __MAC_10_12_1 = 101201; +enum __MAC_10_12_2 = 101202; +enum __MAC_10_12_4 = 101204; +enum __MAC_10_13 = 101300; +enum __MAC_10_13_1 = 101301; +enum __MAC_10_13_2 = 101302; +enum __MAC_10_13_4 = 101304; +enum __MAC_10_14 = 101400; +enum __MAC_10_14_1 = 101401; +enum __MAC_10_14_4 = 101404; +enum __MAC_10_15 = 101500; +enum __MAC_10_15_1 = 101501; +enum __MAC_10_16 = 101501; +enum __MAC_11_0 = 110000; diff --git a/libphobos/libdruntime/core/sys/darwin/fcntl.d b/libphobos/libdruntime/core/sys/darwin/fcntl.d new file mode 100644 index 0000000..47d895a --- /dev/null +++ b/libphobos/libdruntime/core/sys/darwin/fcntl.d @@ -0,0 +1,20 @@ +module core.sys.darwin.fcntl; + +public import core.sys.posix.fcntl; + +version (OSX) + version = Darwin; +else version (iOS) + version = Darwin; +else version (TVOS) + version = Darwin; +else version (WatchOS) + version = Darwin; + +version (Darwin): +extern (C): +nothrow: +@nogc: +@system: + +enum F_FULLFSYNC = 51; diff --git a/libphobos/libdruntime/core/sys/darwin/mach/thread_act.d b/libphobos/libdruntime/core/sys/darwin/mach/thread_act.d index b61673f..d455d1b 100644 --- a/libphobos/libdruntime/core/sys/darwin/mach/thread_act.d +++ b/libphobos/libdruntime/core/sys/darwin/mach/thread_act.d @@ -38,6 +38,10 @@ version (AArch64) version = AnyARM; version (ARM) version = AnyARM; +version (PPC) + version = AnyPPC; +version (PPC64) + version = AnyPPC; version (i386) { @@ -235,3 +239,65 @@ else version (AnyARM) kern_return_t thread_resume(thread_act_t); kern_return_t thread_get_state(thread_act_t, thread_state_flavor_t, thread_state_t*, mach_msg_type_number_t*); } +else version (AnyPPC) +{ + alias thread_act_t = mach_port_t; + alias thread_state_t = void; + alias thread_state_flavor_t = int; + alias mach_msg_type_number_t = natural_t; + + enum + { + PPC_THREAD_STATE = 1, + PPC_FLOAT_STATE = 2, + PPC_EXCEPTION_STATE = 3, + PPC_VECTOR_STATE = 4, + PPC_THREAD_STATE64 = 5, + PPC_EXCEPTION_STATE64 = 6, + THREAD_STATE_NONE = 7 + } + + struct ppc_thread_state_t + { + uint srr0; /// Instruction address register (PC) + uint srr1; /// Machine state register (supervisor) + uint[32] r; /// General purpose register r0-r31 + uint cr; /// Condition register + uint xer; /// User's integer exception register + uint lr; /// Link register + uint ctr; /// Count register + uint mq; /// MQ register (601 only) + uint vrsave; /// Vector save register + } + + alias ppc_thread_state32_t = ppc_thread_state_t; + + struct ppc_thread_state64_t + { + ulong srr0; /// Instruction address register (PC) + ulong srr1; /// Machine state register (supervisor) + ulong[32] r; /// General purpose register r0-r31 + uint cr; /// Condition register + uint pad0; + ulong xer; /// User's integer exception register + ulong lr; /// Link register + ulong ctr; /// Count register + uint vrsave; /// Vector save register + uint pad1; + } + + enum : mach_msg_type_number_t + { + PPC_THREAD_STATE_COUNT = cast(mach_msg_type_number_t) (ppc_thread_state_t.sizeof / uint.sizeof), + PPC_THREAD_STATE32_COUNT = cast(mach_msg_type_number_t) (ppc_thread_state32_t.sizeof / uint.sizeof), + PPC_THREAD_STATE64_COUNT = cast(mach_msg_type_number_t) (ppc_thread_state64_t.sizeof / uint.sizeof), + } + + alias MACHINE_THREAD_STATE = PPC_THREAD_STATE; + alias MACHINE_THREAD_STATE_COUNT = PPC_THREAD_STATE_COUNT; + + mach_port_t mach_thread_self(); + kern_return_t thread_suspend(thread_act_t); + kern_return_t thread_resume(thread_act_t); + kern_return_t thread_get_state(thread_act_t, thread_state_flavor_t, thread_state_t*, mach_msg_type_number_t*); +} diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/dlfcn.d b/libphobos/libdruntime/core/sys/dragonflybsd/dlfcn.d index 1d3812f..2c5d8d7 100644 --- a/libphobos/libdruntime/core/sys/dragonflybsd/dlfcn.d +++ b/libphobos/libdruntime/core/sys/dragonflybsd/dlfcn.d @@ -82,16 +82,13 @@ struct __dlfunc_arg { alias dlfunc_t = void function(__dlfunc_arg); -private template __externC(RT, P...) -{ - alias __externC = extern(C) RT function(P) nothrow @nogc @system; -} - /* XSI functions first. */ -static assert(is(typeof(&dlclose) == __externC!(int, void*))); -static assert(is(typeof(&dlerror) == __externC!(char*))); -static assert(is(typeof(&dlopen) == __externC!(void*, const char*, int))); -static assert(is(typeof(&dlsym) == __externC!(void*, void*, const char*))); +extern(C) { + static assert(is(typeof(&dlclose) == int function(void*))); + static assert(is(typeof(&dlerror) == char* function())); + static assert(is(typeof(&dlopen) == void* function(const scope char*, int))); + static assert(is(typeof(&dlsym) == void* function(void*, const scope char*))); +} void* fdlopen(int, int); int dladdr(const(void)*, Dl_info*); diff --git a/libphobos/libdruntime/core/sys/freebsd/dlfcn.d b/libphobos/libdruntime/core/sys/freebsd/dlfcn.d index fad9141..7baacfe 100644 --- a/libphobos/libdruntime/core/sys/freebsd/dlfcn.d +++ b/libphobos/libdruntime/core/sys/freebsd/dlfcn.d @@ -90,8 +90,8 @@ static if (__BSD_VISIBLE) extern(C) { static assert(is(typeof(&dlclose) == int function(void*))); static assert(is(typeof(&dlerror) == char* function())); - static assert(is(typeof(&dlopen) == void* function(in char*, int))); - static assert(is(typeof(&dlsym) == void* function(void*, in char*))); + static assert(is(typeof(&dlopen) == void* function(const scope char*, int))); + static assert(is(typeof(&dlsym) == void* function(void*, const scope char*))); } static if (__BSD_VISIBLE) diff --git a/libphobos/libdruntime/core/sys/linux/epoll.d b/libphobos/libdruntime/core/sys/linux/epoll.d index 0c3aed9..f5ff7db 100644 --- a/libphobos/libdruntime/core/sys/linux/epoll.d +++ b/libphobos/libdruntime/core/sys/linux/epoll.d @@ -10,6 +10,8 @@ module core.sys.linux.epoll; version (linux): +import core.sys.posix.signal : sigset_t; + extern (C): @system: @nogc: @@ -52,16 +54,19 @@ enum EPOLLHUP = 0x010, EPOLLRDHUP = 0x2000, // since Linux 2.6.17 EPOLLEXCLUSIVE = 1u << 28, // since Linux 4.5 + EPOLLWAKEUP = 1u << 29, EPOLLONESHOT = 1u << 30, EPOLLET = 1u << 31 } -/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */ +/** + * Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). + */ enum { - EPOLL_CTL_ADD = 1, // Add a file descriptor to the interface. - EPOLL_CTL_DEL = 2, // Remove a file descriptor from the interface. - EPOLL_CTL_MOD = 3, // Change file descriptor epoll_event structure. + EPOLL_CTL_ADD = 1, /// Add a file descriptor to the interface. + EPOLL_CTL_DEL = 2, /// Remove a file descriptor from the interface. + EPOLL_CTL_MOD = 3, /// Change file descriptor epoll_event structure. } version (X86_Any) @@ -142,7 +147,82 @@ union epoll_data_t ulong u64; } +/** + * Creates an epoll instance. + * + * Params: + * size = a hint specifying the number of file descriptors to be associated + * with the new instance. T + * Returns: an fd for the new instance. The fd returned by epoll_create() should + * be closed with close(). + * See_also: epoll_create1 (int flags) + */ int epoll_create (int size); + +/* Same as epoll_create but with an FLAGS parameter. The unused SIZE + parameter has been dropped. */ + +/** + * Creates an epoll instance. + * + * Params: + * flags = a specified flag. If flags is 0, then, other than the fact that the + * obsolete size argument is dropped, epoll_create1() is the same as + * epoll_create(). + * Returns: an fd for the new instance. The fd returned by epoll_create() should + * be closed with close(). + * See_also: epoll_create (int size) + */ int epoll_create1 (int flags); + +/** + * Manipulate an epoll instance + * + * Params: + * epfd = an epoll file descriptor instance + * op = one of the EPOLL_CTL_* constants + * fd = target file descriptor of the operation + * event = describes which events the caller is interested in and any + * associated user dat + * Returns: 0 in case of success, -1 in case of error ( the "errno" variable + * will contain the specific error code ) + */ int epoll_ctl (int epfd, int op, int fd, epoll_event *event); + + +/** + * Wait for events on an epoll instance. + * + * + * Params: + * epfd = an epoll file descriptor instance + * events = a buffer that will contain triggered events + * maxevents = the maximum number of events to be returned ( usually size of + * "events" ) + * timeout = specifies the maximum wait time in milliseconds (-1 == infinite) + * + * Returns: the number of triggered events returned in "events" buffer. Or -1 in + * case of error with the "errno" variable set to the specific error + * code. + */ int epoll_wait (int epfd, epoll_event *events, int maxevents, int timeout); + +/** + * Wait for events on an epoll instance + * + * + * Params: + * epfd = an epoll file descriptor instance + * events = a buffer that will contain triggered events + * maxevents = the maximum number of events to be returned ( usually size of + * "events" ) + * timeout = specifies the maximum wait time in milliseconds (-1 == infinite) + * ss = a signal set. May be specified as `null`, in which case epoll_pwait() is + * equivalent to epoll_wait(). + * + * Returns: the number of triggered events returned in "events" buffer. Or -1 in + * case of error with the "errno" variable set to the specific error + * code. + */ +int epoll_pwait (int epfd, epoll_event *events, int maxevents, int timeout, + const sigset_t *ss); diff --git a/libphobos/libdruntime/core/sys/netbsd/dlfcn.d b/libphobos/libdruntime/core/sys/netbsd/dlfcn.d index dbbcc76..468ffbf 100644 --- a/libphobos/libdruntime/core/sys/netbsd/dlfcn.d +++ b/libphobos/libdruntime/core/sys/netbsd/dlfcn.d @@ -87,16 +87,13 @@ static if (__BSD_VISIBLE) } } -private template __externC(RT, P...) -{ - alias __externC = extern(C) RT function(P) nothrow @nogc; -} - /* XSI functions first. */ -static assert(is(typeof(&dlclose) == __externC!(int, void*))); -static assert(is(typeof(&dlerror) == __externC!(char*))); -static assert(is(typeof(&dlopen) == __externC!(void*, const char*, int))); -static assert(is(typeof(&dlsym) == __externC!(void*, void*, const char*))); +extern(C) { + static assert(is(typeof(&dlclose) == int function(void*))); + static assert(is(typeof(&dlerror) == char* function())); + static assert(is(typeof(&dlopen) == void* function(const scope char*, int))); + static assert(is(typeof(&dlsym) == void* function(void*, const scope char*))); +} static if (__BSD_VISIBLE) { diff --git a/libphobos/libdruntime/core/sys/openbsd/string.d b/libphobos/libdruntime/core/sys/openbsd/string.d index 8d35b9c..cb978c8 100644 --- a/libphobos/libdruntime/core/sys/openbsd/string.d +++ b/libphobos/libdruntime/core/sys/openbsd/string.d @@ -18,4 +18,6 @@ nothrow: static if (__BSD_VISIBLE) { pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen); + pure int timingsafe_bcmp(scope const void*, scope const void*, size_t); + pure int timingsafe_memcmp(scope const void*, scope const void*, size_t); } diff --git a/libphobos/libdruntime/core/sys/openbsd/sys/link_elf.d b/libphobos/libdruntime/core/sys/openbsd/sys/link_elf.d index f88671a..55fc792 100644 --- a/libphobos/libdruntime/core/sys/openbsd/sys/link_elf.d +++ b/libphobos/libdruntime/core/sys/openbsd/sys/link_elf.d @@ -63,3 +63,8 @@ private alias int function(dl_phdr_info*, size_t, void *) @nogc dl_iterate_phdr_ int dl_iterate_phdr(dl_iterate_phdr_cb __callback, void*__data); int dl_iterate_phdr(dl_iterate_phdr_cb_ngc __callback, void*__data) @nogc; + +int _rtld_addr_phdr(const void*, dl_phdr_info*) @nogc +{ + return 0; +} diff --git a/libphobos/libdruntime/core/sys/openbsd/unistd.d b/libphobos/libdruntime/core/sys/openbsd/unistd.d new file mode 100644 index 0000000..ddd102c --- /dev/null +++ b/libphobos/libdruntime/core/sys/openbsd/unistd.d @@ -0,0 +1,17 @@ +/** + * D header file for OpenBSD unistd.h. + * + * Copyright: Copyright © 2021, The D Language Foundation + * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. + * Authors: Brian Callahan + */ +module core.sys.openbsd.unistd; +public import core.sys.posix.unistd; + +version (OpenBSD): +extern (C): +nothrow: +@nogc: + +int pledge(const scope char*, const scope char*); +int unveil(const scope char*, const scope char*); diff --git a/libphobos/libdruntime/core/sys/posix/config.d b/libphobos/libdruntime/core/sys/posix/config.d index c02debff..3b575fa 100644 --- a/libphobos/libdruntime/core/sys/posix/config.d +++ b/libphobos/libdruntime/core/sys/posix/config.d @@ -117,6 +117,7 @@ else version (CRuntime_UClibc) else version (CRuntime_Bionic) { enum _GNU_SOURCE = false; + enum __USE_FILE_OFFSET64 = false; // see https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md enum __USE_GNU = _GNU_SOURCE; version (D_LP64) diff --git a/libphobos/libdruntime/core/sys/posix/dlfcn.d b/libphobos/libdruntime/core/sys/posix/dlfcn.d index e97c7ea..f6476ec 100644 --- a/libphobos/libdruntime/core/sys/posix/dlfcn.d +++ b/libphobos/libdruntime/core/sys/posix/dlfcn.d @@ -139,7 +139,7 @@ else version (Darwin) char* dlerror(); void* dlopen(const scope char*, int); void* dlsym(void*, const scope char*); - int dladdr(void* addr, Dl_info* info); + int dladdr(scope const void* addr, Dl_info* info); struct Dl_info { @@ -158,8 +158,8 @@ else version (FreeBSD) int dlclose(void*); char* dlerror(); - void* dlopen(in char*, int); - void* dlsym(void*, in char*); + void* dlopen(const scope char*, int); + void* dlsym(void*, const scope char*); int dladdr(const(void)* addr, Dl_info* info); struct Dl_info @@ -294,6 +294,15 @@ else version (CRuntime_Musl) const(char)* dlerror(); void* dlopen(const scope char*, int); void* dlsym(void*, const scope char*); + + int dladdr(scope const void *addr, Dl_info *info); + struct Dl_info + { + const(char)* dli_fname; + void* dli_fbase; + const(char)* dli_sname; + void* dli_saddr; + } } else version (CRuntime_UClibc) { diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d index 44f45f2..0dce8c5 100644 --- a/libphobos/libdruntime/core/sys/posix/signal.d +++ b/libphobos/libdruntime/core/sys/posix/signal.d @@ -3503,7 +3503,7 @@ struct sigevent pthread_attr_t* sigev_notify_attributes; } -int sigqueue(pid_t, int, in sigval); +int sigqueue(pid_t, int, const sigval); int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); */ @@ -3543,7 +3543,7 @@ version (CRuntime_Glibc) } _sigev_un_t _sigev_un; } - int sigqueue(pid_t, int, in sigval); + int sigqueue(pid_t, int, const sigval); int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); } @@ -3566,7 +3566,7 @@ else version (FreeBSD) } } - int sigqueue(pid_t, int, in sigval); + int sigqueue(pid_t, int, const sigval); int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); } @@ -3581,7 +3581,7 @@ else version (NetBSD) void /* pthread_attr_t */*sigev_notify_attributes; } - int sigqueue(pid_t, int, in sigval); + int sigqueue(pid_t, int, const sigval); int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); } @@ -3613,7 +3613,7 @@ else version (DragonFlyBSD) void function(_sigval_t) sigev_notify_function; } - int sigqueue(pid_t, int, in sigval); + int sigqueue(pid_t, int, const sigval); int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); } @@ -3640,7 +3640,7 @@ else version (Solaris) int __sigev_pad2; } - int sigqueue(pid_t, int, in sigval); + int sigqueue(pid_t, int, const sigval); int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); } @@ -3717,7 +3717,7 @@ else version (CRuntime_UClibc) @property void function(sigval) sigev_notify_function(ref sigevent _sigevent) { return _sigevent._sigev_un._sigev_thread._function; } @property void* sigev_notify_attributes(ref sigevent _sigevent) { return _sigevent._sigev_un._sigev_thread._attribute; } - int sigqueue(pid_t, int, in sigval); + int sigqueue(pid_t, int, const sigval); int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*); int sigwaitinfo(const scope sigset_t*, siginfo_t*); } diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d index 031bcb7..41b52da 100644 --- a/libphobos/libdruntime/core/sys/posix/stdio.d +++ b/libphobos/libdruntime/core/sys/posix/stdio.d @@ -516,6 +516,46 @@ version (CRuntime_Glibc) int putc_unlocked(int, FILE*); int putchar_unlocked(int); } +else version (CRuntime_Musl) +{ + void flockfile(FILE*); + int ftrylockfile(FILE*); + void funlockfile(FILE*); + int getc_unlocked(FILE*); + int getchar_unlocked(); + int putc_unlocked(int, FILE*); + int putchar_unlocked(int); +} +else version (Darwin) +{ + void flockfile(FILE*); + int ftrylockfile(FILE*); + void funlockfile(FILE*); + int getc_unlocked(FILE*); + int getchar_unlocked(); + int putc_unlocked(int, FILE*); + int putchar_unlocked(int); +} +else version (FreeBSD) +{ + void flockfile(FILE*); + int ftrylockfile(FILE*); + void funlockfile(FILE*); + int getc_unlocked(FILE*); + int getchar_unlocked(); + int putc_unlocked(int, FILE*); + int putchar_unlocked(int); +} +else version (NetBSD) +{ + void flockfile(FILE*); + int ftrylockfile(FILE*); + void funlockfile(FILE*); + int getc_unlocked(FILE*); + int getchar_unlocked(); + int putc_unlocked(int, FILE*); + int putchar_unlocked(int); +} else version (OpenBSD) { void flockfile(FILE*); @@ -526,6 +566,16 @@ else version (OpenBSD) int putc_unlocked(int, FILE*); int putchar_unlocked(int); } +else version (DragonFlyBSD) +{ + void flockfile(FILE*); + int ftrylockfile(FILE*); + void funlockfile(FILE*); + int getc_unlocked(FILE*); + int getchar_unlocked(); + int putc_unlocked(int, FILE*); + int putchar_unlocked(int); +} else version (Solaris) { void flockfile(FILE*); diff --git a/libphobos/libdruntime/core/sys/posix/unistd.d b/libphobos/libdruntime/core/sys/posix/unistd.d index a691884..d996556 100644 --- a/libphobos/libdruntime/core/sys/posix/unistd.d +++ b/libphobos/libdruntime/core/sys/posix/unistd.d @@ -2722,3 +2722,51 @@ else version (CRuntime_UClibc) int truncate(const scope char*, off_t); } } + +// Non-standard definition to access user process environment +version (CRuntime_Glibc) +{ + extern __gshared const char** environ; +} +else version (Darwin) +{ + extern (D) @property const(char**) environ()() + { + pragma (inline, true); + import core.sys.darwin.crt_externs : _NSGetEnviron; + return *_NSGetEnviron(); + } +} +else version (FreeBSD) +{ + extern __gshared const char** environ; +} +else version (NetBSD) +{ + extern __gshared const char** environ; +} +else version (OpenBSD) +{ + extern __gshared const char** environ; +} +else version (DragonFlyBSD) +{ + extern __gshared const char** environ; +} +else version (CRuntime_Bionic) +{ + extern __gshared const char** environ; +} +else version (CRuntime_Musl) +{ + extern __gshared const char** environ; +} +else version (Solaris) +{ + extern __gshared const char** environ; +} +else version (CRuntime_UClibc) +{ + extern __gshared const char** __environ; + alias environ = __environ; +} diff --git a/libphobos/libdruntime/core/sys/windows/com.d b/libphobos/libdruntime/core/sys/windows/com.d index 90a2943..6935dd9 100644 --- a/libphobos/libdruntime/core/sys/windows/com.d +++ b/libphobos/libdruntime/core/sys/windows/com.d @@ -39,16 +39,16 @@ public import core.sys.windows.winerror : RPC_E_CHANGED_MODE; public import core.sys.windows.wtypes : - OLECHAR, LPOLESTR, LPCOLESTR; + CLSCTX, OLECHAR, LPOLESTR, LPCOLESTR; -alias CLSCTX_INPROC_SERVER = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVER ; -alias CLSCTX_INPROC_HANDLER = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLER ; -alias CLSCTX_LOCAL_SERVER = core.sys.windows.wtypes.CLSCTX.CLSCTX_LOCAL_SERVER ; -alias CLSCTX_INPROC_SERVER16 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVER16 ; -alias CLSCTX_REMOTE_SERVER = core.sys.windows.wtypes.CLSCTX.CLSCTX_REMOTE_SERVER ; -alias CLSCTX_INPROC_HANDLER16 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLER16 ; -alias CLSCTX_INPROC_SERVERX86 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_SERVERX86 ; -alias CLSCTX_INPROC_HANDLERX86 = core.sys.windows.wtypes.CLSCTX.CLSCTX_INPROC_HANDLERX86; +alias CLSCTX_INPROC_SERVER = CLSCTX.CLSCTX_INPROC_SERVER ; +alias CLSCTX_INPROC_HANDLER = CLSCTX.CLSCTX_INPROC_HANDLER ; +alias CLSCTX_LOCAL_SERVER = CLSCTX.CLSCTX_LOCAL_SERVER ; +alias CLSCTX_INPROC_SERVER16 = CLSCTX.CLSCTX_INPROC_SERVER16 ; +alias CLSCTX_REMOTE_SERVER = CLSCTX.CLSCTX_REMOTE_SERVER ; +alias CLSCTX_INPROC_HANDLER16 = CLSCTX.CLSCTX_INPROC_HANDLER16 ; +alias CLSCTX_INPROC_SERVERX86 = CLSCTX.CLSCTX_INPROC_SERVERX86 ; +alias CLSCTX_INPROC_HANDLERX86 = CLSCTX.CLSCTX_INPROC_HANDLERX86; alias COINIT_APARTMENTTHREADED = COINIT.COINIT_APARTMENTTHREADED; alias COINIT_MULTITHREADED = COINIT.COINIT_MULTITHREADED ; @@ -57,12 +57,12 @@ alias COINIT_SPEED_OVER_MEMORY = COINIT.COINIT_SPEED_OVER_MEMORY; public import core.sys.windows.uuid; -extern (System) +extern (Windows) { class ComObject : IUnknown { -extern (System): +extern (Windows): HRESULT QueryInterface(const(IID)* riid, void** ppv) { if (*riid == IID_IUnknown) diff --git a/libphobos/libdruntime/core/sys/windows/dbghelp.d b/libphobos/libdruntime/core/sys/windows/dbghelp.d index 8c98270..9848fb9 100644 --- a/libphobos/libdruntime/core/sys/windows/dbghelp.d +++ b/libphobos/libdruntime/core/sys/windows/dbghelp.d @@ -18,7 +18,7 @@ import core.sys.windows.windef; public import core.sys.windows.dbghelp_types; -extern(System) +extern(Windows) { alias BOOL function(HANDLE hProcess, DWORD64 lpBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) ReadProcessMemoryProc64; alias PVOID function(HANDLE hProcess, DWORD64 AddrBase) FunctionTableAccessProc64; diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d index 9f36ac3..cc2422b 100644 --- a/libphobos/libdruntime/core/sys/windows/dll.d +++ b/libphobos/libdruntime/core/sys/windows/dll.d @@ -31,17 +31,7 @@ public import core.sys.windows.threadaux; // not access tls_array[tls_index] as needed for thread local _tlsstart and _tlsend extern (C) { - version (MinGW) - { - extern __gshared void* _tls_start; - extern __gshared void* _tls_end; - extern __gshared void* __xl_a; - - alias _tls_start _tlsstart; - alias _tls_end _tlsend; - alias __xl_a _tls_callbacks_a; - } - else version (Win32) + version (Win32) { version (CRuntime_DigitalMars) { @@ -424,7 +414,7 @@ int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc { version (GNU_InlineAsm) { - asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" peb; } + asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" (peb); } } else { @@ -441,7 +431,7 @@ int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc { version (GNU_InlineAsm) { - asm pure nothrow @nogc { "movl %%fs:0x30, %0;" : "=r" peb; } + asm pure nothrow @nogc { "movl %%fs:0x30, %0;" : "=r" (peb); } } else { diff --git a/libphobos/libdruntime/core/sys/windows/stdc/malloc.d b/libphobos/libdruntime/core/sys/windows/stdc/malloc.d new file mode 100644 index 0000000..f52ba37 --- /dev/null +++ b/libphobos/libdruntime/core/sys/windows/stdc/malloc.d @@ -0,0 +1,26 @@ +/** + * D header file for Windows malloc.h. + * + * Translated from MinGW Windows headers + * + * Authors: Iain Buclaw + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Source: $(DRUNTIMESRC src/core/sys/windows/stdc/_malloc.d) + */ +module core.sys.windows.stdc.malloc; +version (CRuntime_Microsoft): +extern (C): +@system: +nothrow: +@nogc: + +export void* _recalloc(void*, size_t, size_t); + +export void _aligned_free(void*); +export void* _aligned_malloc(size_t, size_t); + +export void* _aligned_offset_malloc(size_t, size_t, size_t); +export void* _aligned_realloc(void*, size_t, size_t); +export void* _aligned_recalloc(void*, size_t, size_t, size_t); +export void* _aligned_offset_realloc(void*, size_t, size_t, size_t); +export void* _aligned_offset_recalloc(void*, size_t, size_t, size_t, size_t); diff --git a/libphobos/libdruntime/core/sys/windows/threadaux.d b/libphobos/libdruntime/core/sys/windows/threadaux.d index fb4d1ee..34fda65 100644 --- a/libphobos/libdruntime/core/sys/windows/threadaux.d +++ b/libphobos/libdruntime/core/sys/windows/threadaux.d @@ -172,7 +172,7 @@ struct thread_aux version (GNU_InlineAsm) { void** teb; - asm pure nothrow @nogc { "movl %%fs:0x18, %0;" : "=r" teb; } + asm pure nothrow @nogc { "movl %%fs:0x18, %0;" : "=r" (teb); } return teb; } else @@ -190,7 +190,7 @@ struct thread_aux version (GNU_InlineAsm) { void** teb; - asm pure nothrow @nogc { "movq %%gs:0x30, %0;" : "=r" teb; } + asm pure nothrow @nogc { "movq %%gs:0x30, %0;" : "=r" (teb); } return teb; } else diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber.d index 3270f2e..f4c04ce 100644 --- a/libphobos/libdruntime/core/thread/fiber.d +++ b/libphobos/libdruntime/core/thread/fiber.d @@ -82,6 +82,8 @@ private version (MinGW) version = GNU_AsmX86_Windows; + else version (OSX) + version = AsmX86_Posix; else version (Posix) version = AsmX86_Posix; } @@ -105,13 +107,21 @@ private version (MinGW) version = GNU_AsmX86_64_Windows; + else version (OSX) + version = AsmX86_64_Posix; else version (Posix) version = AsmX86_64_Posix; } } else version (PPC) { - version (Posix) + version (OSX) + { + version = AsmPPC_Darwin; + version = AsmExternal; + version = AlignFiberStackTo16Byte; + } + else version (Posix) { version = AsmPPC_Posix; version = AsmExternal; @@ -119,7 +129,13 @@ private } else version (PPC64) { - version (Posix) + version (OSX) + { + version = AsmPPC_Darwin; + version = AsmExternal; + version = AlignFiberStackTo16Byte; + } + else version (Posix) { version = AlignFiberStackTo16Byte; } @@ -883,6 +899,7 @@ class Fiber */ static Fiber getThis() @safe nothrow @nogc { + version (GNU) pragma(inline, false); return sm_this; } @@ -1346,6 +1363,28 @@ private: assert( (cast(size_t) pstack & 0x0f) == 0 ); } + else version (AsmPPC_Darwin) + { + version (StackGrowsDown) {} + else static assert(false, "PowerPC Darwin only supports decrementing stacks"); + + uint wsize = size_t.sizeof; + + // linkage + regs + FPRs + VRs + uint space = 8 * wsize + 20 * wsize + 18 * 8 + 12 * 16; + (cast(ubyte*)pstack - space)[0 .. space] = 0; + + pstack -= wsize * 6; + *cast(size_t*)pstack = cast(size_t) &fiber_entryPoint; // LR + pstack -= wsize * 22; + + // On Darwin PPC64 pthread self is in R13 (which is reserved). + // At present, it is not safe to migrate fibers between threads, but if that + // changes, then updating the value of R13 will also need to be handled. + version (PPC64) + *cast(size_t*)(pstack + wsize) = cast(size_t) Thread.getThis().m_addr; + assert( (cast(size_t) pstack & 0x0f) == 0 ); + } else version (AsmMIPS_O32_Posix) { version (StackGrowsDown) {} @@ -1731,6 +1770,11 @@ unittest // Multiple threads running shared fibers version (PPC) version = UnsafeFiberMigration; version (PPC64) version = UnsafeFiberMigration; +version (OSX) +{ + version (X86) version = UnsafeFiberMigration; + version (X86_64) version = UnsafeFiberMigration; +} version (UnsafeFiberMigration) { diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d index defdc95..9fcd30e 100644 --- a/libphobos/libdruntime/core/thread/osthread.d +++ b/libphobos/libdruntime/core/thread/osthread.d @@ -349,7 +349,8 @@ class Thread : ThreadBase } else version (Posix) { - pthread_detach( m_addr ); + if (m_addr != m_addr.init) + pthread_detach( m_addr ); m_addr = m_addr.init; } version (Darwin) @@ -420,6 +421,17 @@ class Thread : ThreadBase { uint[16] m_reg; // r0-r15 } + else version (PPC) + { + // Make the assumption that we only care about non-fp and non-vr regs. + // ??? : it seems plausible that a valid address can be copied into a VR. + uint[32] m_reg; // r0-31 + } + else version (PPC64) + { + // As above. + ulong[32] m_reg; // r0-31 + } else { static assert(false, "Architecture not supported." ); @@ -510,7 +522,7 @@ class Thread : ThreadBase { version (GNU) { - auto libs = externDFunc!("gcc.sections.elf_shared.pinLoadedLibraries", + auto libs = externDFunc!("gcc.sections.pinLoadedLibraries", void* function() @nogc nothrow)(); } else @@ -527,7 +539,7 @@ class Thread : ThreadBase { version (GNU) { - externDFunc!("gcc.sections.elf_shared.unpinLoadedLibraries", + externDFunc!("gcc.sections.unpinLoadedLibraries", void function(void*) @nogc nothrow)(libs); } else @@ -578,7 +590,7 @@ class Thread : ThreadBase { version (Windows) { - if ( WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 ) + if ( m_addr != m_addr.init && WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 ) throw new ThreadException( "Unable to join thread" ); // NOTE: m_addr must be cleared before m_hndl is closed to avoid // a race condition with isRunning. The operation is done @@ -589,7 +601,7 @@ class Thread : ThreadBase } else version (Posix) { - if ( pthread_join( m_addr, null ) != 0 ) + if ( m_addr != m_addr.init && pthread_join( m_addr, null ) != 0 ) throw new ThreadException( "Unable to join thread" ); // NOTE: pthread_join acts as a substitute for pthread_detach, // which is normally called by the dtor. Setting m_addr @@ -1396,8 +1408,78 @@ in (fn) void *sp = void; version (GNU) { - __builtin_unwind_init(); - sp = &sp; + // The generic solution below using a call to __builtin_unwind_init () + // followed by an assignment to sp has two issues: + // 1) On some archs it stores a huge amount of FP and Vector state which + // is not the subject of the scan - and, indeed might produce false + // hits. + // 2) Even on archs like X86, where there are no callee-saved FPRs/VRs there + // tend to be 'holes' in the frame allocations (to deal with alignment) which + // also will contain random data which could produce false positives. + // This solution stores only the integer callee-saved registers. + version (X86) + { + void*[3] regs = void; + asm pure nothrow @nogc + { + "movl %%ebx, %0" : "=m" (regs[0]); + "movl %%esi, %0" : "=m" (regs[1]); + "movl %%edi, %0" : "=m" (regs[2]); + } + sp = cast(void*)®s[0]; + } + else version (X86_64) + { + void*[5] regs = void; + asm pure nothrow @nogc + { + "movq %%rbx, %0" : "=m" (regs[0]); + "movq %%r12, %0" : "=m" (regs[1]); + "movq %%r13, %0" : "=m" (regs[2]); + "movq %%r14, %0" : "=m" (regs[3]); + "movq %%r15, %0" : "=m" (regs[4]); + } + sp = cast(void*)®s[0]; + } + else version (PPC) + { + void*[19] regs = void; + version (Darwin) + enum regname = "r"; + else + enum regname = ""; + static foreach (i; 0 .. regs.length) + {{ + enum int j = 13 + i; // source register + asm pure nothrow @nogc + { + "stw "~regname~j.stringof~", %0" : "=m" (regs[i]); + } + }} + sp = cast(void*)®s[0]; + } + else version (PPC64) + { + void*[19] regs = void; + version (Darwin) + enum regname = "r"; + else + enum regname = ""; + static foreach (i; 0 .. regs.length) + {{ + enum int j = 13 + i; // source register + asm pure nothrow @nogc + { + "std "~regname~j.stringof~", %0" : "=m" (regs[i]); + } + }} + sp = cast(void*)®s[0]; + } + else + { + __builtin_unwind_init(); + sp = &sp; + } } else version (AsmX86_Posix) { @@ -1539,9 +1621,9 @@ package extern(D) void* getStackBottom() nothrow @nogc void *bottom; version (X86) - asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" bottom; } + asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" (bottom); } else version (X86_64) - asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" bottom; } + asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" (bottom); } else static assert(false, "Platform not supported."); @@ -1790,6 +1872,28 @@ private extern (D) bool suspend( Thread t ) nothrow @nogc t.m_reg[14] = state.lr; t.m_reg[15] = state.pc; } + else version (PPC) + { + ppc_thread_state_t state = void; + mach_msg_type_number_t count = PPC_THREAD_STATE_COUNT; + + if (thread_get_state(t.m_tmach, PPC_THREAD_STATE, &state, &count) != KERN_SUCCESS) + onThreadError("Unable to load thread state"); + if (!t.m_lock) + t.m_curr.tstack = cast(void*) state.r[1]; + t.m_reg[] = state.r[]; + } + else version (PPC64) + { + ppc_thread_state64_t state = void; + mach_msg_type_number_t count = PPC_THREAD_STATE64_COUNT; + + if (thread_get_state(t.m_tmach, PPC_THREAD_STATE64, &state, &count) != KERN_SUCCESS) + onThreadError("Unable to load thread state"); + if (!t.m_lock) + t.m_curr.tstack = cast(void*) state.r[1]; + t.m_reg[] = state.r[]; + } else { static assert(false, "Architecture not supported." ); @@ -2196,7 +2300,7 @@ else version (Posix) // before initilizing GC for TLS (rt_tlsgc_init) version (GNUShared) { - externDFunc!("gcc.sections.elf_shared.inheritLoadedLibraries", + externDFunc!("gcc.sections.inheritLoadedLibraries", void function(void*) @nogc nothrow)(loadedLibraries); } else version (Shared) @@ -2287,7 +2391,7 @@ else version (Posix) rt_moduleTlsDtor(); version (GNUShared) { - externDFunc!("gcc.sections.elf_shared.cleanupLoadedLibraries", + externDFunc!("gcc.sections.cleanupLoadedLibraries", void function() @nogc nothrow)(); } else version (Shared) @@ -2786,7 +2890,7 @@ private size_t adjustStackSize(size_t sz) nothrow @nogc // On glibc, TLS uses the top of the stack, so add its size to the requested size version (GNU) { - sz += externDFunc!("gcc.sections.elf_shared.sizeOfTLS", + sz += externDFunc!("gcc.sections.elf.sizeOfTLS", size_t function() @nogc nothrow)(); } else diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d index c2c2333..0a8de10 100644 --- a/libphobos/libdruntime/core/thread/threadbase.d +++ b/libphobos/libdruntime/core/thread/threadbase.d @@ -10,6 +10,9 @@ * Source: $(DRUNTIMESRC core/thread/osthread.d) */ +/* NOTE: This file has been patched from the original DMD distribution to + * work with the GDC compiler. + */ module core.thread.threadbase; import core.thread.context; @@ -313,6 +316,7 @@ class ThreadBase // NOTE: This function may not be called until thread_init has // completed. See thread_suspendAll for more information // on why this might occur. + version (GNU) pragma(inline, false); return sm_this; } diff --git a/libphobos/libdruntime/gc/impl/conservative/gc.d b/libphobos/libdruntime/gc/impl/conservative/gc.d index b7bb9b0..300a32a 100644 --- a/libphobos/libdruntime/gc/impl/conservative/gc.d +++ b/libphobos/libdruntime/gc/impl/conservative/gc.d @@ -76,7 +76,7 @@ debug(PRINTF_TO_FILE) gcStartTick = MonoTime.currTime; immutable timeElapsed = MonoTime.currTime - gcStartTick; immutable secondsAsDouble = timeElapsed.total!"hnsecs" / cast(double)convert!("seconds", "hnsecs")(1); - len = fprintf(gcx_fh, "%10.6lf: ", secondsAsDouble); + len = fprintf(gcx_fh, "%10.6f: ", secondsAsDouble); } len += fprintf(gcx_fh, fmt, args); fflush(gcx_fh); @@ -159,7 +159,7 @@ debug (LOGGING) printf(" p = %p, size = %zd, parent = %p ", p, size, parent); if (file) { - printf("%s(%u)", file, line); + printf("%s(%u)", file, cast(uint)line); } printf("\n"); } diff --git a/libphobos/libdruntime/gcc/attribute.d b/libphobos/libdruntime/gcc/attribute.d index fc90d2a..d1ff5c7 100644 --- a/libphobos/libdruntime/gcc/attribute.d +++ b/libphobos/libdruntime/gcc/attribute.d @@ -20,14 +20,7 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. +deprecated("Import gcc.attributes instead") module gcc.attribute; -private struct Attribute(A...) -{ - A args; -} - -auto attribute(A...)(A args) if (A.length > 0 && is(A[0] == string)) -{ - return Attribute!A(args); -} +public import gcc.attributes; diff --git a/libphobos/libdruntime/gcc/attributes.d b/libphobos/libdruntime/gcc/attributes.d new file mode 100644 index 0000000..58a4023 --- /dev/null +++ b/libphobos/libdruntime/gcc/attributes.d @@ -0,0 +1,605 @@ +// GNU D Compiler attribute support declarations. +// Copyright (C) 2021 Free Software Foundation, Inc. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +module gcc.attributes; + +// Private helper templates. +private struct Attribute(A...) +{ + A arguments; +} + +private enum bool isStringValue(alias T) = is(typeof(T) == string); + +private enum bool isStringOrIntValue(alias T) + = is(typeof(T) == string) || is(typeof(T) == int); + +private template allSatisfy(alias F, T...) +{ + static if (T.length == 0) + enum allSatisfy = true; + else static if (T.length == 1) + enum allSatisfy = F!(T[0]); + else + { + enum allSatisfy = allSatisfy!(F, T[ 0 .. $/2]) + && allSatisfy!(F, T[$/2 .. $ ]); + } +} + +/** + * Generic entrypoint for applying GCC attributes to a function or type. + * There is no type checking done, as well as no deprecation path for + * attributes removed from the compiler. So the recommendation is to use any + , of the other UDAs available unless it is a target-specific attribute. + * + * Function attributes introduced by the @attribute UDA are used in the + * declaration of a function, followed by an attribute name string and + * any arguments separated by commas enclosed in parentheses. + * + * Example: + * --- + * import gcc.attributes; + * + * @attribute("regparm", 1) int func(int size); + * --- + */ +@system +auto attribute(A...)(A arguments) + if (A.length > 0 && is(A[0] == string)) +{ + return Attribute!A(arguments); +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// Supported common attributes exposed by GDC. +// +/////////////////////////////////////////////////////////////////////////////// + +/** + * The `@alloc_size` attribute may be applied to a function that returns a + * pointer and takes at least one argument of an integer or enumerated type. + * It indicates that the returned pointer points to memory whose size is given + * by the function argument at `sizeArgIdx`, or by the product of the arguments + * at `sizeArgIdx` and `numArgIdx`. Meaningful sizes are positive values less + * than `ptrdiff_t.max`. Unless `zeroBasedNumbering` is true, argument + * numbering starts at one for ordinary functions, and at two for non-static + * member functions. + * + * If `numArgIdx` is less than `0`, it is taken to mean there is no argument + * specifying the element count. + * + * Example: + * --- + * import gcc.attributes; + * + * @alloc_size(1) extern(C) void* malloc(size_t size); + * @alloc_size(3,2) extern(C) void* reallocarray(void *ptr, size_t nmemb, + * size_t size); + * @alloc_size(1,2) void* my_calloc(size_t element_size, size_t count, + * bool irrelevant); + * --- + */ +auto alloc_size(int sizeArgIdx) +{ + return attribute("alloc_size", sizeArgIdx); +} + +/// ditto +auto alloc_size(int sizeArgIdx, int numArgIdx) +{ + return attribute("alloc_size", sizeArgIdx, numArgIdx); +} + +/// ditto +auto alloc_size(int sizeArgIdx, int numArgIdx, bool zeroBasedNumbering) +{ + return attribute("alloc_size", sizeArgIdx, numArgIdx, zeroBasedNumbering); +} + +auto alloc_size(A...)(A arguments) +{ + assert(false, "alloc_size attribute argument value is not an integer constant"); +} + +/** + * The `@always_inline` attribute inlines the function independent of any + * restrictions that otherwise apply to inlining. Failure to inline such a + * function is diagnosed as an error. + * + * Example: + * --- + * import gcc.attributes; + * + * @always_inline int func(); + * --- + */ +enum always_inline = attribute("always_inline"); + +/** + * The `@cold` attribute on functions is used to inform the compiler that the + * function is unlikely to be executed. The function is optimized for size + * rather than speed and on many targets it is placed into a special subsection + * of the text section so all cold functions appear close together, improving + * code locality of non-cold parts of program. The paths leading to calls of + * cold functions within code are considered to be cold too. + * + * Example: + * --- + * import gcc.attributes; + * + * @cold int func(); + * --- + */ +enum cold = attribute("cold"); + +/** + * The `@flatten` attribute is used to inform the compiler that every call + * inside this function should be inlined, if possible. Functions declared with + * attribute `@noinline` and similar are not inlined. + * + * Example: + * --- + * import gcc.attributes; + * + * @flatten int func(); + * --- + */ +enum flatten = attribute("flatten"); + +/** + * The `@no_icf` attribute prevents a functions from being merged with another + * semantically equivalent function. + * + * Example: + * --- + * import gcc.attributes; + * + * @no_icf int func(); + * --- + */ +enum no_icf = attribute("no_icf"); + +/** + * The `@noclone` attribute prevents a function from being considered for + * cloning - a mechanism that produces specialized copies of functions and + * which is (currently) performed by interprocedural constant propagation. + * + * Example: + * --- + * import gcc.attributes; + * + * @noclone int func(); + * --- + */ +enum noclone = attribute("noclone"); + +/** + * The `@noinline` attribute prevents a function from being considered for + * inlining. If the function does not have side effects, there are + * optimizations other than inlining that cause function calls to be optimized + * away, although the function call is live. To keep such calls from being + * optimized away, put `asm { ""; }` in the called function, to serve as a + * special side effect. + * + * Example: + * --- + * import gcc.attributes; + * + * @noinline int func(); + * --- + */ +enum noinline = attribute("noinline"); + +/** + * The `@noipa` attribute disables interprocedural optimizations between the + * function with this attribute and its callers, as if the body of the function + * is not available when optimizing callers and the callers are unavailable when + * optimizing the body. This attribute implies `@noinline`, `@noclone`, and + * `@no_icf` attributes. However, this attribute is not equivalent to a + * combination of other attributes, because its purpose is to suppress existing + * and future optimizations employing interprocedural analysis, including those + * that do not have an attribute suitable for disabling them individually. + * + * This attribute is supported mainly for the purpose of testing the compiler. + * + * Example: + * --- + * import gcc.attributes; + * + * @noipa int func(); + * --- + */ +enum noipa = attribute("noipa"); + +/** + * The `@optimize` attribute is used to specify that a function is to be + * compiled with different optimization options than specified on the command + * line. Valid `arguments` are constant non-negative integers and strings. + * Multiple arguments can be provided, separated by commas to specify multiple + * options. Each numeric argument specifies an optimization level. Each string + * argument that begins with the letter O refers to an optimization option such + * as `-O0` or `-Os`. Other options are taken as suffixes to the `-f` prefix + * jointly forming the name of an optimization option. + * + * Not every optimization option that starts with the `-f` prefix specified by + * the attribute necessarily has an effect on the function. The `@optimize` + * attribute should be used for debugging purposes only. It is not suitable in + * production code. + * + * Example: + * --- + * import gcc.attributes; + * + * @optimize(2) double fn0(double x); + * @optimize("2") double fn1(double x); + * @optimize("s") double fn2(double x); + * @optimize("Ofast") double fn3(double x); + * @optimize("-O2") double fn4(double x); + * @optimize("tree-vectorize") double fn5(double x); + * @optimize("-ftree-vectorize") double fn6(double x); + * @optimize("no-finite-math-only", 3) double fn7(double x); + * --- + */ +auto optimize(A...)(A arguments) + if (allSatisfy!(isStringOrIntValue, arguments)) +{ + return attribute("optimize", arguments); +} + +auto optimize(A...)(A arguments) + if (!allSatisfy!(isStringOrIntValue, arguments)) +{ + assert(false, "optimize attribute argument not a string or integer constant"); +} + +/** + * The `@restrict` attribute specifies that a function parameter is to be + * restrict-qualified in the C99 sense of the term. The parameter needs to + * boil down to either a pointer or reference type, such as a D pointer, + * class reference, or a `ref` parameter. + * + * Example: + * --- + * import gcc.attributes; + * + * void func(@restrict ref const float[16] array); + * --- + */ +enum restrict = attribute("restrict"); + +/** + * The `@section` attribute specifies that a function lives in a particular + * section. For when you need certain particular functions to appear in + * special sections. + * + * Some file formats do not support arbitrary sections so the section attribute + * is not available on all platforms. If you need to map the entire contents + * of a module to a particular section, consider using the facilities of the + * linker instead. + * + * Example: + * --- + * import gcc.attributes; + * + * @section("bar") extern void func(); + * --- + */ +auto section(string sectionName) +{ + return attribute("section", sectionName); +} + +auto section(A...)(A arguments) +{ + assert(false, "section attribute argument not a string constant"); +} + +/** + * The `@symver` attribute creates a symbol version on ELF targets. The syntax + * of the string parameter is `name@nodename`. The `name` part of the parameter + * is the actual name of the symbol by which it will be externally referenced. + * The `nodename` portion should be the name of a node specified in the version + * script supplied to the linker when building a shared library. Versioned + * symbol must be defined and must be exported with default visibility. + * + * Finally if the parameter is `name@@nodename` then in addition to creating a + * symbol version (as if `name@nodename` was used) the version will be also used + * to resolve `name` by the linker. + * + * Example: + * --- + * import gcc.attributes; + * + * @symver("foo@VERS_1") int foo_v1(); + * --- + */ +auto symver(A...)(A arguments) + if (allSatisfy!(isStringValue, arguments)) +{ + return attribute("symver", arguments); +} + +auto symver(A...)(A arguments) + if (!allSatisfy!(isStringValue, arguments)) +{ + assert(false, "symver attribute argument not a string constant"); +} + +/** + * The `@target` attribute is used to specify that a function is to be + * compiled with different target options than specified on the command line. + * One or more strings can be provided as arguments, separated by commas to + * specify multiple options. Each string consists of one or more + * comma-separated suffixes to the `-m` prefix jointly forming the name of a + * machine-dependent option. + * + * The target attribute can be used for instance to have a function compiled + * with a different ISA (instruction set architecture) than the default. + * + * The options supported are specific to each target. + * + * Example: + * --- + * import gcc.attributes; + * + * @target("arch=core2") void core2_func(); + * @target("sse3") void sse3_func(); + * --- + */ +auto target(A...)(A arguments) + if (allSatisfy!(isStringValue, arguments)) +{ + return attribute("target", arguments); +} + +auto target(A...)(A arguments) + if (!allSatisfy!(isStringValue, arguments)) +{ + assert(false, "target attribute argument not a string constant"); +} + +/** + * The `@target_clones` attribute is used to specify that a function be cloned + * into multiple versions compiled with different target `options` than + * specified on the command line. The supported options and restrictions are + * the same as for `@target` attribute. + * + * It also creates a resolver function that dynamically selects a clone suitable + * for current architecture. The resolver is created only if there is a usage + * of a function with `@target_clones` attribute. + * + * Example: + * --- + * import gcc.attributes; + * + * @target_clones("sse4.1,avx,default") double func(double x); + * --- + */ +auto target_clones(A...)(A arguments) + if (allSatisfy!(isStringValue, arguments)) +{ + return attribute("target_clones", arguments); +} + +auto target_clones(A...)(A arguments) + if (!allSatisfy!(isStringValue, arguments)) +{ + assert(false, "target attribute argument not a string constant"); +} + +/** + * The `@used` attribute, annotated to a function, means that code must be + * emitted for the function even if it appears that the function is not + * referenced. This is useful, for example, when the function is referenced + * only in inline assembly. + * + * Example: + * --- + * import gcc.attributes; + * + * @used __gshared int var = 0x1000; + * --- + */ +enum used = attribute("used"); + +/** + * The `@weak` attribute causes a declaration of an external symbol to be + * emitted as a weak symbol rather than a global. This is primarily useful in + * defining library functions that can be overridden in user code, though it can + * also be used with non-function declarations. The overriding symbol must have + * the same type as the weak symbol. In addition, if it designates a variable + * it must also have the same size and alignment as the weak symbol. + * + * Weak symbols are supported for ELF targets, and also for a.out targets when + * using the GNU assembler and linker. + * + * Example: + * --- + * import gcc.attributes; + * + * @weak int func() { return 1; } + * --- + */ +enum weak = attribute("weak"); + +/** + * The `@noplt` attribute is the counterpart to option `-fno-plt`. Calls to + * functions marked with this attribute in position-independent code do not use + * the PLT in position-independent code. + * + * In position-dependant code, a few targets also convert call to functions + * that are marked to not use the PLT to use the GOT instead. + * + * Example: + * --- + * import gcc.attributes; + * + * @noplt int func(); + * + * --- + */ +enum noplt = attribute("noplt"); + +/////////////////////////////////////////////////////////////////////////////// +// +// Attributes defined for compatibility with LDC. +// +/////////////////////////////////////////////////////////////////////////////// + +/** + * Specifies that the function returns `null` or a pointer to at least a + * certain number of allocated bytes. `sizeArgIdx` and `numArgIdx` specify + * the 0-based index of the function arguments that should be used to calculate + * the number of bytes returned. + * + * Example: + * --- + * import gcc.attributes; + * + * @allocSize(0) extern(C) void* malloc(size_t size); + * @allocSize(2,1) extern(C) void* reallocarray(void *ptr, size_t nmemb, + * size_t size); + * @allocSize(0,1) void* my_calloc(size_t element_size, size_t count, + * bool irrelevant); + * --- + */ +auto allocSize(int sizeArgIdx, int numArgIdx = int.min) +{ + return alloc_size(sizeArgIdx, numArgIdx, true); +} + +auto allocSize(A...)(A arguments) +{ + assert(false, "allocSize attribute argument value is not an integer constant"); +} + +/** + * When applied to a global symbol, the compiler, assembler, and linker are + * required to treat the symbol as if there is a reference to the symbol that + * it cannot see (which is why they have to be named). For example, it + * prevents the deletion by the linker of an unreferenced symbol. + * + * Example: + * --- + * import gcc.attributes; + * + * @assumeUsed __gshared int var = 0x1000; + * --- + */ +alias assumeUsed = used; + +/// This attribute has no effect. +enum dynamicCompile = false; + +/// ditto +enum dynamicCompileConst = false; + +/// ditto +enum dynamicCompileEmit = false; + +/** + * Explicitly sets "fast-math" for a function, enabling aggressive math + * optimizations. These optimizations may dramatically change the outcome of + * floating point calculations (e.g. because of reassociation). + * + * Example: + * --- + * import gcc.attributes; + * + * @fastmath + * double dot(double[] a, double[] b) { + * double s = 0; + * foreach(size_t i; 0..a.length) + * { + * // will result in vectorized fused-multiply-add instructions + * s += a * b; + * } + * return s; + * } + * --- + */ +enum fastmath = optimize("Ofast"); + +/** + * Adds GCC's "naked" attribute to a function, disabling function prologue / + * epilogue emission. + * Intended to be used in combination with basic `asm` statement. While using + * extended `asm` or a mixture of basic `asm` and D code may appear to work, + * they cannot be depended upon to work reliably and are not supported. + * + * Example: + * --- + * import gcc.attributes; + * + * @naked void abort() { + * asm { "ud2"; } + * } + * --- + */ +enum naked = attribute("naked"); + +/** + * Sets the optimization strategy for a function. + * Valid strategies are "none", "optsize", "minsize". The strategies are + * mutually exclusive. + * + * Example: + * --- + * import gcc.attributes; + * + * @optStrategy("none") + * int func() { + * return call(); + * } + * --- + */ +auto optStrategy(string strategy) +{ + if (strategy == "none") + return optimize("O0"); + else if (strategy == "optsize" || strategy == "minsize") + return optimize("Os"); + else + { + assert(false, "unrecognized parameter `" ~ strategy + ~ "` for `gcc.attribute.optStrategy`"); + } +} + +auto optStrategy(A...)(A arguments) +{ + assert(false, "optStrategy attribute argument value is not a string constant"); +} + +/** + * When applied to a function, specifies that the function should be optimzed + * by Graphite, GCC's polyhedral optimizer. Useful for optimizing loops for + * data locality, vectorization and parallelism. + * + * Experimental! + * + * Only effective when GDC was built with ISL included. + */ +enum polly = optimize("loop-parallelize-all", "loop-nest-optimize"); diff --git a/libphobos/libdruntime/gcc/backtrace.d b/libphobos/libdruntime/gcc/backtrace.d index 45dd011..8f5582d 100644 --- a/libphobos/libdruntime/gcc/backtrace.d +++ b/libphobos/libdruntime/gcc/backtrace.d @@ -424,8 +424,10 @@ private: import core.sys.freebsd.dlfcn; else version (NetBSD) import core.sys.netbsd.dlfcn; + else version (OpenBSD) + import core.sys.openbsd.dlfcn; else version (Solaris) - import core.sys.netbsd.dlfcn; + import core.sys.solaris.dlfcn; else version (Posix) import core.sys.posix.dlfcn; diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d index c747b51..eb83751c 100644 --- a/libphobos/libdruntime/gcc/deh.d +++ b/libphobos/libdruntime/gcc/deh.d @@ -28,17 +28,12 @@ import gcc.unwind; import gcc.unwind.pe; import gcc.builtins; import gcc.config; -import gcc.attribute; +import gcc.attributes; extern(C) { int _d_isbaseof(ClassInfo, ClassInfo); void _d_createTrace(Object, void*); - - // Not used in GDC but declaration required by rt/sections.d - struct FuncTable - { - } } /** @@ -552,7 +547,7 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti _Unwind_Ptr LPStart = 0; if (LPStartEncoding != DW_EH_PE_omit) - LPStart = read_encoded_value(context, LPStartEncoding, &p); + LPStart = read_encoded_value(context, LPStartEncoding, p); else LPStart = Start; @@ -568,14 +563,14 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti // hardcoded OS-specific format. TTypeEncoding = _TTYPE_ENCODING; } - auto TTbase = read_uleb128(&p); + auto TTbase = read_uleb128(p); TType = p + TTbase; } // The encoding and length of the call-site table; the action table // immediately follows. ubyte CSEncoding = *p++; - auto CSTableSize = read_uleb128(&p); + auto CSTableSize = read_uleb128(p); const(ubyte)* actionTable = p + CSTableSize; auto TTypeBase = base_of_encoded_value(TTypeEncoding, context); @@ -613,8 +608,8 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti _uleb128_t CSLandingPad, CSAction; do { - CSLandingPad = read_uleb128(&p); - CSAction = read_uleb128(&p); + CSLandingPad = read_uleb128(p); + CSAction = read_uleb128(p); } while (--ip); @@ -631,10 +626,10 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti while (p < actionTable) { // Note that all call-site encodings are "absolute" displacements. - auto CSStart = read_encoded_value(null, CSEncoding, &p); - auto CSLen = read_encoded_value(null, CSEncoding, &p); - auto CSLandingPad = read_encoded_value(null, CSEncoding, &p); - auto CSAction = read_uleb128(&p); + auto CSStart = read_encoded_value(null, CSEncoding, p); + auto CSLen = read_encoded_value(null, CSEncoding, p); + auto CSLandingPad = read_encoded_value(null, CSEncoding, p); + auto CSAction = read_uleb128(p); // The table is sorted, so if we've passed the ip, stop. if (ip < Start + CSStart) @@ -708,9 +703,9 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader, while (1) { auto ap = actionRecord; - auto ARFilter = read_sleb128(&ap); + auto ARFilter = read_sleb128(ap); auto apn = ap; - auto ARDisp = read_sleb128(&ap); + auto ARDisp = read_sleb128(ap); if (ARFilter == 0) { @@ -730,7 +725,7 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader, // the ClassInfo is stored. const(ubyte)* tp = TType - ARFilter * encodedSize; - auto entry = read_encoded_value_with_base(TTypeEncoding, TTypeBase, &tp); + auto entry = read_encoded_value_with_base(TTypeEncoding, TTypeBase, tp); ClassInfo ci = cast(ClassInfo)cast(void*)(entry); // D does not have catch-all handlers, and so the following @@ -805,7 +800,7 @@ version (GNU_SEH_Exceptions) void* ms_orig_context, void* ms_disp) { return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context, - ms_disp, &__gdc_personality_imp); + ms_disp, &gdc_personality); } } else version (GNU_SjLj_Exceptions) diff --git a/libphobos/libdruntime/gcc/gthread.d b/libphobos/libdruntime/gcc/gthread.d index ef35a3c27..5003637 100644 --- a/libphobos/libdruntime/gcc/gthread.d +++ b/libphobos/libdruntime/gcc/gthread.d @@ -86,10 +86,12 @@ else static if (GNU_Thread_Model == ThreadModel.Single) } else static if (GNU_Thread_Model == ThreadModel.Win32) { + import core.stdc.config; + struct __gthread_once_t { - INT done; - LONG started; + int done; + c_long started; } int __gthr_win32_key_create(__gthread_key_t* keyp, GthreadDestroyFn dtor); diff --git a/libphobos/libdruntime/gcc/sections/android.d b/libphobos/libdruntime/gcc/sections/android.d deleted file mode 100644 index 4af26b4..0000000 --- a/libphobos/libdruntime/gcc/sections/android.d +++ /dev/null @@ -1,184 +0,0 @@ -// Bionic-specific support for sections. -// Copyright (C) 2019-2021 Free Software Foundation, Inc. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// <http://www.gnu.org/licenses/>. - -module gcc.sections.android; - -version (CRuntime_Bionic): - -// debug = PRINTF; -debug(PRINTF) import core.stdc.stdio; -import core.stdc.stdlib : malloc, free; -import rt.deh, rt.minfo; -import core.sys.posix.pthread; -import core.stdc.stdlib : calloc; -import core.stdc.string : memcpy; - -struct SectionGroup -{ - static int opApply(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - static int opApplyReverse(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - @property immutable(ModuleInfo*)[] modules() const nothrow @nogc - { - return _moduleGroup.modules; - } - - @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc - { - return _moduleGroup; - } - - @property immutable(FuncTable)[] ehTables() const nothrow @nogc - { - auto pbeg = cast(immutable(FuncTable)*)&__start_deh; - auto pend = cast(immutable(FuncTable)*)&__stop_deh; - return pbeg[0 .. pend - pbeg]; - } - - @property inout(void[])[] gcRanges() inout nothrow @nogc - { - return _gcRanges[]; - } - -private: - ModuleGroup _moduleGroup; - void[][1] _gcRanges; -} - -void initSections() nothrow @nogc -{ - pthread_key_create(&_tlsKey, null); - - auto mbeg = cast(immutable ModuleInfo**)&__start_minfo; - auto mend = cast(immutable ModuleInfo**)&__stop_minfo; - _sections.moduleGroup = ModuleGroup(mbeg[0 .. mend - mbeg]); - - auto pbeg = cast(void*)&_tlsend; - auto pend = cast(void*)&__bss_end__; - // _tlsend is a 32-bit int and may not be 64-bit void*-aligned, so align pbeg. - version (D_LP64) pbeg = cast(void*)(cast(size_t)(pbeg + 7) & ~cast(size_t)7); - _sections._gcRanges[0] = pbeg[0 .. pend - pbeg]; -} - -void finiSections() nothrow @nogc -{ - pthread_key_delete(_tlsKey); -} - -void[]* initTLSRanges() nothrow @nogc -{ - return &getTLSBlock(); -} - -void finiTLSRanges(void[]* rng) nothrow @nogc -{ - .free(rng.ptr); - .free(rng); -} - -void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow -{ - dg(rng.ptr, rng.ptr + rng.length); -} - -/* NOTE: The Bionic C library ignores thread-local data stored in the normal - * .tbss/.tdata ELF sections, which are marked with the SHF_TLS/STT_TLS - * flags. So instead we roll our own by keeping TLS data in the - * .tdata/.tbss sections but removing the SHF_TLS/STT_TLS flags, and - * access the TLS data using this function and the _tlsstart/_tlsend - * symbols as delimiters. - * - * This function is called by the code emitted by the compiler. It - * is expected to translate an address in the TLS static data to - * the corresponding address in the TLS dynamic per-thread data. - */ - -extern(C) void* __tls_get_addr( void* p ) nothrow @nogc -{ - debug(PRINTF) printf(" __tls_get_addr input - %p\n", p); - immutable offset = cast(size_t)(p - cast(void*)&_tlsstart); - auto tls = getTLSBlockAlloc(); - assert(offset < tls.length); - return tls.ptr + offset; -} - -private: - -__gshared pthread_key_t _tlsKey; - -ref void[] getTLSBlock() nothrow @nogc -{ - auto pary = cast(void[]*)pthread_getspecific(_tlsKey); - if (pary is null) - { - pary = cast(void[]*).calloc(1, (void[]).sizeof); - if (pthread_setspecific(_tlsKey, pary) != 0) - { - import core.stdc.stdio; - perror("pthread_setspecific failed with"); - assert(0); - } - } - return *pary; -} - -ref void[] getTLSBlockAlloc() nothrow @nogc -{ - auto pary = &getTLSBlock(); - if (!pary.length) - { - auto pbeg = cast(void*)&_tlsstart; - auto pend = cast(void*)&_tlsend; - auto p = .malloc(pend - pbeg); - memcpy(p, pbeg, pend - pbeg); - *pary = p[0 .. pend - pbeg]; - } - return *pary; -} - -__gshared SectionGroup _sections; - -extern(C) -{ - /* Symbols created by the compiler/linker and inserted into the - * object file that 'bracket' sections. - */ - extern __gshared - { - void* __start_deh; - void* __stop_deh; - void* __start_minfo; - void* __stop_minfo; - - size_t __bss_end__; - - int _tlsstart; - int _tlsend; - } -} diff --git a/libphobos/libdruntime/gcc/sections/common.d b/libphobos/libdruntime/gcc/sections/common.d new file mode 100644 index 0000000..85fdc0e --- /dev/null +++ b/libphobos/libdruntime/gcc/sections/common.d @@ -0,0 +1,39 @@ +// Contains various utility functions used by the runtime implementation. +// Copyright (C) 2019-2021 Free Software Foundation, Inc. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +module gcc.sections.common; + +/** + * Asserts that the given condition is `true`. + * + * The assertion is independent from -release, by abort()ing. Regular assertions + * throw an AssertError and thus require an initialized GC, which might not be + * the case (yet or anymore) for the startup/shutdown code in this package + * (called by CRT ctors/dtors etc.). + */ +package(gcc) void safeAssert( + bool condition, scope string msg, scope string file = __FILE__, size_t line = __LINE__ +) nothrow @nogc @safe +{ + import core.internal.abort; + condition || abort(msg, file, line); +} diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf.d index 5b0fad9..3480fb9 100644 --- a/libphobos/libdruntime/gcc/sections/elf_shared.d +++ b/libphobos/libdruntime/gcc/sections/elf.d @@ -20,7 +20,7 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. -module gcc.sections.elf_shared; +module gcc.sections.elf; version (MIPS32) version = MIPS_Any; version (MIPS64) version = MIPS_Any; @@ -33,13 +33,13 @@ version (CRuntime_Glibc) enum SharedELF = true; else version (CRuntime_Musl) enum SharedELF = true; else version (FreeBSD) enum SharedELF = true; else version (NetBSD) enum SharedELF = true; +else version (OpenBSD) enum SharedELF = true; else version (DragonFlyBSD) enum SharedELF = true; else version (CRuntime_UClibc) enum SharedELF = true; else version (Solaris) enum SharedELF = true; else enum SharedELF = false; static if (SharedELF): -// debug = PRINTF; import core.memory; import core.stdc.config; import core.stdc.stdio; @@ -63,6 +63,12 @@ else version (NetBSD) import core.sys.netbsd.sys.elf; import core.sys.netbsd.sys.link_elf; } +else version (OpenBSD) +{ + import core.sys.openbsd.dlfcn; + import core.sys.openbsd.sys.elf; + import core.sys.openbsd.sys.link_elf; +} else version (DragonFlyBSD) { import core.sys.dragonflybsd.dlfcn; @@ -81,25 +87,14 @@ else static assert(0, "unimplemented"); } import core.sys.posix.pthread; -import gcc.builtins; -import gcc.config; import rt.deh; import rt.dmain2; import rt.minfo; import rt.util.container.array; import rt.util.container.hashtab; - -/**** - * Asserts the specified condition, independent from -release, by abort()ing. - * Regular assertions throw an AssertError and thus require an initialized - * GC, which isn't the case (yet or anymore) for the startup/shutdown code in - * this module (called by CRT ctors/dtors etc.). - */ -private void safeAssert(bool condition, scope string msg, size_t line = __LINE__) @nogc nothrow @safe -{ - import core.internal.abort; - condition || abort(msg, __FILE__, line); -} +import gcc.builtins; +import gcc.config; +import gcc.sections.common; alias DSO SectionGroup; struct DSO @@ -134,11 +129,6 @@ struct DSO return _moduleGroup; } - @property immutable(FuncTable)[] ehTables() const nothrow @nogc - { - return null; - } - @property inout(void[])[] gcRanges() inout nothrow @nogc { return _gcRanges[]; @@ -177,22 +167,12 @@ private: __gshared bool _isRuntimeInitialized; -version (FreeBSD) private __gshared void* dummy_ref; -version (DragonFlyBSD) private __gshared void* dummy_ref; -version (NetBSD) private __gshared void* dummy_ref; -version (Solaris) private __gshared void* dummy_ref; - /**** * Gets called on program startup just before GC is initialized. */ void initSections() nothrow @nogc { _isRuntimeInitialized = true; - // reference symbol to support weak linkage - version (FreeBSD) dummy_ref = &_d_dso_registry; - version (DragonFlyBSD) dummy_ref = &_d_dso_registry; - version (NetBSD) dummy_ref = &_d_dso_registry; - version (Solaris) dummy_ref = &_d_dso_registry; } @@ -208,6 +188,9 @@ alias ScanDG = void delegate(void* pbeg, void* pend) nothrow; version (Shared) { + import gcc.sections : pinLoadedLibraries, unpinLoadedLibraries, + inheritLoadedLibraries, cleanupLoadedLibraries; + /*** * Called once per thread; returns array of thread local storage ranges */ @@ -248,6 +231,7 @@ version (Shared) } // interface for core.thread to inherit loaded libraries + pragma(mangle, gcc.sections.pinLoadedLibraries.mangleof) void* pinLoadedLibraries() nothrow @nogc { auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof); @@ -266,6 +250,7 @@ version (Shared) return res; } + pragma(mangle, gcc.sections.unpinLoadedLibraries.mangleof) void unpinLoadedLibraries(void* p) nothrow @nogc { auto pary = cast(Array!(ThreadDSO)*)p; @@ -285,6 +270,7 @@ version (Shared) // Called before TLS ctors are ran, copy over the loaded libraries // of the parent thread. + pragma(mangle, gcc.sections.inheritLoadedLibraries.mangleof) void inheritLoadedLibraries(void* p) nothrow @nogc { safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread."); @@ -298,6 +284,7 @@ version (Shared) } // Called after all TLS dtors ran, decrements all remaining dlopen refs. + pragma(mangle, gcc.sections.cleanupLoadedLibraries.mangleof) void cleanupLoadedLibraries() nothrow @nogc { foreach (ref tdso; _loadedDSOs) @@ -403,12 +390,6 @@ version (Shared) */ __gshared pthread_mutex_t _handleToDSOMutex; @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow { __gshared HashTab!(void*, DSO*) x; return x; } - - /* - * Section in executable that contains copy relocations. - * Might be null when druntime is dynamically loaded by a C host. - */ - __gshared const(void)[] _copyRelocSection; } else { @@ -714,20 +695,22 @@ version (Shared) @nogc nothrow: link_map* linkMapForHandle(void* handle) { - link_map* map; - const success = dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0; - safeAssert(success, "Failed to get DSO info."); - return map; + static if (__traits(compiles, RTLD_DI_LINKMAP)) + { + link_map* map; + const success = dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0; + safeAssert(success, "Failed to get DSO info."); + return map; + } + else version (OpenBSD) + { + safeAssert(handle !is null, "Failed to get DSO info."); + return cast(link_map*)handle; + } + else + static assert(0, "unimplemented"); } - link_map* exeLinkMap(link_map* map) - { - safeAssert(map !is null, "Invalid link_map."); - while (map.l_prev !is null) - map = map.l_prev; - return map; - } - DSO* dsoForHandle(void* handle) { DSO* pdso; @@ -792,6 +775,8 @@ version (Shared) strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate else version (NetBSD) strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate + else version (OpenBSD) + strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate else version (DragonFlyBSD) strtab = cast(const(char)*)(info.dlpi_addr + dyn.d_un.d_ptr); // relocate else version (Solaris) @@ -821,9 +806,21 @@ version (Shared) void* handleForName(const char* name) { - auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY); - version (Solaris) { } - else if (handle !is null) .dlclose(handle); // drop reference count + version (Solaris) enum refCounted = false; + else version (OpenBSD) enum refCounted = false; + else enum refCounted = true; + + static if (__traits(compiles, RTLD_NOLOAD)) + enum flags = (RTLD_NOLOAD | RTLD_LAZY); + else + enum flags = RTLD_LAZY; + + auto handle = .dlopen(name, flags); + static if (refCounted) + { + if (handle !is null) + .dlclose(handle); // drop reference count + } return handle; } } @@ -917,6 +914,7 @@ bool findDSOInfoForAddr(in void* addr, dl_phdr_info* result=null) nothrow @nogc { version (linux) enum IterateManually = true; else version (NetBSD) enum IterateManually = true; + else version (OpenBSD) enum IterateManually = true; else version (Solaris) enum IterateManually = true; else enum IterateManually = false; @@ -976,29 +974,6 @@ bool findSegmentForAddr(in ref dl_phdr_info info, in void* addr, ElfW!"Phdr"* re return false; } -version (linux) import core.sys.linux.errno : program_invocation_name; -// should be in core.sys.freebsd.stdlib -version (FreeBSD) extern(C) const(char)* getprogname() nothrow @nogc; -version (DragonFlyBSD) extern(C) const(char)* getprogname() nothrow @nogc; -version (NetBSD) extern(C) const(char)* getprogname() nothrow @nogc; -version (Solaris) extern(C) const(char)* getprogname() nothrow @nogc; - -@property const(char)* progname() nothrow @nogc -{ - version (linux) return program_invocation_name; - version (FreeBSD) return getprogname(); - version (DragonFlyBSD) return getprogname(); - version (NetBSD) return getprogname(); - version (Solaris) return getprogname(); -} - -const(char)[] dsoName(const char* dlpi_name) nothrow @nogc -{ - // the main executable doesn't have a name in its dlpi_name field - const char* p = dlpi_name[0] != 0 ? dlpi_name : progname; - return p[0 .. strlen(p)]; -} - /************************** * Input: * addr an internal address of a DSO diff --git a/libphobos/libdruntime/gcc/sections/macho.d b/libphobos/libdruntime/gcc/sections/macho.d new file mode 100644 index 0000000..3ce58a5 --- /dev/null +++ b/libphobos/libdruntime/gcc/sections/macho.d @@ -0,0 +1,738 @@ +// MACHO-specific support for sections. +// Copyright (C) 2021 Free Software Foundation, Inc. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +module gcc.sections.macho; + +version (OSX): + +import core.memory; +import core.stdc.stdlib; +import core.sys.darwin.dlfcn; +import core.sys.darwin.mach.dyld; +import core.sys.darwin.mach.getsect; +import core.sys.posix.pthread; +import rt.minfo; +import rt.util.container.array; +import rt.util.container.hashtab; +import gcc.sections.common; + +version (GNU_EMUTLS) + import gcc.emutls; + +alias DSO SectionGroup; +struct DSO +{ + static int opApply(scope int delegate(ref DSO) dg) + { + foreach (dso; _loadedDSOs) + { + if (auto res = dg(*dso)) + return res; + } + return 0; + } + + static int opApplyReverse(scope int delegate(ref DSO) dg) + { + foreach_reverse (dso; _loadedDSOs) + { + if (auto res = dg(*dso)) + return res; + } + return 0; + } + + @property immutable(ModuleInfo*)[] modules() const nothrow @nogc + { + return _moduleGroup.modules; + } + + @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc + { + return _moduleGroup; + } + + @property inout(void[])[] gcRanges() inout nothrow @nogc + { + return _gcRanges[]; + } + +private: + + invariant() + { + safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO."); + } + + void** _slot; + ModuleGroup _moduleGroup; + Array!(void[]) _gcRanges; + + version (Shared) + { + Array!(void[]) _codeSegments; // array of code segments + Array!(DSO*) _deps; // D libraries needed by this DSO + void* _handle; // corresponding handle + } +} + +/**** + * Boolean flag set to true while the runtime is initialized. + */ +__gshared bool _isRuntimeInitialized; + +/**** + * Gets called on program startup just before GC is initialized. + */ +void initSections() nothrow @nogc +{ + _isRuntimeInitialized = true; +} + +/*** + * Gets called on program shutdown just after GC is terminated. + */ +void finiSections() nothrow @nogc +{ + _isRuntimeInitialized = false; +} + +alias ScanDG = void delegate(void* pbeg, void* pend) nothrow; + +version (Shared) +{ + import gcc.sections : pinLoadedLibraries, unpinLoadedLibraries, + inheritLoadedLibraries, cleanupLoadedLibraries; + + /*** + * Called once per thread; returns array of thread local storage ranges + */ + Array!(ThreadDSO)* initTLSRanges() @nogc nothrow + { + return &_loadedDSOs(); + } + + void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow + { + // Nothing to do here. tdsos used to point to the _loadedDSOs instance + // in the dying thread's TLS segment and as such is not valid anymore. + // The memory for the array contents was already reclaimed in + // cleanupLoadedLibraries(). + } + + void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow + { + version (GNU_EMUTLS) + _d_emutls_scan(dg); + else + static assert(0, "Native TLS unimplemented"); + } + + // interface for core.thread to inherit loaded libraries + pragma(mangle, gcc.sections.pinLoadedLibraries.mangleof) + void* pinLoadedLibraries() nothrow @nogc + { + auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof); + res.length = _loadedDSOs.length; + foreach (i, ref tdso; _loadedDSOs) + { + (*res)[i] = tdso; + if (tdso._addCnt) + { + // Increment the dlopen ref for explicitly loaded libraries to pin them. + const success = .dlopen(nameForDSO(tdso._pdso), RTLD_LAZY) !is null; + safeAssert(success, "Failed to increment dlopen ref."); + (*res)[i]._addCnt = 1; // new array takes over the additional ref count + } + } + return res; + } + + pragma(mangle, gcc.sections.unpinLoadedLibraries.mangleof) + void unpinLoadedLibraries(void* p) nothrow @nogc + { + auto pary = cast(Array!(ThreadDSO)*)p; + // In case something failed we need to undo the pinning. + foreach (ref tdso; *pary) + { + if (tdso._addCnt) + { + auto handle = tdso._pdso._handle; + safeAssert(handle !is null, "Invalid library handle."); + .dlclose(handle); + } + } + pary.reset(); + .free(pary); + } + + // Called before TLS ctors are ran, copy over the loaded libraries + // of the parent thread. + pragma(mangle, gcc.sections.inheritLoadedLibraries.mangleof) + void inheritLoadedLibraries(void* p) nothrow @nogc + { + safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread."); + _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p); + .free(p); + } + + // Called after all TLS dtors ran, decrements all remaining dlopen refs. + pragma(mangle, gcc.sections.cleanupLoadedLibraries.mangleof) + void cleanupLoadedLibraries() nothrow @nogc + { + foreach (ref tdso; _loadedDSOs) + { + if (tdso._addCnt == 0) continue; + + auto handle = tdso._pdso._handle; + safeAssert(handle !is null, "Invalid DSO handle."); + for (; tdso._addCnt > 0; --tdso._addCnt) + .dlclose(handle); + } + + // Free the memory for the array contents. + _loadedDSOs.reset(); + } +} +else +{ + /*** + * Called once per thread; returns array of thread local storage ranges + */ + Array!(void[])* initTLSRanges() nothrow @nogc + { + return null; + } + + void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc + { + } + + void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow + { + version (GNU_EMUTLS) + _d_emutls_scan(dg); + else + static assert(0, "Native TLS unimplemented"); + } +} + +private: + +version (Shared) +{ + /* + * Array of thread local DSO metadata for all libraries loaded and + * initialized in this thread. + * + * Note: + * A newly spawned thread will inherit these libraries. + * Note: + * We use an array here to preserve the order of + * initialization. If that became a performance issue, we + * could use a hash table and enumerate the DSOs during + * loading so that the hash table values could be sorted when + * necessary. + */ + struct ThreadDSO + { + DSO* _pdso; + static if (_pdso.sizeof == 8) uint _refCnt, _addCnt; + else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt; + else static assert(0, "unimplemented"); + alias _pdso this; + } + + @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow + { + static Array!(ThreadDSO) x; + return x; + } + + /* + * Set to true during rt_loadLibrary/rt_unloadLibrary calls. + */ + bool _rtLoading; + + /* + * Hash table to map the native handle (as returned by dlopen) + * to the corresponding DSO*, protected by a mutex. + */ + __gshared pthread_mutex_t _handleToDSOMutex; + @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow + { + __gshared HashTab!(void*, DSO*) x; + return x; + } +} +else +{ + /* + * Static DSOs loaded by the runtime linker. This includes the + * executable. These can't be unloaded. + */ + @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow + { + __gshared Array!(DSO*) x; + return x; + } + + enum _rtLoading = false; +} + +/////////////////////////////////////////////////////////////////////////////// +// Compiler to runtime interface. +/////////////////////////////////////////////////////////////////////////////// + +struct MachHeader +{ + const(mach_header)* header; // the mach header of the image + intptr_t slide; // virtural memory address slide amount +} + +/**** + * This data structure is generated by the compiler, and then passed to + * _d_dso_registry(). + */ +struct CompilerDSOData +{ + size_t _version; // currently 1 + void** _slot; // can be used to store runtime data + immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file +} + +T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; } + +/* For each shared library and executable, the compiler generates code that + * sets up CompilerDSOData and calls _d_dso_registry(). + * A pointer to that code is inserted into both the .ctors and .dtors + * segment so it gets called by the loader on startup and shutdown. + */ +extern(C) void _d_dso_registry(CompilerDSOData* data) +{ + // only one supported currently + safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version."); + + // no backlink => register + if (*data._slot is null) + { + immutable firstDSO = _loadedDSOs.empty; + if (firstDSO) initLocks(); + + DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof); + assert(typeid(DSO).initializer().ptr is null); + pdso._slot = data._slot; + *data._slot = pdso; // store backlink in library record + + pdso._moduleGroup = ModuleGroup(toRange(data._minfo_beg, data._minfo_end)); + + MachHeader header = void; + const headerFound = findImageHeaderForAddr(data._slot, header); + safeAssert(headerFound, "Failed to find image header."); + + scanSegments(header, pdso); + + version (Shared) + { + auto handle = handleForAddr(data._slot); + + getDependencies(header, pdso._deps); + pdso._handle = handle; + setDSOForHandle(pdso, pdso._handle); + + if (!_rtLoading) + { + /* This DSO was not loaded by rt_loadLibrary which + * happens for all dependencies of an executable or + * the first dlopen call from a C program. + * In this case we add the DSO to the _loadedDSOs of this + * thread with a refCnt of 1 and call the TlsCtors. + */ + immutable ushort refCnt = 1, addCnt = 0; + _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt)); + } + } + else + { + foreach (p; _loadedDSOs) + safeAssert(p !is pdso, "DSO already registered."); + _loadedDSOs.insertBack(pdso); + } + + // don't initialize modules before rt_init was called + if (_isRuntimeInitialized) + { + registerGCRanges(pdso); + // rt_loadLibrary will run tls ctors, so do this only for dlopen + immutable runTlsCtors = !_rtLoading; + runModuleConstructors(pdso, runTlsCtors); + } + } + // has backlink => unregister + else + { + DSO* pdso = cast(DSO*)*data._slot; + *data._slot = null; + + // don't finalizes modules after rt_term was called (see Bugzilla 11378) + if (_isRuntimeInitialized) + { + // rt_unloadLibrary already ran tls dtors, so do this only for dlclose + immutable runTlsDtors = !_rtLoading; + runModuleDestructors(pdso, runTlsDtors); + unregisterGCRanges(pdso); + // run finalizers after module dtors (same order as in rt_term) + version (Shared) runFinalizers(pdso); + } + + version (Shared) + { + if (!_rtLoading) + { + /* This DSO was not unloaded by rt_unloadLibrary so we + * have to remove it from _loadedDSOs here. + */ + foreach (i, ref tdso; _loadedDSOs) + { + if (tdso._pdso == pdso) + { + _loadedDSOs.remove(i); + break; + } + } + } + + unsetDSOForHandle(pdso, pdso._handle); + } + else + { + // static DSOs are unloaded in reverse order + safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one."); + _loadedDSOs.popBack(); + } + + freeDSO(pdso); + + // last DSO being unloaded => shutdown registry + if (_loadedDSOs.empty) + { + version (GNU_EMUTLS) + _d_emutls_destroy(); + version (Shared) + { + safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs."); + _handleToDSO.reset(); + } + finiLocks(); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// dynamic loading +/////////////////////////////////////////////////////////////////////////////// + +// Shared D libraries are only supported when linking against a shared druntime library. + +version (Shared) +{ + ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc + { + foreach (ref tdata; _loadedDSOs) + if (tdata._pdso == pdso) return &tdata; + return null; + } + + void incThreadRef(DSO* pdso, bool incAdd) + { + if (auto tdata = findThreadDSO(pdso)) // already initialized + { + if (incAdd && ++tdata._addCnt > 1) return; + ++tdata._refCnt; + } + else + { + foreach (dep; pdso._deps) + incThreadRef(dep, false); + immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0; + _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt)); + pdso._moduleGroup.runTlsCtors(); + } + } + + void decThreadRef(DSO* pdso, bool decAdd) + { + auto tdata = findThreadDSO(pdso); + safeAssert(tdata !is null, "Failed to find thread DSO."); + safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call."); + + if (decAdd && --tdata._addCnt > 0) return; + if (--tdata._refCnt > 0) return; + + pdso._moduleGroup.runTlsDtors(); + foreach (i, ref td; _loadedDSOs) + if (td._pdso == pdso) _loadedDSOs.remove(i); + foreach (dep; pdso._deps) + decThreadRef(dep, false); + } + + extern(C) void* rt_loadLibrary(const char* name) + { + immutable save = _rtLoading; + _rtLoading = true; + scope (exit) _rtLoading = save; + + auto handle = .dlopen(name, RTLD_LAZY); + if (handle is null) return null; + + // if it's a D library + if (auto pdso = dsoForHandle(handle)) + incThreadRef(pdso, true); + return handle; + } + + extern(C) int rt_unloadLibrary(void* handle) + { + if (handle is null) return false; + + immutable save = _rtLoading; + _rtLoading = true; + scope (exit) _rtLoading = save; + + // if it's a D library + if (auto pdso = dsoForHandle(handle)) + decThreadRef(pdso, true); + return .dlclose(handle) == 0; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// helper functions +/////////////////////////////////////////////////////////////////////////////// + +void initLocks() nothrow @nogc +{ + version (Shared) + !pthread_mutex_init(&_handleToDSOMutex, null) || assert(0); +} + +void finiLocks() nothrow @nogc +{ + version (Shared) + !pthread_mutex_destroy(&_handleToDSOMutex) || assert(0); +} + +void runModuleConstructors(DSO* pdso, bool runTlsCtors) +{ + pdso._moduleGroup.sortCtors(); + pdso._moduleGroup.runCtors(); + if (runTlsCtors) pdso._moduleGroup.runTlsCtors(); +} + +void runModuleDestructors(DSO* pdso, bool runTlsDtors) +{ + if (runTlsDtors) pdso._moduleGroup.runTlsDtors(); + pdso._moduleGroup.runDtors(); +} + +void registerGCRanges(DSO* pdso) nothrow @nogc +{ + foreach (rng; pdso._gcRanges) + GC.addRange(rng.ptr, rng.length); +} + +void unregisterGCRanges(DSO* pdso) nothrow @nogc +{ + foreach (rng; pdso._gcRanges) + GC.removeRange(rng.ptr); +} + +version (Shared) void runFinalizers(DSO* pdso) +{ + foreach (seg; pdso._codeSegments) + GC.runFinalizers(seg); +} + +void freeDSO(DSO* pdso) nothrow @nogc +{ + pdso._gcRanges.reset(); + version (Shared) + { + pdso._codeSegments.reset(); + pdso._deps.reset(); + pdso._handle = null; + } + .free(pdso); +} + +version (Shared) +{ +@nogc nothrow: + const(char)* nameForDSO(in DSO* pdso) + { + Dl_info info = void; + const success = dladdr(pdso._slot, &info) != 0; + safeAssert(success, "Failed to get DSO info."); + return info.dli_fname; + } + + DSO* dsoForHandle(void* handle) + { + DSO* pdso; + !pthread_mutex_lock(&_handleToDSOMutex) || assert(0); + if (auto ppdso = handle in _handleToDSO) + pdso = *ppdso; + !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0); + return pdso; + } + + void setDSOForHandle(DSO* pdso, void* handle) + { + !pthread_mutex_lock(&_handleToDSOMutex) || assert(0); + safeAssert(handle !in _handleToDSO, "DSO already registered."); + _handleToDSO[handle] = pdso; + !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0); + } + + void unsetDSOForHandle(DSO* pdso, void* handle) + { + !pthread_mutex_lock(&_handleToDSOMutex) || assert(0); + safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO."); + _handleToDSO.remove(handle); + !pthread_mutex_unlock(&_handleToDSOMutex) || assert(0); + } + + void getDependencies(in MachHeader info, ref Array!(DSO*) deps) + { + // FIXME: Not implemented yet. + } + + void* handleForName(const char* name) + { + auto handle = .dlopen(name, RTLD_NOLOAD | RTLD_LAZY); + if (handle !is null) .dlclose(handle); // drop reference count + return handle; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Mach-O program header iteration +/////////////////////////////////////////////////////////////////////////////// + +/************ + * Scan segments in the image header and store + * the writeable data segments in *pdso. + */ + +void scanSegments(in MachHeader info, DSO* pdso) +{ + foreach (e; dataSegs) + { + auto sect = getSection(info.header, info.slide, e.seg.ptr, e.sect.ptr); + if (sect != null) + pdso._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]); + } + + version (Shared) + { + void[] text = getSection(info.header, info.slide, "__TEXT", "__text"); + if (!text) + assert(0, "Failed to get text section."); + pdso._codeSegments.insertBack(text); + } +} + +/************************** + * Input: + * result where the output is to be written + * Returns: + * true if found, and *result is filled in + */ + +bool findImageHeaderForAddr(in void* addr, out MachHeader result) +{ + Dl_info info; + if (dladdr(addr, &info) == 0) + return false; + + foreach (i; 0 .. _dyld_image_count()) + { + if (info.dli_fbase == _dyld_get_image_header(i)) + { + result.header = cast(const(mach_header)*)info.dli_fbase; + result.slide = _dyld_get_image_vmaddr_slide(i); + return true; + } + } + return false; +} + +/************************** + * Input: + * addr an internal address of a DSO + * Returns: + * the dlopen handle for that DSO or null if addr is not within a loaded DSO + */ +version (Shared) void* handleForAddr(void* addr) nothrow @nogc +{ + Dl_info info = void; + if (dladdr(addr, &info) != 0) + return handleForName(info.dli_fname); + return null; +} + +struct SegRef +{ + string seg; + string sect; +} + +static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA}, + {SEG_DATA, SECT_BSS}, + {SEG_DATA, SECT_COMMON}]; + +/** + * Returns the section for the named section in the named segment + * for the mach_header pointer passed, or null if not found. + */ +ubyte[] getSection(in mach_header* header, intptr_t slide, + in char* segmentName, in char* sectionName) +{ + version (D_LP64) + { + assert(header.magic == MH_MAGIC_64); + auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header, + segmentName, + sectionName); + } + else + { + assert(header.magic == MH_MAGIC); + auto sect = getsectbynamefromheader(header, + segmentName, + sectionName); + } + + if (sect !is null && sect.size > 0) + return (cast(ubyte*)sect.addr + slide)[0 .. cast(size_t)sect.size]; + return null; +} diff --git a/libphobos/libdruntime/gcc/sections/osx.d b/libphobos/libdruntime/gcc/sections/osx.d deleted file mode 100644 index 3e3db70..0000000 --- a/libphobos/libdruntime/gcc/sections/osx.d +++ /dev/null @@ -1,284 +0,0 @@ -// OSX-specific support for sections. -// Copyright (C) 2019-2021 Free Software Foundation, Inc. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// <http://www.gnu.org/licenses/>. - -module gcc.sections.osx; - -version (OSX): - -// debug = PRINTF; -import core.stdc.stdio; -import core.stdc.string, core.stdc.stdlib; -import core.sys.posix.pthread; -import core.sys.darwin.mach.dyld; -import core.sys.darwin.mach.getsect; -import rt.deh, rt.minfo; -import rt.util.container.array; - -struct SectionGroup -{ - static int opApply(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - static int opApplyReverse(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - @property immutable(ModuleInfo*)[] modules() const nothrow @nogc - { - return _moduleGroup.modules; - } - - @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc - { - return _moduleGroup; - } - - @property inout(void[])[] gcRanges() inout nothrow @nogc - { - return _gcRanges[]; - } - - @property immutable(FuncTable)[] ehTables() const nothrow @nogc - { - return _ehTables[]; - } - -private: - immutable(FuncTable)[] _ehTables; - ModuleGroup _moduleGroup; - Array!(void[]) _gcRanges; - immutable(void)[][2] _tlsImage; -} - -/**** - * Boolean flag set to true while the runtime is initialized. - */ -__gshared bool _isRuntimeInitialized; - -/**** - * Gets called on program startup just before GC is initialized. - */ -void initSections() nothrow @nogc -{ - pthread_key_create(&_tlsKey, null); - _dyld_register_func_for_add_image(§ions_osx_onAddImage); - _isRuntimeInitialized = true; -} - -/*** - * Gets called on program shutdown just after GC is terminated. - */ -void finiSections() nothrow @nogc -{ - _sections._gcRanges.reset(); - pthread_key_delete(_tlsKey); - _isRuntimeInitialized = false; -} - -void[]* initTLSRanges() nothrow @nogc -{ - return &getTLSBlock(); -} - -void finiTLSRanges(void[]* rng) nothrow @nogc -{ - .free(rng.ptr); - .free(rng); -} - -void scanTLSRanges(void[]* rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow -{ - dg(rng.ptr, rng.ptr + rng.length); -} - -// NOTE: The Mach-O object file format does not allow for thread local -// storage declarations. So instead we roll our own by putting tls -// into the __tls_data and the __tlscoal_nt sections. -// -// This function is called by the code emitted by the compiler. It -// is expected to translate an address into the TLS static data to -// the corresponding address in the TLS dynamic per-thread data. - -// NB: the compiler mangles this function as '___tls_get_addr' even though it is extern(D) -extern(D) void* ___tls_get_addr( void* p ) -{ - immutable off = tlsOffset(p); - auto tls = getTLSBlockAlloc(); - assert(off < tls.length); - return tls.ptr + off; -} - -private: - -__gshared pthread_key_t _tlsKey; - -size_t tlsOffset(void* p) -in -{ - assert(_sections._tlsImage[0].ptr !is null || - _sections._tlsImage[1].ptr !is null); -} -body -{ - // NOTE: p is an address in the TLS static data emitted by the - // compiler. If it isn't, something is disastrously wrong. - immutable off0 = cast(size_t)(p - _sections._tlsImage[0].ptr); - if (off0 < _sections._tlsImage[0].length) - { - return off0; - } - immutable off1 = cast(size_t)(p - _sections._tlsImage[1].ptr); - if (off1 < _sections._tlsImage[1].length) - { - size_t sz = (_sections._tlsImage[0].length + 15) & ~cast(size_t)15; - return sz + off1; - } - assert(0); -} - -ref void[] getTLSBlock() nothrow @nogc -{ - auto pary = cast(void[]*)pthread_getspecific(_tlsKey); - if (pary is null) - { - pary = cast(void[]*).calloc(1, (void[]).sizeof); - if (pthread_setspecific(_tlsKey, pary) != 0) - { - import core.stdc.stdio; - perror("pthread_setspecific failed with"); - assert(0); - } - } - return *pary; -} - -ref void[] getTLSBlockAlloc() -{ - auto pary = &getTLSBlock(); - if (!pary.length) - { - auto imgs = _sections._tlsImage; - immutable sz0 = (imgs[0].length + 15) & ~cast(size_t)15; - immutable sz2 = sz0 + imgs[1].length; - auto p = .malloc(sz2); - memcpy(p, imgs[0].ptr, imgs[0].length); - memcpy(p + sz0, imgs[1].ptr, imgs[1].length); - *pary = p[0 .. sz2]; - } - return *pary; -} - -__gshared SectionGroup _sections; - -extern (C) void sections_osx_onAddImage(in mach_header* h, intptr_t slide) -{ - foreach (e; dataSegs) - { - auto sect = getSection(h, slide, e.seg.ptr, e.sect.ptr); - if (sect != null) - _sections._gcRanges.insertBack((cast(void*)sect.ptr)[0 .. sect.length]); - } - - auto minfosect = getSection(h, slide, "__DATA", "__minfodata"); - if (minfosect != null) - { - // no support for multiple images yet - // take the sections from the last static image which is the executable - if (_isRuntimeInitialized) - { - fprintf(stderr, "Loading shared libraries isn't yet supported on OSX.\n"); - return; - } - else if (_sections.modules.ptr !is null) - { - fprintf(stderr, "Shared libraries are not yet supported on OSX.\n"); - } - - debug(PRINTF) printf(" minfodata\n"); - auto p = cast(immutable(ModuleInfo*)*)minfosect.ptr; - immutable len = minfosect.length / (*p).sizeof; - - _sections._moduleGroup = ModuleGroup(p[0 .. len]); - } - - auto ehsect = getSection(h, slide, "__DATA", "__deh_eh"); - if (ehsect != null) - { - debug(PRINTF) printf(" deh_eh\n"); - auto p = cast(immutable(FuncTable)*)ehsect.ptr; - immutable len = ehsect.length / (*p).sizeof; - - _sections._ehTables = p[0 .. len]; - } - - auto tlssect = getSection(h, slide, "__DATA", "__tls_data"); - if (tlssect != null) - { - debug(PRINTF) printf(" tls_data %p %p\n", tlssect.ptr, tlssect.ptr + tlssect.length); - _sections._tlsImage[0] = (cast(immutable(void)*)tlssect.ptr)[0 .. tlssect.length]; - } - - auto tlssect2 = getSection(h, slide, "__DATA", "__tlscoal_nt"); - if (tlssect2 != null) - { - debug(PRINTF) printf(" tlscoal_nt %p %p\n", tlssect2.ptr, tlssect2.ptr + tlssect2.length); - _sections._tlsImage[1] = (cast(immutable(void)*)tlssect2.ptr)[0 .. tlssect2.length]; - } -} - -struct SegRef -{ - string seg; - string sect; -} - -static immutable SegRef[] dataSegs = [{SEG_DATA, SECT_DATA}, - {SEG_DATA, SECT_BSS}, - {SEG_DATA, SECT_COMMON}]; - -ubyte[] getSection(in mach_header* header, intptr_t slide, - in char* segmentName, in char* sectionName) -{ - version (X86) - { - assert(header.magic == MH_MAGIC); - auto sect = getsectbynamefromheader(header, - segmentName, - sectionName); - } - else version (X86_64) - { - assert(header.magic == MH_MAGIC_64); - auto sect = getsectbynamefromheader_64(cast(mach_header_64*)header, - segmentName, - sectionName); - } - else - static assert(0, "unimplemented"); - - if (sect !is null && sect.size > 0) - return (cast(ubyte*)sect.addr + slide)[0 .. cast(size_t)sect.size]; - return null; -} diff --git a/libphobos/libdruntime/gcc/sections/package.d b/libphobos/libdruntime/gcc/sections/package.d index fdaf039..1e887cd 100644 --- a/libphobos/libdruntime/gcc/sections/package.d +++ b/libphobos/libdruntime/gcc/sections/package.d @@ -22,27 +22,31 @@ module gcc.sections; -version (CRuntime_Glibc) - public import gcc.sections.elf_shared; -else version (CRuntime_Musl) - public import gcc.sections.elf_shared; -else version (CRuntime_UClibc) - public import gcc.sections.elf_shared; -else version (FreeBSD) - public import gcc.sections.elf_shared; -else version (NetBSD) - public import gcc.sections.elf_shared; -else version (DragonFlyBSD) - public import gcc.sections.elf_shared; -else version (Solaris) - public import gcc.sections.elf_shared; -else version (OSX) - public import gcc.sections.osx; -else version (CRuntime_DigitalMars) - public import gcc.sections.win32; -else version (CRuntime_Microsoft) - public import gcc.sections.win64; -else version (CRuntime_Bionic) - public import gcc.sections.android; +version (CRuntime_Glibc) version = SectionsElf; +version (CRuntime_Musl) version = SectionsElf; +version (CRuntime_UClibc) version = SectionsElf; +version (FreeBSD) version = SectionsElf; +version (NetBSD) version = SectionsElf; +version (OpenBSD) version = SectionsElf; +version (DragonFlyBSD) version = SectionsElf; +version (Solaris) version = SectionsElf; +version (OSX) version = SectionsMacho; +version (Windows) version = SectionsPeCoff; + +version (SectionsElf) + public import gcc.sections.elf; +else version (SectionsMacho) + public import gcc.sections.macho; +else version (SectionsPeCoff) + public import gcc.sections.pecoff; else static assert(0, "unimplemented"); + +version (Shared) +{ + // interface for core.thread to inherit loaded libraries + void* pinLoadedLibraries() nothrow @nogc; + void unpinLoadedLibraries(void* p) nothrow @nogc; + void inheritLoadedLibraries(void* p) nothrow @nogc; + void cleanupLoadedLibraries() nothrow @nogc; +} diff --git a/libphobos/libdruntime/gcc/sections/pecoff.d b/libphobos/libdruntime/gcc/sections/pecoff.d new file mode 100644 index 0000000..ed0340e --- /dev/null +++ b/libphobos/libdruntime/gcc/sections/pecoff.d @@ -0,0 +1,826 @@ +// PE/COFF-specific support for sections. +// Copyright (C) 2021 Free Software Foundation, Inc. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +module gcc.sections.pecoff; + +version (Windows): + +import core.memory; +import core.stdc.stdlib; +import core.sys.windows.winbase; +import core.sys.windows.windef; +import core.sys.windows.winnt; +import rt.minfo; +import rt.util.container.array; +import rt.util.container.hashtab; +import gcc.sections.common; + +version (GNU_EMUTLS) + import gcc.emutls; + +alias DSO SectionGroup; +struct DSO +{ + static int opApply(scope int delegate(ref DSO) dg) + { + foreach (dso; _loadedDSOs) + { + if (auto res = dg(*dso)) + return res; + } + return 0; + } + + static int opApplyReverse(scope int delegate(ref DSO) dg) + { + foreach_reverse (dso; _loadedDSOs) + { + if (auto res = dg(*dso)) + return res; + } + return 0; + } + + @property immutable(ModuleInfo*)[] modules() const nothrow @nogc + { + return _moduleGroup.modules; + } + + @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc + { + return _moduleGroup; + } + + @property inout(void[])[] gcRanges() inout nothrow @nogc + { + return _gcRanges[]; + } + +private: + + invariant() + { + safeAssert(_moduleGroup.modules.length > 0, "No modules for DSO."); + } + + void** _slot; + ModuleGroup _moduleGroup; + Array!(void[]) _gcRanges; + + version (Shared) + { + Array!(void[]) _codeSegments; // array of code segments + Array!(DSO*) _deps; // D libraries needed by this DSO + void* _handle; // corresponding handle + } +} + +/**** + * Boolean flag set to true while the runtime is initialized. + */ +__gshared bool _isRuntimeInitialized; + +/**** + * Gets called on program startup just before GC is initialized. + */ +void initSections() nothrow @nogc +{ + _isRuntimeInitialized = true; +} + +/*** + * Gets called on program shutdown just after GC is terminated. + */ +void finiSections() nothrow @nogc +{ + _isRuntimeInitialized = false; +} + +alias ScanDG = void delegate(void* pbeg, void* pend) nothrow; + +version (Shared) +{ + import gcc.sections : pinLoadedLibraries, unpinLoadedLibraries, + inheritLoadedLibraries, cleanupLoadedLibraries; + + /*** + * Called once per thread; returns array of thread local storage ranges + */ + Array!(ThreadDSO)* initTLSRanges() @nogc nothrow + { + return &_loadedDSOs(); + } + + void finiTLSRanges(Array!(ThreadDSO)* tdsos) @nogc nothrow + { + // Nothing to do here. tdsos used to point to the _loadedDSOs instance + // in the dying thread's TLS segment and as such is not valid anymore. + // The memory for the array contents was already reclaimed in + // cleanupLoadedLibraries(). + } + + void scanTLSRanges(Array!(ThreadDSO)* tdsos, scope ScanDG dg) nothrow + { + version (GNU_EMUTLS) + _d_emutls_scan(dg); + else + static assert(0, "Native TLS unimplemented"); + } + + // interface for core.thread to inherit loaded libraries + pragma(mangle, gcc.sections.pinLoadedLibraries.mangleof) + void* pinLoadedLibraries() nothrow @nogc + { + auto res = cast(Array!(ThreadDSO)*)calloc(1, Array!(ThreadDSO).sizeof); + res.length = _loadedDSOs.length; + foreach (i, ref tdso; _loadedDSOs) + { + (*res)[i] = tdso; + if (tdso._addCnt) + { + // Increment the DLL ref for explicitly loaded libraries to pin them. + char[MAX_PATH] buf; + char[] buffer = buf[]; + const success = .LoadLibraryA(nameForDSO(tdso._pdso, buffer)) !is null; + safeAssert(success, "Failed to increment DLL ref."); + (*res)[i]._addCnt = 1; // new array takes over the additional ref count + } + } + return res; + } + + pragma(mangle, gcc.sections.unpinLoadedLibraries.mangleof) + void unpinLoadedLibraries(void* p) nothrow @nogc + { + auto pary = cast(Array!(ThreadDSO)*)p; + // In case something failed we need to undo the pinning. + foreach (ref tdso; *pary) + { + if (tdso._addCnt) + { + auto handle = tdso._pdso._handle; + safeAssert(handle !is null, "Invalid library handle."); + .FreeLibrary(handle); + } + } + pary.reset(); + .free(pary); + } + + // Called before TLS ctors are ran, copy over the loaded libraries + // of the parent thread. + pragma(mangle, gcc.sections.inheritLoadedLibraries.mangleof) + void inheritLoadedLibraries(void* p) nothrow @nogc + { + safeAssert(_loadedDSOs.empty, "DSOs have already been registered for this thread."); + _loadedDSOs.swap(*cast(Array!(ThreadDSO)*)p); + .free(p); + } + + // Called after all TLS dtors ran, decrements all remaining DLL refs. + pragma(mangle, gcc.sections.cleanupLoadedLibraries.mangleof) + void cleanupLoadedLibraries() nothrow @nogc + { + foreach (ref tdso; _loadedDSOs) + { + if (tdso._addCnt == 0) continue; + + auto handle = tdso._pdso._handle; + safeAssert(handle !is null, "Invalid DSO handle."); + for (; tdso._addCnt > 0; --tdso._addCnt) + .FreeLibrary(handle); + } + + // Free the memory for the array contents. + _loadedDSOs.reset(); + } +} +else +{ + /*** + * Called once per thread; returns array of thread local storage ranges + */ + Array!(void[])* initTLSRanges() nothrow @nogc + { + return null; + } + + void finiTLSRanges(Array!(void[])* rngs) nothrow @nogc + { + } + + void scanTLSRanges(Array!(void[])* rngs, scope ScanDG dg) nothrow + { + version (GNU_EMUTLS) + _d_emutls_scan(dg); + else + static assert(0, "Native TLS unimplemented"); + } +} + +private: + +version (Shared) +{ + /* + * Array of thread local DSO metadata for all libraries loaded and + * initialized in this thread. + * + * Note: + * A newly spawned thread will inherit these libraries. + * Note: + * We use an array here to preserve the order of + * initialization. If that became a performance issue, we + * could use a hash table and enumerate the DSOs during + * loading so that the hash table values could be sorted when + * necessary. + */ + struct ThreadDSO + { + DSO* _pdso; + static if (_pdso.sizeof == 8) uint _refCnt, _addCnt; + else static if (_pdso.sizeof == 4) ushort _refCnt, _addCnt; + else static assert(0, "unimplemented"); + alias _pdso this; + } + + @property ref Array!(ThreadDSO) _loadedDSOs() @nogc nothrow + { + static Array!(ThreadDSO) x; + return x; + } + + /* + * Set to true during rt_loadLibrary/rt_unloadLibrary calls. + */ + bool _rtLoading; + + /* + * Hash table to map the native handle (as returned by dlopen) + * to the corresponding DSO*, protected by a mutex. + */ + __gshared CRITICAL_SECTION _handleToDSOMutex; + @property ref HashTab!(void*, DSO*) _handleToDSO() @nogc nothrow + { + __gshared HashTab!(void*, DSO*) x; + return x; + } +} +else +{ + /* + * Static DSOs loaded by the runtime linker. This includes the + * executable. These can't be unloaded. + */ + @property ref Array!(DSO*) _loadedDSOs() @nogc nothrow + { + __gshared Array!(DSO*) x; + return x; + } + + enum _rtLoading = false; +} + +/////////////////////////////////////////////////////////////////////////////// +// Compiler to runtime interface. +/////////////////////////////////////////////////////////////////////////////// + +/**** + * This data structure is generated by the compiler, and then passed to + * _d_dso_registry(). + */ +struct CompilerDSOData +{ + size_t _version; // currently 1 + void** _slot; // can be used to store runtime data + immutable(object.ModuleInfo*)* _minfo_beg, _minfo_end; // array of modules in this object file +} + +T[] toRange(T)(T* beg, T* end) { return beg[0 .. end - beg]; } + +/* For each shared library and executable, the compiler generates code that + * sets up CompilerDSOData and calls _d_dso_registry(). + * A pointer to that code is inserted into both the .ctors and .dtors + * segment so it gets called by the loader on startup and shutdown. + */ +extern(C) void _d_dso_registry(CompilerDSOData* data) +{ + // only one supported currently + safeAssert(data._version >= 1, "Incompatible compiler-generated DSO data version."); + + // no backlink => register + if (*data._slot is null) + { + immutable firstDSO = _loadedDSOs.empty; + if (firstDSO) initLocks(); + + DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof); + assert(typeid(DSO).initializer().ptr is null); + pdso._slot = data._slot; + *data._slot = pdso; // store backlink in library record + + pdso._moduleGroup = ModuleGroup(toRange(data._minfo_beg, data._minfo_end)); + + HMODULE handle = void; + const moduleFound = findModuleHandleForAddr(data._slot, handle); + safeAssert(moduleFound, "Failed to find image header."); + + scanSegments(handle, pdso); + + version (Shared) + { + getDependencies(handle, pdso._deps); + pdso._handle = handle; + setDSOForHandle(pdso, pdso._handle); + + if (!_rtLoading) + { + /* This DSO was not loaded by rt_loadLibrary which + * happens for all dependencies of an executable or + * the first dlopen call from a C program. + * In this case we add the DSO to the _loadedDSOs of this + * thread with a refCnt of 1 and call the TlsCtors. + */ + immutable ushort refCnt = 1, addCnt = 0; + _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt)); + } + } + else + { + foreach (p; _loadedDSOs) + safeAssert(p !is pdso, "DSO already registered."); + _loadedDSOs.insertBack(pdso); + } + + // don't initialize modules before rt_init was called + if (_isRuntimeInitialized) + { + registerGCRanges(pdso); + // rt_loadLibrary will run tls ctors, so do this only for dlopen + immutable runTlsCtors = !_rtLoading; + runModuleConstructors(pdso, runTlsCtors); + } + } + // has backlink => unregister + else + { + DSO* pdso = cast(DSO*)*data._slot; + *data._slot = null; + + // don't finalizes modules after rt_term was called (see Bugzilla 11378) + if (_isRuntimeInitialized) + { + // rt_unloadLibrary already ran tls dtors, so do this only for dlclose + immutable runTlsDtors = !_rtLoading; + runModuleDestructors(pdso, runTlsDtors); + unregisterGCRanges(pdso); + // run finalizers after module dtors (same order as in rt_term) + version (Shared) runFinalizers(pdso); + } + + version (Shared) + { + if (!_rtLoading) + { + /* This DSO was not unloaded by rt_unloadLibrary so we + * have to remove it from _loadedDSOs here. + */ + foreach (i, ref tdso; _loadedDSOs) + { + if (tdso._pdso == pdso) + { + _loadedDSOs.remove(i); + break; + } + } + } + + unsetDSOForHandle(pdso, pdso._handle); + } + else + { + // static DSOs are unloaded in reverse order + safeAssert(pdso == _loadedDSOs.back, "DSO being unregistered isn't current last one."); + _loadedDSOs.popBack(); + } + + freeDSO(pdso); + + // last DSO being unloaded => shutdown registry + if (_loadedDSOs.empty) + { + version (GNU_EMUTLS) + _d_emutls_destroy(); + version (Shared) + { + safeAssert(_handleToDSO.empty, "_handleToDSO not in sync with _loadedDSOs."); + _handleToDSO.reset(); + } + finiLocks(); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// dynamic loading +/////////////////////////////////////////////////////////////////////////////// + +// Shared D libraries are only supported when linking against a shared druntime library. + +version (Shared) +{ + ThreadDSO* findThreadDSO(DSO* pdso) nothrow @nogc + { + foreach (ref tdata; _loadedDSOs) + if (tdata._pdso == pdso) return &tdata; + return null; + } + + void incThreadRef(DSO* pdso, bool incAdd) + { + if (auto tdata = findThreadDSO(pdso)) // already initialized + { + if (incAdd && ++tdata._addCnt > 1) return; + ++tdata._refCnt; + } + else + { + foreach (dep; pdso._deps) + incThreadRef(dep, false); + immutable ushort refCnt = 1, addCnt = incAdd ? 1 : 0; + _loadedDSOs.insertBack(ThreadDSO(pdso, refCnt, addCnt)); + pdso._moduleGroup.runTlsCtors(); + } + } + + void decThreadRef(DSO* pdso, bool decAdd) + { + auto tdata = findThreadDSO(pdso); + safeAssert(tdata !is null, "Failed to find thread DSO."); + safeAssert(!decAdd || tdata._addCnt > 0, "Mismatching rt_unloadLibrary call."); + + if (decAdd && --tdata._addCnt > 0) return; + if (--tdata._refCnt > 0) return; + + pdso._moduleGroup.runTlsDtors(); + foreach (i, ref td; _loadedDSOs) + if (td._pdso == pdso) _loadedDSOs.remove(i); + foreach (dep; pdso._deps) + decThreadRef(dep, false); + } +} + +/*********************************** + * These are a temporary means of providing a GC hook for DLL use. They may be + * replaced with some other similar functionality later. + */ +extern (C) +{ + void* gc_getProxy(); + void gc_setProxy(void* p); + void gc_clrProxy(); + + alias void function(void*) gcSetFn; + alias void function() gcClrFn; +} + +/******************************************* + * Loads a DLL written in D with the name 'name'. + * Returns: + * opaque handle to the DLL if successfully loaded + * null if failure + */ +extern(C) void* rt_loadLibrary(const char* name) +{ + version (Shared) + { + immutable save = _rtLoading; + _rtLoading = true; + scope (exit) _rtLoading = save; + } + return initLibrary(.LoadLibraryA(name)); +} + +extern (C) void* rt_loadLibraryW(const wchar_t* name) +{ + version (Shared) + { + immutable save = _rtLoading; + _rtLoading = true; + scope (exit) _rtLoading = save; + } + return initLibrary(.LoadLibraryW(name)); +} + +void* initLibrary(void* handle) +{ + if (handle is null) + return null; + + version (Shared) + { + // if it's a D library + if (auto pdso = dsoForHandle(handle)) + incThreadRef(pdso, true); + } + gcSetFn gcSet = cast(gcSetFn) GetProcAddress(handle, "gc_setProxy"); + if (gcSet !is null) + { + // BUG: Set proxy, but too late + gcSet(gc_getProxy()); + } + return handle; +} + +/************************************* + * Unloads DLL that was previously loaded by rt_loadLibrary(). + * Input: + * handle the handle returned by rt_loadLibrary() + * Returns: + * 1 succeeded + * 0 some failure happened + */ +extern(C) int rt_unloadLibrary(void* handle) +{ + if (handle is null) + return false; + + version (Shared) + { + immutable save = _rtLoading; + _rtLoading = true; + scope (exit) _rtLoading = save; + + // if it's a D library + if (auto pdso = dsoForHandle(handle)) + decThreadRef(pdso, true); + } + gcClrFn gcClr = cast(gcClrFn) GetProcAddress(handle, "gc_clrProxy"); + if (gcClr !is null) + gcClr(); + return .FreeLibrary(handle) != 0; +} + +/////////////////////////////////////////////////////////////////////////////// +// helper functions +/////////////////////////////////////////////////////////////////////////////// + +void initLocks() nothrow @nogc +{ + version (Shared) + InitializeCriticalSection(&_handleToDSOMutex); +} + +void finiLocks() nothrow @nogc +{ + version (Shared) + DeleteCriticalSection(&_handleToDSOMutex); +} + +void runModuleConstructors(DSO* pdso, bool runTlsCtors) +{ + pdso._moduleGroup.sortCtors(); + pdso._moduleGroup.runCtors(); + if (runTlsCtors) pdso._moduleGroup.runTlsCtors(); +} + +void runModuleDestructors(DSO* pdso, bool runTlsDtors) +{ + if (runTlsDtors) pdso._moduleGroup.runTlsDtors(); + pdso._moduleGroup.runDtors(); +} + +void registerGCRanges(DSO* pdso) nothrow @nogc +{ + foreach (rng; pdso._gcRanges) + GC.addRange(rng.ptr, rng.length); +} + +void unregisterGCRanges(DSO* pdso) nothrow @nogc +{ + foreach (rng; pdso._gcRanges) + GC.removeRange(rng.ptr); +} + +version (Shared) void runFinalizers(DSO* pdso) +{ + foreach (seg; pdso._codeSegments) + GC.runFinalizers(seg); +} + +void freeDSO(DSO* pdso) nothrow @nogc +{ + pdso._gcRanges.reset(); + version (Shared) + { + pdso._codeSegments.reset(); + pdso._deps.reset(); + pdso._handle = null; + } + .free(pdso); +} + +version (Shared) +{ +@nogc nothrow: + const(char)* nameForDSO(DSO* pdso, ref char[] buffer) + { + const success = GetModuleFileNameA(pdso._handle, buffer.ptr, cast(DWORD)buffer.length) != 0; + safeAssert(success, "Failed to get DLL name."); + return buffer.ptr; + } + + DSO* dsoForHandle(in void* handle) + { + DSO* pdso; + .EnterCriticalSection(&_handleToDSOMutex); + if (auto ppdso = handle in _handleToDSO) + pdso = *ppdso; + .LeaveCriticalSection(&_handleToDSOMutex); + return pdso; + } + + void setDSOForHandle(DSO* pdso, void* handle) + { + .EnterCriticalSection(&_handleToDSOMutex); + safeAssert(handle !in _handleToDSO, "DSO already registered."); + _handleToDSO[handle] = pdso; + .LeaveCriticalSection(&_handleToDSOMutex); + } + + void unsetDSOForHandle(DSO* pdso, void* handle) + { + .EnterCriticalSection(&_handleToDSOMutex); + safeAssert(_handleToDSO[handle] == pdso, "Handle doesn't match registered DSO."); + _handleToDSO.remove(handle); + .LeaveCriticalSection(&_handleToDSOMutex); + } + + void getDependencies(in HMODULE handle, ref Array!(DSO*) deps) + { + auto nthdr = getNTHeader(handle); + auto import_entry = nthdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + auto addr = import_entry.VirtualAddress; + auto datasize = import_entry.Size; + + if (addr == 0 && datasize == 0) + { + // Maybe the optional header isn't there, look for the section. + foreach (section; getSectionHeader(handle)) + { + if (!compareSectionName(section, ".idata")) + continue; + addr = section.VirtualAddress; + datasize = section.Misc.VirtualSize; + break; + } + if (datasize == 0) + return; + } + else + { + bool foundSection = false; + foreach (section; getSectionHeader(handle)) + { + if (!compareSectionName(section, ".idata")) + continue; + // Section containing import table has no contents. + if (section.Misc.VirtualSize == 0) + return; + foundSection = true; + break; + } + // There is an import table, but the section containing it could not be found + if (!foundSection) + return; + } + + // Get the names of each DLL + for (uint i = 0; i + IMAGE_IMPORT_DESCRIPTOR.sizeof <= datasize; + i += IMAGE_IMPORT_DESCRIPTOR.sizeof) + { + const data = cast(PIMAGE_IMPORT_DESCRIPTOR)(handle + addr + i); + if (data.Name == 0) + break; + + // dll name of dependency + auto name = cast(char*)(handle + data.Name); + // get handle without loading the library + auto libhandle = handleForName(name); + // the runtime linker has already loaded all dependencies + safeAssert(handle !is null, "Failed to get library handle."); + // if it's a D library + if (auto pdso = dsoForHandle(handle)) + deps.insertBack(pdso); // append it to the dependencies + } + } + + void* handleForName(const char* name) + { + return GetModuleHandleA(name); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// PE/COFF program header iteration +/////////////////////////////////////////////////////////////////////////////// + +bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc +{ + if (name[] != cast(char[])section.Name[0 .. name.length]) + return false; + return name.length == 8 || section.Name[name.length] == 0; +} + +/************ + * Scan segments in the image header and store + * the writeable data segments in *pdso. + */ + +void scanSegments(in HMODULE handle, DSO* pdso) nothrow @nogc +{ + foreach (section; getSectionHeader(handle)) + { + // the ".data" image section includes both object file sections ".data" and ".bss" + if (compareSectionName(section, ".data")) + { + auto data = cast(void*)handle + section.VirtualAddress; + pdso._gcRanges.insertBack(data[0 .. section.Misc.VirtualSize]); + continue; + } + + version (Shared) + { + if (compareSectionName(section, ".text")) + { + auto text = cast(void*)handle + section.VirtualAddress; + pdso._codeSegments.insertBack(text[0 .. section.Misc.VirtualSize]); + continue; + } + } + } +} + +/************************** + * Input: + * handle where the output is to be written + * Returns: + * true if found, and *handle is filled in + */ + +bool findModuleHandleForAddr(in void* addr, out HMODULE handle) nothrow @nogc +{ + if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + cast(const(wchar)*) addr, &handle)) + return true; + + return false; +} + +/** + * Returns the image NT header for the HMODULE handle passed, + * or null if not found. + */ +PIMAGE_NT_HEADERS getNTHeader(in HMODULE handle) nothrow @nogc +{ + auto doshdr = cast(PIMAGE_DOS_HEADER)handle; + if (doshdr.e_magic != IMAGE_DOS_SIGNATURE) + return null; + + return cast(typeof(return))(cast(void*)doshdr + doshdr.e_lfanew); +} + +/** + * Returns the image section header for the HMODULE handle passed, + * or null if not found. + */ +IMAGE_SECTION_HEADER[] getSectionHeader(in HMODULE handle) nothrow @nogc +{ + if (auto nthdr = getNTHeader(handle)) + { + const void* opthdr = &nthdr.OptionalHeader; + const offset = nthdr.FileHeader.SizeOfOptionalHeader; + const length = nthdr.FileHeader.NumberOfSections; + return (cast(PIMAGE_SECTION_HEADER)(opthdr + offset))[0 .. length]; + } + return null; +} diff --git a/libphobos/libdruntime/gcc/sections/win32.d b/libphobos/libdruntime/gcc/sections/win32.d deleted file mode 100644 index b355dfc..0000000 --- a/libphobos/libdruntime/gcc/sections/win32.d +++ /dev/null @@ -1,183 +0,0 @@ -// Win32-specific support for sections. -// Copyright (C) 2019-2021 Free Software Foundation, Inc. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// <http://www.gnu.org/licenses/>. - -module gcc.sections.win32; - -version (CRuntime_DigitalMars): - -// debug = PRINTF; -debug(PRINTF) import core.stdc.stdio; -import rt.minfo; -import core.stdc.stdlib : malloc, free; - -struct SectionGroup -{ - static int opApply(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - static int opApplyReverse(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - @property immutable(ModuleInfo*)[] modules() const nothrow @nogc - { - return _moduleGroup.modules; - } - - @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc - { - return _moduleGroup; - } - - @property inout(void[])[] gcRanges() inout nothrow @nogc - { - return _gcRanges[]; - } - -private: - ModuleGroup _moduleGroup; - void[][] _gcRanges; -} - -shared(bool) conservative; - -void initSections() nothrow @nogc -{ - _sections._moduleGroup = ModuleGroup(getModuleInfos()); - - import rt.sections; - conservative = !scanDataSegPrecisely(); - - if (conservative) - { - _sections._gcRanges = (cast(void[]*) malloc(2 * (void[]).sizeof))[0..2]; - - auto databeg = cast(void*)&_xi_a; - auto dataend = cast(void*)_moduleinfo_array.ptr; - _sections._gcRanges[0] = databeg[0 .. dataend - databeg]; - - // skip module info and CONST segment - auto bssbeg = cast(void*)&_edata; - auto bssend = cast(void*)&_end; - _sections._gcRanges[1] = bssbeg[0 .. bssend - bssbeg]; - } - else - { - size_t count = &_DPend - &_DPbegin; - auto ranges = cast(void[]*) malloc(count * (void[]).sizeof); - size_t r = 0; - void* prev = null; - for (size_t i = 0; i < count; i++) - { - void* addr = (&_DPbegin)[i]; - if (prev + (void*).sizeof == addr) - ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof]; - else - ranges[r++] = (cast(void**)addr)[0..1]; - prev = addr; - } - _sections._gcRanges = ranges[0..r]; - } -} - -void finiSections() nothrow @nogc -{ - free(_sections._gcRanges.ptr); -} - -void[] initTLSRanges() nothrow @nogc -{ - auto pbeg = cast(void*)&_tlsstart; - auto pend = cast(void*)&_tlsend; - return pbeg[0 .. pend - pbeg]; -} - -void finiTLSRanges(void[] rng) nothrow @nogc -{ -} - -void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow -{ - if (conservative) - { - dg(rng.ptr, rng.ptr + rng.length); - } - else - { - for (auto p = &_TPbegin; p < &_TPend; ) - { - uint beg = *p++; - uint end = beg + cast(uint)((void*).sizeof); - while (p < &_TPend && *p == end) - { - end += (void*).sizeof; - p++; - } - dg(rng.ptr + beg, rng.ptr + end); - } - } -} - -private: - -__gshared SectionGroup _sections; - -// Windows: this gets initialized by minit.asm -extern(C) __gshared immutable(ModuleInfo*)[] _moduleinfo_array; -extern(C) void _minit() nothrow @nogc; - -immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc -out (result) -{ - foreach (m; result) - assert(m !is null); -} -body -{ - // _minit directly alters the global _moduleinfo_array - _minit(); - return _moduleinfo_array; -} - -extern(C) -{ - extern __gshared - { - int _xi_a; // &_xi_a just happens to be start of data segment - int _edata; // &_edata is start of BSS segment - int _end; // &_end is past end of BSS - - void* _DPbegin; // first entry in the array of pointers addresses - void* _DPend; // &_DPend points after last entry of array - uint _TPbegin; // first entry in the array of TLS offsets of pointers - uint _TPend; // &_DPend points after last entry of array - } - - extern - { - int _tlsstart; - int _tlsend; - } -} diff --git a/libphobos/libdruntime/gcc/sections/win64.d b/libphobos/libdruntime/gcc/sections/win64.d deleted file mode 100644 index 357940b..0000000 --- a/libphobos/libdruntime/gcc/sections/win64.d +++ /dev/null @@ -1,321 +0,0 @@ -// Win64-specific support for sections. -// Copyright (C) 2019-2021 Free Software Foundation, Inc. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// <http://www.gnu.org/licenses/>. - -module gcc.sections.win64; - -version (CRuntime_Microsoft): - -// debug = PRINTF; -debug(PRINTF) import core.stdc.stdio; -import core.stdc.stdlib : malloc, free; -import rt.deh, rt.minfo; - -struct SectionGroup -{ - static int opApply(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - static int opApplyReverse(scope int delegate(ref SectionGroup) dg) - { - return dg(_sections); - } - - @property immutable(ModuleInfo*)[] modules() const nothrow @nogc - { - return _moduleGroup.modules; - } - - @property ref inout(ModuleGroup) moduleGroup() inout nothrow @nogc - { - return _moduleGroup; - } - - version (Win64) - @property immutable(FuncTable)[] ehTables() const nothrow @nogc - { - auto pbeg = cast(immutable(FuncTable)*)&_deh_beg; - auto pend = cast(immutable(FuncTable)*)&_deh_end; - return pbeg[0 .. pend - pbeg]; - } - - @property inout(void[])[] gcRanges() inout nothrow @nogc - { - return _gcRanges[]; - } - -private: - ModuleGroup _moduleGroup; - void[][] _gcRanges; -} - -shared(bool) conservative; - -void initSections() nothrow @nogc -{ - _sections._moduleGroup = ModuleGroup(getModuleInfos()); - - // the ".data" image section includes both object file sections ".data" and ".bss" - void[] dataSection = findImageSection(".data"); - debug(PRINTF) printf("found .data section: [%p,+%llx]\n", dataSection.ptr, - cast(ulong)dataSection.length); - - import rt.sections; - conservative = !scanDataSegPrecisely(); - - if (conservative) - { - _sections._gcRanges = (cast(void[]*) malloc((void[]).sizeof))[0..1]; - _sections._gcRanges[0] = dataSection; - } - else - { - size_t count = &_DP_end - &_DP_beg; - auto ranges = cast(void[]*) malloc(count * (void[]).sizeof); - size_t r = 0; - void* prev = null; - for (size_t i = 0; i < count; i++) - { - auto off = (&_DP_beg)[i]; - if (off == 0) // skip zero entries added by incremental linking - continue; // assumes there is no D-pointer at the very beginning of .data - void* addr = dataSection.ptr + off; - debug(PRINTF) printf(" scan %p\n", addr); - // combine consecutive pointers into single range - if (prev + (void*).sizeof == addr) - ranges[r-1] = ranges[r-1].ptr[0 .. ranges[r-1].length + (void*).sizeof]; - else - ranges[r++] = (cast(void**)addr)[0..1]; - prev = addr; - } - _sections._gcRanges = ranges[0..r]; - } -} - -void finiSections() nothrow @nogc -{ - .free(cast(void*)_sections.modules.ptr); - .free(_sections._gcRanges.ptr); -} - -void[] initTLSRanges() nothrow @nogc -{ - void* pbeg; - void* pend; - // with VS2017 15.3.1, the linker no longer puts TLS segments into a - // separate image section. That way _tls_start and _tls_end no - // longer generate offsets into .tls, but DATA. - // Use the TEB entry to find the start of TLS instead and read the - // length from the TLS directory - version (D_InlineAsm_X86) - { - asm @nogc nothrow - { - mov EAX, _tls_index; - mov ECX, FS:[0x2C]; // _tls_array - mov EAX, [ECX+4*EAX]; - mov pbeg, EAX; - add EAX, [_tls_used+4]; // end - sub EAX, [_tls_used+0]; // start - mov pend, EAX; - } - } - else version (D_InlineAsm_X86_64) - { - asm @nogc nothrow - { - xor RAX, RAX; - mov EAX, _tls_index; - mov RCX, 0x58; - mov RCX, GS:[RCX]; // _tls_array (immediate value causes fixup) - mov RAX, [RCX+8*RAX]; - mov pbeg, RAX; - add RAX, [_tls_used+8]; // end - sub RAX, [_tls_used+0]; // start - mov pend, RAX; - } - } - else - static assert(false, "Architecture not supported."); - - return pbeg[0 .. pend - pbeg]; -} - -void finiTLSRanges(void[] rng) nothrow @nogc -{ -} - -void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow -{ - if (conservative) - { - dg(rng.ptr, rng.ptr + rng.length); - } - else - { - for (auto p = &_TP_beg; p < &_TP_end; ) - { - uint beg = *p++; - uint end = beg + cast(uint)((void*).sizeof); - while (p < &_TP_end && *p == end) - { - end += (void*).sizeof; - p++; - } - dg(rng.ptr + beg, rng.ptr + end); - } - } -} - -private: -__gshared SectionGroup _sections; - -extern(C) -{ - extern __gshared void* _minfo_beg; - extern __gshared void* _minfo_end; -} - -immutable(ModuleInfo*)[] getModuleInfos() nothrow @nogc -out (result) -{ - foreach (m; result) - assert(m !is null); -} -body -{ - auto m = (cast(immutable(ModuleInfo*)*)&_minfo_beg)[1 .. &_minfo_end - &_minfo_beg]; - /* Because of alignment inserted by the linker, various null pointers - * are there. We need to filter them out. - */ - auto p = m.ptr; - auto pend = m.ptr + m.length; - - // count non-null pointers - size_t cnt; - for (; p < pend; ++p) - { - if (*p !is null) ++cnt; - } - - auto result = (cast(immutable(ModuleInfo)**).malloc(cnt * size_t.sizeof))[0 .. cnt]; - - p = m.ptr; - cnt = 0; - for (; p < pend; ++p) - if (*p !is null) result[cnt++] = *p; - - return cast(immutable)result; -} - -extern(C) -{ - /* Symbols created by the compiler/linker and inserted into the - * object file that 'bracket' sections. - */ - extern __gshared - { - void* __ImageBase; - - void* _deh_beg; - void* _deh_end; - - uint _DP_beg; - uint _DP_end; - uint _TP_beg; - uint _TP_end; - - void*[2] _tls_used; // start, end - int _tls_index; - } -} - -///////////////////////////////////////////////////////////////////// - -enum IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ - -struct IMAGE_DOS_HEADER // DOS .EXE header -{ - ushort e_magic; // Magic number - ushort[29] e_res2; // Reserved ushorts - int e_lfanew; // File address of new exe header -} - -struct IMAGE_FILE_HEADER -{ - ushort Machine; - ushort NumberOfSections; - uint TimeDateStamp; - uint PointerToSymbolTable; - uint NumberOfSymbols; - ushort SizeOfOptionalHeader; - ushort Characteristics; -} - -struct IMAGE_NT_HEADERS -{ - uint Signature; - IMAGE_FILE_HEADER FileHeader; - // optional header follows -} - -struct IMAGE_SECTION_HEADER -{ - char[8] Name = 0; - union { - uint PhysicalAddress; - uint VirtualSize; - } - uint VirtualAddress; - uint SizeOfRawData; - uint PointerToRawData; - uint PointerToRelocations; - uint PointerToLinenumbers; - ushort NumberOfRelocations; - ushort NumberOfLinenumbers; - uint Characteristics; -} - -bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow @nogc -{ - if (name[] != section.Name[0 .. name.length]) - return false; - return name.length == 8 || section.Name[name.length] == 0; -} - -void[] findImageSection(string name) nothrow @nogc -{ - if (name.length > 8) // section name from string table not supported - return null; - IMAGE_DOS_HEADER* doshdr = cast(IMAGE_DOS_HEADER*) &__ImageBase; - if (doshdr.e_magic != IMAGE_DOS_SIGNATURE) - return null; - - auto nthdr = cast(IMAGE_NT_HEADERS*)(cast(void*)doshdr + doshdr.e_lfanew); - auto sections = cast(IMAGE_SECTION_HEADER*)(cast(void*)nthdr + IMAGE_NT_HEADERS.sizeof + nthdr.FileHeader.SizeOfOptionalHeader); - for (ushort i = 0; i < nthdr.FileHeader.NumberOfSections; i++) - if (compareSectionName (sections[i], name)) - return (cast(void*)&__ImageBase + sections[i].VirtualAddress)[0 .. sections[i].VirtualSize]; - - return null; -} diff --git a/libphobos/libdruntime/gcc/unwind/generic.d b/libphobos/libdruntime/gcc/unwind/generic.d index 5315739..592b3af 100644 --- a/libphobos/libdruntime/gcc/unwind/generic.d +++ b/libphobos/libdruntime/gcc/unwind/generic.d @@ -269,6 +269,6 @@ version (GNU_SEH_Exceptions) ExceptionCollidedUnwind } - extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, + extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, void*, _Unwind_Personality_Fn); } diff --git a/libphobos/libdruntime/gcc/unwind/pe.d b/libphobos/libdruntime/gcc/unwind/pe.d index 361ec12..b9b05cb 100644 --- a/libphobos/libdruntime/gcc/unwind/pe.d +++ b/libphobos/libdruntime/gcc/unwind/pe.d @@ -103,40 +103,37 @@ _Unwind_Ptr base_of_encoded_value(ubyte encoding, _Unwind_Context* context) assert(0); } -// Read an unsigned leb128 value from P, *P is incremented past the value. +// Read an unsigned leb128 value from P, P is incremented past the value. // We assume that a word is large enough to hold any value so encoded; // if it is smaller than a pointer on some target, pointers should not be // leb128 encoded on that target. -_uleb128_t read_uleb128(const(ubyte)** p) +_uleb128_t read_uleb128(ref const(ubyte)* p) { - auto q = *p; _uleb128_t result = 0; uint shift = 0; while (1) { - ubyte b = *q++; + ubyte b = *p++; result |= cast(_uleb128_t)(b & 0x7F) << shift; if ((b & 0x80) == 0) break; shift += 7; } - *p = q; return result; } // Similar, but read a signed leb128 value. -_sleb128_t read_sleb128(const(ubyte)** p) +_sleb128_t read_sleb128(ref const(ubyte)* p) { - auto q = *p; _sleb128_t result = 0; uint shift = 0; ubyte b = void; while (1) { - b = *q++; + b = *p++; result |= cast(_sleb128_t)(b & 0x7F) << shift; shift += 7; if ((b & 0x80) == 0) @@ -147,69 +144,82 @@ _sleb128_t read_sleb128(const(ubyte)** p) if (shift < result.sizeof * 8 && (b & 0x40)) result |= -(cast(_sleb128_t)1 << shift); - *p = q; return result; } -// Load an encoded value from memory at P. The value is returned in VAL; -// The function returns P incremented past the value. BASE is as given +// Similar, but read an unaligned value of type T. +pragma(inline, true) +private T read_unaligned(T)(ref const(ubyte)* p) +{ + version (X86) enum hasUnalignedLoads = true; + else version (X86_64) enum hasUnalignedLoads = true; + else enum hasUnalignedLoads = false; + + static if (hasUnalignedLoads) + { + T result = *cast(T*)p; + } + else + { + import core.stdc.string : memcpy; + T result = void; + memcpy(&result, p, T.sizeof); + } + p += T.sizeof; + return result; +} + +// Load an encoded value from memory at P. The function returns the +// encoded value. P is incremented past the value. BASE is as given // by base_of_encoded_value for this encoding in the appropriate context. _Unwind_Ptr read_encoded_value_with_base(ubyte encoding, _Unwind_Ptr base, - const(ubyte)** p) + ref const(ubyte)* p) { - auto q = *p; + auto psave = p; _Unwind_Internal_Ptr result; if (encoding == DW_EH_PE_aligned) { - _Unwind_Internal_Ptr a = cast(_Unwind_Internal_Ptr)q; + _Unwind_Internal_Ptr a = cast(_Unwind_Internal_Ptr)p; a = cast(_Unwind_Internal_Ptr)((a + (void*).sizeof - 1) & - (void*).sizeof); result = *cast(_Unwind_Internal_Ptr*)a; - q = cast(ubyte*) cast(_Unwind_Internal_Ptr)(a + (void*).sizeof); + p = cast(ubyte*) cast(_Unwind_Internal_Ptr)(a + (void*).sizeof); } else { switch (encoding & 0x0f) { case DW_EH_PE_uleb128: - result = cast(_Unwind_Internal_Ptr)read_uleb128(&q); + result = cast(_Unwind_Internal_Ptr)read_uleb128(p); break; case DW_EH_PE_sleb128: - result = cast(_Unwind_Internal_Ptr)read_sleb128(&q); + result = cast(_Unwind_Internal_Ptr)read_sleb128(p); break; case DW_EH_PE_udata2: - result = cast(_Unwind_Internal_Ptr) *cast(ushort*)q; - q += 2; + result = cast(_Unwind_Internal_Ptr)read_unaligned!ushort(p); break; case DW_EH_PE_udata4: - result = cast(_Unwind_Internal_Ptr) *cast(uint*)q; - q += 4; + result = cast(_Unwind_Internal_Ptr)read_unaligned!uint(p); break; case DW_EH_PE_udata8: - result = cast(_Unwind_Internal_Ptr) *cast(ulong*)q; - q += 8; + result = cast(_Unwind_Internal_Ptr)read_unaligned!ulong(p); break; case DW_EH_PE_sdata2: - result = cast(_Unwind_Internal_Ptr) *cast(short*)q; - q += 2; + result = cast(_Unwind_Internal_Ptr)read_unaligned!short(p); break; case DW_EH_PE_sdata4: - result = cast(_Unwind_Internal_Ptr) *cast(int*)q; - q += 4; + result = cast(_Unwind_Internal_Ptr)read_unaligned!int(p); break; case DW_EH_PE_sdata8: - result = cast(_Unwind_Internal_Ptr) *cast(long*)q; - q += 8; + result = cast(_Unwind_Internal_Ptr)read_unaligned!long(p); break; case DW_EH_PE_absptr: - if (size_t.sizeof == 8) - goto case DW_EH_PE_udata8; - else - goto case DW_EH_PE_udata4; + result = cast(_Unwind_Internal_Ptr)read_unaligned!(size_t)(p); + break; default: __builtin_abort(); @@ -218,20 +228,19 @@ _Unwind_Ptr read_encoded_value_with_base(ubyte encoding, _Unwind_Ptr base, if (result != 0) { result += ((encoding & 0x70) == DW_EH_PE_pcrel - ? cast(_Unwind_Internal_Ptr)*p : base); + ? cast(_Unwind_Internal_Ptr)psave : base); if (encoding & DW_EH_PE_indirect) result = *cast(_Unwind_Internal_Ptr*)result; } } - *p = q; return result; } // Like read_encoded_value_with_base, but get the base from the context // rather than providing it directly. _Unwind_Ptr read_encoded_value(_Unwind_Context* context, ubyte encoding, - const(ubyte)** p) + ref const(ubyte)* p) { auto base = base_of_encoded_value(encoding, context); return read_encoded_value_with_base(encoding, base, p); diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d index 04d5457..e96d1c4 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -19,10 +19,11 @@ private alias size_t = typeof(int.sizeof); alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0); -alias sizediff_t = ptrdiff_t; //For backwards compatibility only. +alias sizediff_t = ptrdiff_t; // For backwards compatibility only. +alias noreturn = typeof(*null); /// bottom type -alias hash_t = size_t; //For backwards compatibility only. -alias equals_t = bool; //For backwards compatibility only. +alias hash_t = size_t; // For backwards compatibility only. +alias equals_t = bool; // For backwards compatibility only. alias string = immutable(char)[]; alias wstring = immutable(wchar)[]; @@ -41,7 +42,7 @@ else version (X86_64) else version (Windows) { /* no need for Win64 ABI */ } else version = WithArgTypes; } -version (AArch64) +else version (AArch64) { // Apple uses a trivial varargs implementation version (OSX) {} diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d index 3d5ba29..e6acbd5 100644 --- a/libphobos/libdruntime/rt/dmain2.d +++ b/libphobos/libdruntime/rt/dmain2.d @@ -9,6 +9,9 @@ * 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 @@ -70,70 +73,6 @@ version (CRuntime_Microsoft) extern(C) void init_msvc(); } -/*********************************** - * These are a temporary means of providing a GC hook for DLL use. They may be - * replaced with some other similar functionality later. - */ -extern (C) -{ - void* gc_getProxy(); - void gc_setProxy(void* p); - void gc_clrProxy(); - - alias void* function() gcGetFn; - alias void function(void*) gcSetFn; - alias void function() gcClrFn; -} - -version (Windows) -{ - /******************************************* - * Loads a DLL written in D with the name 'name'. - * Returns: - * opaque handle to the DLL if successfully loaded - * null if failure - */ - extern (C) void* rt_loadLibrary(const char* name) - { - return initLibrary(.LoadLibraryA(name)); - } - - extern (C) void* rt_loadLibraryW(const wchar_t* name) - { - return initLibrary(.LoadLibraryW(name)); - } - - void* initLibrary(void* mod) - { - // BUG: LoadLibrary() call calls rt_init(), which fails if proxy is not set! - // (What? LoadLibrary() is a Windows API call, it shouldn't call rt_init().) - if (mod is null) - return mod; - gcSetFn gcSet = cast(gcSetFn) GetProcAddress(mod, "gc_setProxy"); - if (gcSet !is null) - { // BUG: Set proxy, but too late - gcSet(gc_getProxy()); - } - return mod; - } - - /************************************* - * Unloads DLL that was previously loaded by rt_loadLibrary(). - * Input: - * ptr the handle returned by rt_loadLibrary() - * Returns: - * 1 succeeded - * 0 some failure happened - */ - extern (C) int rt_unloadLibrary(void* ptr) - { - gcClrFn gcClr = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy"); - if (gcClr !is null) - gcClr(); - return FreeLibrary(ptr) != 0; - } -} - /* To get out-of-band access to the args[] passed to main(). */ diff --git a/libphobos/m4/autoconf.m4 b/libphobos/m4/autoconf.m4 index f46a780..f0ca947 100644 --- a/libphobos/m4/autoconf.m4 +++ b/libphobos/m4/autoconf.m4 @@ -27,7 +27,7 @@ AU_DEFUN([AC_LANG_D], [AC_LANG(D)]) # AC_LANG_PROGRAM(D)([PROLOGUE], [BODY]) # --------------------------------------- m4_define([AC_LANG_PROGRAM(D)], -[module mod; +[module object; $1 extern(C) int main() { diff --git a/libphobos/m4/druntime.m4 b/libphobos/m4/druntime.m4 index 7221712..2a7a689 100644 --- a/libphobos/m4/druntime.m4 +++ b/libphobos/m4/druntime.m4 @@ -116,3 +116,22 @@ AC_DEFUN([DRUNTIME_INSTALL_DIRECTORIES], gdc_include_dir='$(libdir)/gcc/${target_alias}/${gcc_version}/include/d' AC_SUBST(gdc_include_dir) ]) + +# DRUNTIME_SECTION_FLAGS +# ---------------------- +# Check for -ffunction-sections nad -fdata-sections. +AC_DEFUN([DRUNTIME_SECTION_FLAGS], +[ + WITH_LOCAL_DRUNTIME([ + AC_LANG_PUSH([D]) + GDCFLAGS="$GDCFLAGS -g -Werror -ffunction-sections -fdata-sections" + AC_TRY_COMPILE([int foo; void bar() { }],[return 0;], + [ac_fdsections=yes], [ac_fdsections=no]) + if test "x$ac_fdsections" = "xyes"; then + SECTION_FLAGS='-ffunction-sections -fdata-sections' + fi + AC_MSG_RESULT($ac_fdsections) + AC_LANG_POP([D]) + ], [-nophoboslib]) + AC_SUBST(SECTION_FLAGS) +]) diff --git a/libphobos/m4/druntime/libraries.m4 b/libphobos/m4/druntime/libraries.m4 index 743d3e3..45a56f6 100644 --- a/libphobos/m4/druntime/libraries.m4 +++ b/libphobos/m4/druntime/libraries.m4 @@ -116,7 +116,7 @@ AC_DEFUN([DRUNTIME_LIBRARIES_ATOMIC], DCFG_HAVE_LIBATOMIC=false LIBATOMIC= - AS_IF([test "x$with_libatomic" != "xno"], [ + AS_IF([test "x$enable_libatomic" != "xno" && test "x$with_libatomic" != "xno"], [ DCFG_HAVE_LIBATOMIC=true LIBATOMIC=../../libatomic/libatomic_convenience.la ], [ @@ -145,7 +145,7 @@ AC_DEFUN([DRUNTIME_LIBRARIES_BACKTRACE], AS_HELP_STRING([--without-libbacktrace], [Do not use libbacktrace in core.runtime (default: auto)])) - AS_IF([test "x$with_libbacktrace" != "xno"], [ + AS_IF([test "x$enable_libbacktrace" != "xno" && test "x$with_libbacktrace" != "xno"], [ LIBBACKTRACE=../../libbacktrace/libbacktrace.la gdc_save_CPPFLAGS=$CPPFLAGS diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4 index ed93e30..15cde3b 100644 --- a/libphobos/m4/druntime/os.m4 +++ b/libphobos/m4/druntime/os.m4 @@ -54,9 +54,10 @@ AC_DEFUN([DRUNTIME_OS_DETECT], # DRUNTIME_OS_SOURCES # ------------------- -# Detect target OS and add DRUNTIME_OS_AIX DRUNTIME_OS_DARWIN -# DRUNTIME_OS_FREEBSD DRUNTIME_OS_LINUX DRUNTIME_OS_MINGW -# DRUNTIME_OS_SOLARIS DRUNTIME_OS_OPENBSD conditionals. +# Detect target OS and add DRUNTIME_OS_AIX DRUNTIME_OS_ANDROID +# DRUNTIME_OS_DARWIN DRUNTIME_OS_DRAGONFLYBSD DRUNTIME_OS_FREEBSD +# DRUNTIME_OS_LINUX DRUNTIME_OS_MINGW DRUNTIME_OS_NETBSD +# DRUNTIME_OS_OPENBSD DRUNTIME_OS_SOLARIS conditionals. # If the system is posix, add DRUNTIME_OS_POSIX conditional. AC_DEFUN([DRUNTIME_OS_SOURCES], [ @@ -149,17 +150,31 @@ AC_DEFUN([DRUNTIME_OS_ARM_EABI_UNWINDER], # substitute DCFG_MINFO_BRACKETING. AC_DEFUN([DRUNTIME_OS_MINFO_BRACKETING], [ + AC_REQUIRE([DRUNTIME_OS_DETECT]) + AC_LANG_PUSH([C]) AC_MSG_CHECKING([for minfo section bracketing]) + case "$druntime_cv_target_os" in + darwin*) + section="__DATA,__minfodata" + start="section\$start\$__DATA\$__minfodata" + stop="section\$end\$__DATA\$__minfodata" + ;; + *) + section="minfo" + start="__start_minfo" + stop="__stop_minfo" + ;; + esac AC_LINK_IFELSE([AC_LANG_SOURCE([ - void* module_info_ptr __attribute__((section ("minfo"))); - extern void* __start_minfo __attribute__((visibility ("hidden"))); - extern void* __stop_minfo __attribute__((visibility ("hidden"))); + void* module_info_ptr __attribute__((section ("$section"))); + extern void* start_minfo __asm__("$start") __attribute__((visibility ("hidden"))); + extern void* stop_minfo __asm__("$stop") __attribute__((visibility ("hidden"))); int main() { // Never run, just to prevent compiler from optimizing access - return &__start_minfo == &__stop_minfo; + return (int)(&stop_minfo - &start_minfo); } ])], [AC_MSG_RESULT([yes]) diff --git a/libphobos/m4/gcc_support.m4 b/libphobos/m4/gcc_support.m4 index 0903ed4..cc1acb4 100644 --- a/libphobos/m4/gcc_support.m4 +++ b/libphobos/m4/gcc_support.m4 @@ -27,7 +27,7 @@ AC_DEFUN([PHOBOS_ABS_SRCDIR], [ AC_DEFUN([WITH_LOCAL_DRUNTIME], [ AC_REQUIRE([PHOBOS_ABS_SRCDIR]) gdc_save_DFLAGS=$GDCFLAGS - GDCFLAGS="-fno-moduleinfo -nostdinc -I $phobos_cv_abs_srcdir/libdruntime $2 $GDCFLAGS" + GDCFLAGS="-fno-druntime -nostdinc -I $phobos_cv_abs_srcdir/libdruntime $2 $GDCFLAGS" $1 GDCFLAGS=$gdc_save_DFLAGS ]) diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index 6de04b4..01cf594 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -9d575282edeccecbc061e615bf2486fd07e8c084 +55bb17543138a87c376a84745f2a30ec00bdecd9 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/Makefile.am b/libphobos/src/Makefile.am index 2de8ab9..9f62510 100644 --- a/libphobos/src/Makefile.am +++ b/libphobos/src/Makefile.am @@ -24,8 +24,8 @@ D_EXTRA_DFLAGS=-nostdinc -I $(srcdir) \ # D flags for compilation AM_DFLAGS= \ - $(phobos_compiler_pic_flag) \ - $(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS) + $(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \ + $(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_DFLAGS) # Flags for other kinds of sources AM_CFLAGS=$(CET_FLAGS) @@ -45,8 +45,12 @@ libgphobos_la_SOURCES = $(ALL_PHOBOS_SOURCES) libgphobos_la_LIBTOOLFLAGS = libgphobos_la_LDFLAGS = -Wc,-nophoboslib,-dstartfiles,-B../libdruntime/gcc \ -version-info $(libtool_VERSION) +if ENABLE_LIBDRUNTIME_ONLY +libgphobos_la_LIBADD = ../libdruntime/libgdruntime_convenience.la +else libgphobos_la_LIBADD = \ ../libdruntime/libgdruntime_convenience.la $(LIBZ) +endif libgphobos_la_DEPENDENCIES = \ ../libdruntime/libgdruntime_convenience.la libgphobos.spec @@ -135,11 +139,11 @@ PHOBOS_DSOURCES = etc/c/curl.d etc/c/sqlite3.d etc/c/zlib.d \ std/regex/internal/backtracking.d std/regex/internal/generator.d \ std/regex/internal/ir.d std/regex/internal/kickstart.d \ std/regex/internal/parser.d std/regex/internal/tests.d \ - std/regex/internal/thompson.d std/regex/package.d std/signals.d \ - std/socket.d std/stdint.d std/stdio.d std/string.d std/system.d \ - std/traits.d std/typecons.d std/typetuple.d std/uni.d std/uri.d \ - std/utf.d std/uuid.d std/variant.d std/windows/charset.d \ - std/windows/registry.d std/windows/syserror.d std/xml.d std/zip.d \ - std/zlib.d + std/regex/internal/tests2.d std/regex/internal/thompson.d \ + std/regex/package.d std/signals.d std/socket.d std/stdint.d \ + std/stdio.d std/string.d std/system.d std/traits.d std/typecons.d \ + std/typetuple.d std/uni.d std/uri.d std/utf.d std/uuid.d std/variant.d \ + std/windows/charset.d std/windows/registry.d std/windows/syserror.d \ + std/xml.d std/zip.d std/zlib.d endif diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in index 2e72178..f8b7648 100644 --- a/libphobos/src/Makefile.in +++ b/libphobos/src/Makefile.in @@ -249,6 +249,7 @@ am__dirstamp = $(am__leading_dot)dirstamp @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/kickstart.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/parser.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/tests.lo \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/tests2.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/thompson.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/package.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/signals.lo std/socket.lo \ @@ -387,6 +388,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +SECTION_FLAGS = @SECTION_FLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -414,6 +416,8 @@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ +enable_shared = @enable_shared@ +enable_static = @enable_static@ exec_prefix = @exec_prefix@ gcc_version = @gcc_version@ gdc_include_dir = @gdc_include_dir@ @@ -443,6 +447,7 @@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ phobos_compiler_pic_flag = @phobos_compiler_pic_flag@ phobos_compiler_shared_flag = @phobos_compiler_shared_flag@ +phobos_lt_pic_flag = @phobos_lt_pic_flag@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ @@ -477,8 +482,8 @@ D_EXTRA_DFLAGS = -nostdinc -I $(srcdir) \ # D flags for compilation AM_DFLAGS = \ - $(phobos_compiler_pic_flag) \ - $(WARN_DFLAGS) $(CHECKING_DFLAGS) $(CET_DFLAGS) + $(phobos_lt_pic_flag) $(phobos_compiler_shared_flag) \ + $(WARN_DFLAGS) $(CHECKING_DFLAGS) $(SECTION_FLAGS) $(CET_DFLAGS) # Flags for other kinds of sources @@ -499,9 +504,10 @@ libgphobos_la_LIBTOOLFLAGS = libgphobos_la_LDFLAGS = -Wc,-nophoboslib,-dstartfiles,-B../libdruntime/gcc \ -version-info $(libtool_VERSION) -libgphobos_la_LIBADD = \ - ../libdruntime/libgdruntime_convenience.la $(LIBZ) +@ENABLE_LIBDRUNTIME_ONLY_FALSE@libgphobos_la_LIBADD = \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ ../libdruntime/libgdruntime_convenience.la $(LIBZ) +@ENABLE_LIBDRUNTIME_ONLY_TRUE@libgphobos_la_LIBADD = ../libdruntime/libgdruntime_convenience.la libgphobos_la_DEPENDENCIES = \ ../libdruntime/libgdruntime_convenience.la libgphobos.spec @@ -569,12 +575,12 @@ libgphobos_la_LINK = $(LIBTOOL) --tag=D $(libgphobos_la_LIBTOOLFLAGS) \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/backtracking.d std/regex/internal/generator.d \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/ir.d std/regex/internal/kickstart.d \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/parser.d std/regex/internal/tests.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/thompson.d std/regex/package.d std/signals.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/socket.d std/stdint.d std/stdio.d std/string.d std/system.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/traits.d std/typecons.d std/typetuple.d std/uni.d std/uri.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/utf.d std/uuid.d std/variant.d std/windows/charset.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/registry.d std/windows/syserror.d std/xml.d std/zip.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/zlib.d +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/tests2.d std/regex/internal/thompson.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/package.d std/signals.d std/socket.d std/stdint.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/stdio.d std/string.d std/system.d std/traits.d std/typecons.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/typetuple.d std/uni.d std/uri.d std/utf.d std/uuid.d std/variant.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/windows/charset.d std/windows/registry.d std/windows/syserror.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/xml.d std/zip.d std/zlib.d # Source file definitions. Boring stuff, auto-generated with @@ -848,6 +854,7 @@ std/regex/internal/ir.lo: std/regex/internal/$(am__dirstamp) std/regex/internal/kickstart.lo: std/regex/internal/$(am__dirstamp) std/regex/internal/parser.lo: std/regex/internal/$(am__dirstamp) std/regex/internal/tests.lo: std/regex/internal/$(am__dirstamp) +std/regex/internal/tests2.lo: std/regex/internal/$(am__dirstamp) std/regex/internal/thompson.lo: std/regex/internal/$(am__dirstamp) std/regex/$(am__dirstamp): @$(MKDIR_P) std/regex diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d index c77792d..19cfb77 100644 --- a/libphobos/src/std/algorithm/iteration.d +++ b/libphobos/src/std/algorithm/iteration.d @@ -769,9 +769,9 @@ private struct MapResult(alias fun, Range) string s1 = "hello world!"; dstring s2 = "日本語"; dstring s3 = "hello world!"d; - auto ms1 = map!(std.ascii.toUpper)(s1); - auto ms2 = map!(std.ascii.toUpper)(s2); - auto ms3 = map!(std.ascii.toUpper)(s3); + auto ms1 = map!(toUpper)(s1); + auto ms2 = map!(toUpper)(s2); + auto ms3 = map!(toUpper)(s3); static assert(!is(ms1[0])); //narrow strings can't be indexed assert(ms2[0] == '日'); assert(ms3[0] == 'H'); @@ -4450,7 +4450,7 @@ private struct SplitterResult(alias isTerminator, Range) ["là", "dove", "terminava", "quella", "valle"] )); assert(equal( - splitter!(std.uni.isWhite)("là dove terminava quella valle"), + splitter!(isWhite)("là dove terminava quella valle"), ["là", "dove", "terminava", "quella", "valle"] )); assert(equal(splitter!"a=='本'"("日本語"), ["日", "語"])); diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d index 6468a87..09073f6 100644 --- a/libphobos/src/std/algorithm/searching.d +++ b/libphobos/src/std/algorithm/searching.d @@ -959,8 +959,8 @@ if (isInputRange!R && import std.ascii : isDigit; import std.uni : isWhite; - assert(countUntil!(std.uni.isWhite)("hello world") == 5); - assert(countUntil!(std.ascii.isDigit)("hello world") == -1); + assert(countUntil!(isWhite)("hello world") == 5); + assert(countUntil!(isDigit)("hello world") == -1); assert(countUntil!"a > 20"([0, 7, 12, 22, 9]) == 3); } diff --git a/libphobos/src/std/container/rbtree.d b/libphobos/src/std/container/rbtree.d index 861da5e..5e31ac2 100644 --- a/libphobos/src/std/container/rbtree.d +++ b/libphobos/src/std/container/rbtree.d @@ -1814,8 +1814,8 @@ assert(equal(rbt[], [5])); test!byte(); } -import std.range.primitives : isInputRange, isSomeString, ElementType; -import std.traits : isArray; +import std.range.primitives : isInputRange, ElementType; +import std.traits : isArray, isSomeString; /++ Convenience function for creating a $(D RedBlackTree!E) from a list of diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d index 31cc651..3560d13 100644 --- a/libphobos/src/std/conv.d +++ b/libphobos/src/std/conv.d @@ -3967,7 +3967,7 @@ if (isOctalLiteral(num)) /// Ditto template octal(alias decimalInteger) -if (isIntegral!(typeof(decimalInteger))) +if (is(typeof(decimalInteger)) && isIntegral!(typeof(decimalInteger))) { enum octal = octal!(typeof(decimalInteger))(to!string(decimalInteger)); } diff --git a/libphobos/src/std/datetime/systime.d b/libphobos/src/std/datetime/systime.d index b229191..913d360 100644 --- a/libphobos/src/std/datetime/systime.d +++ b/libphobos/src/std/datetime/systime.d @@ -9569,7 +9569,7 @@ afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length); } // year - auto found = value[2 .. value.length].find!(not!(std.ascii.isDigit))(); + auto found = value[2 .. value.length].find!(not!(isDigit))(); size_t yearLen = value.length - found.length; if (found.length == 0) throw new DateTimeException("Invalid year"); @@ -9659,7 +9659,7 @@ afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length); case "J": case "j": throw new DateTimeException("Invalid timezone"); default: { - if (all!(std.ascii.isAlpha)(value[0 .. tzLen])) + if (all!(isAlpha)(value[0 .. tzLen])) { tz = new immutable SimpleTimeZone(Duration.zero); break; diff --git a/libphobos/src/std/experimental/logger/nulllogger.d b/libphobos/src/std/experimental/logger/nulllogger.d index fa511be..0c55377 100644 --- a/libphobos/src/std/experimental/logger/nulllogger.d +++ b/libphobos/src/std/experimental/logger/nulllogger.d @@ -31,7 +31,7 @@ class NullLogger : Logger /// @safe unittest { - import std.experimental.logger.nulllogger : LogLevel; + import std.experimental.logger.core : LogLevel; auto nl1 = new NullLogger(LogLevel.all); nl1.info("You will never read this."); diff --git a/libphobos/src/std/experimental/typecons.d b/libphobos/src/std/experimental/typecons.d index 6906f05..07eed8f 100644 --- a/libphobos/src/std/experimental/typecons.d +++ b/libphobos/src/std/experimental/typecons.d @@ -23,8 +23,7 @@ module std.experimental.typecons; import std.meta; // : AliasSeq, allSatisfy; import std.traits; -import std.typecons : Tuple, tuple, Bind, DerivedFunctionType, - isImplicitlyConvertible, mixinAll, staticIota, +import std.typecons : Tuple, tuple, Bind, DerivedFunctionType, mixinAll, staticIota, GetOverloadedMethods; private @@ -113,7 +112,8 @@ if (Targets.length >= 1 && allSatisfy!(isMutable, Targets)) else { enum foundFunc = findCovariantFunction!(TargetMembers[i], Source, SourceMembers); - debug + version (unittest) {} + else debug { static if (foundFunc == -1) pragma(msg, "Could not locate matching function for: ", diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d index 13a3db0..99530cb 100644 --- a/libphobos/src/std/file.d +++ b/libphobos/src/std/file.d @@ -2301,7 +2301,7 @@ if (isConvertibleToString!R) @safe unittest { - import std.path : mkdir; + import std.file : mkdir; static assert(__traits(compiles, mkdir(TestAliasedString(null)))); } @@ -4112,7 +4112,8 @@ auto dirEntries(string path, SpanMode mode, bool followSymlink = true) import std.algorithm.searching : startsWith; import std.array : array; import std.conv : to; - import std.path : dirEntries, buildPath, absolutePath; + import std.path : buildPath, absolutePath; + import std.file : dirEntries; import std.process : thisProcessID; import std.range.primitives : walkLength; diff --git a/libphobos/src/std/format.d b/libphobos/src/std/format.d index 64b1bd3..17e5906 100644 --- a/libphobos/src/std/format.d +++ b/libphobos/src/std/format.d @@ -5199,7 +5199,7 @@ body } debug (unformatRange) printf("\t"); debug (unformatRange) if (!input.empty) printf("input.front = %c, ", input.front); - debug (unformatRange) printf("cont = %.*s\n", cont); + debug (unformatRange) printf("cont = %.*s\n", cast(int) cont.length, cont.ptr); bool checkEnd() { @@ -5246,7 +5246,7 @@ body auto sep = spec.sep !is null ? spec.sep : fmt.trailing; debug (unformatRange) { - if (!sep.empty && !input.empty) printf("-> %c, sep = %.*s\n", input.front, sep); + if (!sep.empty && !input.empty) printf("-> %c, sep = %.*s\n", input.front, cast(int) sep.length, sep.ptr); else printf("\n"); } diff --git a/libphobos/src/std/internal/math/biguintcore.d b/libphobos/src/std/internal/math/biguintcore.d index f5cd769..6fc2d16 100644 --- a/libphobos/src/std/internal/math/biguintcore.d +++ b/libphobos/src/std/internal/math/biguintcore.d @@ -2503,13 +2503,13 @@ pure nothrow void printBiguint(const uint [] data) { char [] buff = biguintToHex(new char[data.length*9], data, '_'); - printf("%.*s\n", buff.length, buff.ptr); + printf("%.*s\n", cast(int) buff.length, buff.ptr); } void printDecimalBigUint(BigUint data) { auto str = data.toDecimalString(0); - printf("%.*s\n", str.length, str.ptr); + printf("%.*s\n", cast(int) str.length, str.ptr); } uint [] a, b; diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d index ff368b7..336c11a 100644 --- a/libphobos/src/std/math.d +++ b/libphobos/src/std/math.d @@ -263,8 +263,8 @@ version (unittest) alias real_t = double; else alias real_t = real; - ix = sprintf(bufx.ptr, "%.*Lg", ndigits, cast(real_t) x); - iy = sprintf(bufy.ptr, "%.*Lg", ndigits, cast(real_t) y); + ix = sprintf(bufx.ptr, is(real_t == real) ? "%.*Lg" : "%.*g", ndigits, cast(real_t) x); + iy = sprintf(bufy.ptr, is(real_t == real) ? "%.*Lg" : "%.*g", ndigits, cast(real_t) y); assert(ix < bufx.length && ix > 0); assert(ix < bufy.length && ix > 0); diff --git a/libphobos/src/std/parallelism.d b/libphobos/src/std/parallelism.d index 43a1ba5..61d5cea 100644 --- a/libphobos/src/std/parallelism.d +++ b/libphobos/src/std/parallelism.d @@ -4000,7 +4000,7 @@ version (unittest) import std.array : split; import std.conv : text; import std.exception : assertThrown; - import std.math : approxEqual, sqrt, log; + import std.math : approxEqual, sqrt, log, abs; import std.range : indexed, iota, join; import std.typecons : Tuple, tuple; @@ -4329,7 +4329,7 @@ version (unittest) assert(equal(iota(1_000_000), bufTrickTest)); - auto myTask = task!(std.math.abs)(-1); + auto myTask = task!(abs)(-1); taskPool.put(myTask); assert(myTask.spinForce == 1); diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d index b0310a8..1e977aa 100644 --- a/libphobos/src/std/process.d +++ b/libphobos/src/std/process.d @@ -887,7 +887,7 @@ version (Windows) @system unittest // Searches the PATH variable for the given executable file, // (checking that it is in fact executable). version (Posix) -private string searchPathFor(in char[] executable) +package(std) string searchPathFor(in char[] executable) @trusted //TODO: @safe nothrow { import std.algorithm.iteration : splitter; @@ -1358,7 +1358,8 @@ version (Windows) /** -Flags that control the behaviour of $(LREF spawnProcess) and +Flags that control the behaviour of process creation functions in this +module. Most flags only apply to $(LREF spawnProcess) and $(LREF spawnShell). Use bitwise OR to combine flags. @@ -1433,6 +1434,21 @@ enum Config Calling $(LREF wait) or $(LREF kill) with the resulting $(D Pid) is invalid. */ detached = 64, + + /** + By default, the $(LREF execute) and $(LREF executeShell) functions + will capture child processes' both stdout and stderr. This can be + undesirable if the standard output is to be processed or otherwise + used by the invoking program, as `execute`'s result would then + contain a mix of output and warning/error messages. + + Specify this flag when calling `execute` or `executeShell` to + cause invoked processes' stderr stream to be sent to $(REF stderr, + std,stdio), and only capture and return standard output. + + This flag has no effect on $(LREF spawnProcess) or $(LREF spawnShell). + */ + stderrPassThrough = 128, } @@ -2487,7 +2503,11 @@ private auto executeImpl(alias pipeFunc, Cmd, ExtraPipeFuncArgs...)( import std.array : appender; import std.typecons : Tuple; - auto p = pipeFunc(commandLine, Redirect.stdout | Redirect.stderrToStdout, + auto redirect = (config & Config.stderrPassThrough) + ? Redirect.stdout + : Redirect.stdout | Redirect.stderrToStdout; + + auto p = pipeFunc(commandLine, redirect, env, config, workDir, extraArgs); auto a = appender!(ubyte[])(); @@ -2551,6 +2571,31 @@ private auto executeImpl(alias pipeFunc, Cmd, ExtraPipeFuncArgs...)( assert(r3.output.empty); } +@system unittest +{ + // Temporarily disable output to stderr so as to not spam the build log. + import std.stdio : stderr; + import std.typecons : Tuple; + import std.file : readText; + import std.traits : ReturnType; + + ReturnType!executeShell r; + auto tmpname = uniqueTempPath; + scope(exit) if (exists(tmpname)) remove(tmpname); + auto t = stderr; + // Open a new scope to minimize code ran with stderr redirected. + { + stderr.open(tmpname, "w"); + scope(exit) stderr = t; + r = executeShell("echo D rox>&2", null, Config.stderrPassThrough); + } + assert(r.status == 0); + assert(r.output.empty); + auto witness = readText(tmpname); + import std.ascii : newline; + assert(witness == "D rox" ~ newline, "'" ~ witness ~ "'"); +} + @safe unittest { import std.typecons : Tuple; @@ -2750,8 +2795,7 @@ private struct TestScript string path; } -version (unittest) -private string uniqueTempPath() @safe +package(std) string uniqueTempPath() @safe { import std.file : tempDir; import std.path : buildPath; diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d index 13601cb..deedb68 100644 --- a/libphobos/src/std/range/package.d +++ b/libphobos/src/std/range/package.d @@ -11379,7 +11379,6 @@ if (isInputRange!R && isIntegral!(ElementType!R)) bw.popFront(); assert(bw[2 * bitsNum - 3] == true); - import core.exception : Error; import std.exception : assertThrown; // Check out of bounds error diff --git a/libphobos/src/std/regex/internal/tests.d b/libphobos/src/std/regex/internal/tests.d index 1c4f295..fe75ce0 100644 --- a/libphobos/src/std/regex/internal/tests.d +++ b/libphobos/src/std/regex/internal/tests.d @@ -8,7 +8,7 @@ package(std.regex): import std.conv, std.exception, std.meta, std.range, std.typecons, std.regex; -import std.regex.internal.parser : Escapables; // characters that need escaping +import std.regex.internal.ir : Escapables; // characters that need escaping alias Sequence(int B, int E) = staticIota!(B, E); @@ -467,654 +467,3 @@ alias Sequence(int B, int E) = staticIota!(B, E); run_tests!match(); //thompson VM } -@safe unittest -{ - auto cr = ctRegex!("abc"); - assert(bmatch("abc",cr).hit == "abc"); - auto cr2 = ctRegex!("ab*c"); - assert(bmatch("abbbbc",cr2).hit == "abbbbc"); -} -@safe unittest -{ - auto cr3 = ctRegex!("^abc$"); - assert(bmatch("abc",cr3).hit == "abc"); - auto cr4 = ctRegex!(`\b(a\B[a-z]b)\b`); - assert(array(match("azb",cr4).captures) == ["azb", "azb"]); -} - -@safe unittest -{ - auto cr5 = ctRegex!("(?:a{2,4}b{1,3}){1,2}"); - assert(bmatch("aaabaaaabbb", cr5).hit == "aaabaaaabbb"); - auto cr6 = ctRegex!("(?:a{2,4}b{1,3}){1,2}?"w); - assert(bmatch("aaabaaaabbb"w, cr6).hit == "aaab"w); -} - -@safe unittest -{ - auto cr7 = ctRegex!(`\r.*?$`,"sm"); - assert(bmatch("abc\r\nxy", cr7).hit == "\r\nxy"); - auto greed = ctRegex!("<packet.*?/packet>"); - assert(bmatch("<packet>text</packet><packet>text</packet>", greed).hit - == "<packet>text</packet>"); -} - -@safe unittest -{ - import std.algorithm.comparison : equal; - auto cr8 = ctRegex!("^(a)(b)?(c*)"); - auto m8 = bmatch("abcc",cr8); - assert(m8); - assert(m8.captures[1] == "a"); - assert(m8.captures[2] == "b"); - assert(m8.captures[3] == "cc"); - auto cr9 = ctRegex!("q(a|b)*q"); - auto m9 = match("xxqababqyy",cr9); - assert(m9); - assert(equal(bmatch("xxqababqyy",cr9).captures, ["qababq", "b"])); -} - -@safe unittest -{ - import std.algorithm.comparison : equal; - auto rtr = regex("a|b|c"); - enum ctr = regex("a|b|c"); - assert(equal(rtr.ir,ctr.ir)); - //CTFE parser BUG is triggered by group - //in the middle of alternation (at least not first and not last) - enum testCT = regex(`abc|(edf)|xyz`); - auto testRT = regex(`abc|(edf)|xyz`); - assert(equal(testCT.ir,testRT.ir)); -} - -@safe unittest -{ - import std.algorithm.comparison : equal; - import std.algorithm.iteration : map; - enum cx = ctRegex!"(A|B|C)"; - auto mx = match("B",cx); - assert(mx); - assert(equal(mx.captures, [ "B", "B"])); - enum cx2 = ctRegex!"(A|B)*"; - assert(match("BAAA",cx2)); - - enum cx3 = ctRegex!("a{3,4}","i"); - auto mx3 = match("AaA",cx3); - assert(mx3); - assert(mx3.captures[0] == "AaA"); - enum cx4 = ctRegex!(`^a{3,4}?[a-zA-Z0-9~]{1,2}`,"i"); - auto mx4 = match("aaaabc", cx4); - assert(mx4); - assert(mx4.captures[0] == "aaaab"); - auto cr8 = ctRegex!("(a)(b)?(c*)"); - auto m8 = bmatch("abcc",cr8); - assert(m8); - assert(m8.captures[1] == "a"); - assert(m8.captures[2] == "b"); - assert(m8.captures[3] == "cc"); - auto cr9 = ctRegex!(".*$", "gm"); - auto m9 = match("First\rSecond", cr9); - assert(m9); - assert(equal(map!"a.hit"(m9), ["First", "", "Second"])); -} - -@safe unittest -{ - import std.algorithm.comparison : equal; - import std.algorithm.iteration : map; -//global matching - void test_body(alias matchFn)() - { - string s = "a quick brown fox jumps over a lazy dog"; - auto r1 = regex("\\b[a-z]+\\b","g"); - string[] test; - foreach (m; matchFn(s, r1)) - test ~= m.hit; - assert(equal(test, [ "a", "quick", "brown", "fox", "jumps", "over", "a", "lazy", "dog"])); - auto free_reg = regex(` - - abc - \s+ - " - ( - [^"]+ - | \\ " - )+ - " - z - `, "x"); - auto m = match(`abc "quoted string with \" inside"z`,free_reg); - assert(m); - string mails = " hey@you.com no@spam.net "; - auto rm = regex(`@(?<=\S+@)\S+`,"g"); - assert(equal(map!"a[0]"(matchFn(mails, rm)), ["@you.com", "@spam.net"])); - auto m2 = matchFn("First line\nSecond line",regex(".*$","gm")); - assert(equal(map!"a[0]"(m2), ["First line", "", "Second line"])); - auto m2a = matchFn("First line\nSecond line",regex(".+$","gm")); - assert(equal(map!"a[0]"(m2a), ["First line", "Second line"])); - auto m2b = matchFn("First line\nSecond line",regex(".+?$","gm")); - assert(equal(map!"a[0]"(m2b), ["First line", "Second line"])); - debug(std_regex_test) writeln("!!! FReD FLAGS test done "~matchFn.stringof~" !!!"); - } - test_body!bmatch(); - test_body!match(); -} - -//tests for accumulated std.regex issues and other regressions -@safe unittest -{ - import std.algorithm.comparison : equal; - import std.algorithm.iteration : map; - void test_body(alias matchFn)() - { - //issue 5857 - //matching goes out of control if ... in (...){x} has .*/.+ - auto c = matchFn("axxxzayyyyyzd",regex("(a.*z){2}d")).captures; - assert(c[0] == "axxxzayyyyyzd"); - assert(c[1] == "ayyyyyz"); - auto c2 = matchFn("axxxayyyyyd",regex("(a.*){2}d")).captures; - assert(c2[0] == "axxxayyyyyd"); - assert(c2[1] == "ayyyyy"); - //issue 2108 - //greedy vs non-greedy - auto nogreed = regex("<packet.*?/packet>"); - assert(matchFn("<packet>text</packet><packet>text</packet>", nogreed).hit - == "<packet>text</packet>"); - auto greed = regex("<packet.*/packet>"); - assert(matchFn("<packet>text</packet><packet>text</packet>", greed).hit - == "<packet>text</packet><packet>text</packet>"); - //issue 4574 - //empty successful match still advances the input - string[] pres, posts, hits; - foreach (m; matchFn("abcabc", regex("","g"))) - { - pres ~= m.pre; - posts ~= m.post; - assert(m.hit.empty); - - } - auto heads = [ - "abcabc", - "abcab", - "abca", - "abc", - "ab", - "a", - "" - ]; - auto tails = [ - "abcabc", - "bcabc", - "cabc", - "abc", - "bc", - "c", - "" - ]; - assert(pres == array(retro(heads))); - assert(posts == tails); - //issue 6076 - //regression on .* - auto re = regex("c.*|d"); - auto m = matchFn("mm", re); - assert(!m); - debug(std_regex_test) writeln("!!! FReD REGRESSION test done "~matchFn.stringof~" !!!"); - auto rprealloc = regex(`((.){5}.{1,10}){5}`); - auto arr = array(repeat('0',100)); - auto m2 = matchFn(arr, rprealloc); - assert(m2); - assert(collectException( - regex(r"^(import|file|binary|config)\s+([^\(]+)\(?([^\)]*)\)?\s*$") - ) is null); - foreach (ch; [Escapables]) - { - assert(match(to!string(ch),regex(`[\`~ch~`]`))); - assert(!match(to!string(ch),regex(`[^\`~ch~`]`))); - assert(match(to!string(ch),regex(`[\`~ch~`-\`~ch~`]`))); - } - //bugzilla 7718 - string strcmd = "./myApp.rb -os OSX -path \"/GIT/Ruby Apps/sec\" -conf 'notimer'"; - auto reStrCmd = regex (`(".*")|('.*')`, "g"); - assert(equal(map!"a[0]"(matchFn(strcmd, reStrCmd)), - [`"/GIT/Ruby Apps/sec"`, `'notimer'`])); - } - test_body!bmatch(); - test_body!match(); -} - -// tests for replace -@safe unittest -{ - void test(alias matchFn)() - { - import std.uni : toUpper; - - foreach (i, v; AliasSeq!(string, wstring, dstring)) - { - auto baz(Cap)(Cap m) - if (is(Cap == Captures!(Cap.String))) - { - return toUpper(m.hit); - } - alias String = v; - assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r")), to!String("c")) - == to!String("ack rapacity")); - assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r"), "g"), to!String("c")) - == to!String("ack capacity")); - assert(std.regex.replace!(matchFn)(to!String("noon"), regex(to!String("^n")), to!String("[$&]")) - == to!String("[n]oon")); - assert(std.regex.replace!(matchFn)( - to!String("test1 test2"), regex(to!String(`\w+`),"g"), to!String("$`:$'") - ) == to!String(": test2 test1 :")); - auto s = std.regex.replace!(baz!(Captures!(String)))(to!String("Strap a rocket engine on a chicken."), - regex(to!String("[ar]"), "g")); - assert(s == "StRAp A Rocket engine on A chicken."); - } - debug(std_regex_test) writeln("!!! Replace test done "~matchFn.stringof~" !!!"); - } - test!(bmatch)(); - test!(match)(); -} - -// tests for splitter -@safe unittest -{ - import std.algorithm.comparison : equal; - auto s1 = ", abc, de, fg, hi, "; - auto sp1 = splitter(s1, regex(", *")); - auto w1 = ["", "abc", "de", "fg", "hi", ""]; - assert(equal(sp1, w1)); - - auto s2 = ", abc, de, fg, hi"; - auto sp2 = splitter(s2, regex(", *")); - auto w2 = ["", "abc", "de", "fg", "hi"]; - - uint cnt; - foreach (e; sp2) - { - assert(w2[cnt++] == e); - } - assert(equal(sp2, w2)); -} - -@safe unittest -{ - char[] s1 = ", abc, de, fg, hi, ".dup; - auto sp2 = splitter(s1, regex(", *")); -} - -@safe unittest -{ - import std.algorithm.comparison : equal; - auto s1 = ", abc, de, fg, hi, "; - auto w1 = ["", "abc", "de", "fg", "hi", ""]; - assert(equal(split(s1, regex(", *")), w1[])); -} - -@safe unittest -{ // bugzilla 7141 - string pattern = `[a\--b]`; - assert(match("-", pattern)); - assert(match("b", pattern)); - string pattern2 = `[&-z]`; - assert(match("b", pattern2)); -} -@safe unittest -{//bugzilla 7111 - assert(match("", regex("^"))); -} -@safe unittest -{//bugzilla 7300 - assert(!match("a"d, "aa"d)); -} - -// bugzilla 7551 -@safe unittest -{ - auto r = regex("[]abc]*"); - assert("]ab".matchFirst(r).hit == "]ab"); - assertThrown(regex("[]")); - auto r2 = regex("[]abc--ab]*"); - assert("]ac".matchFirst(r2).hit == "]"); -} - -@safe unittest -{//bugzilla 7674 - assert("1234".replace(regex("^"), "$$") == "$1234"); - assert("hello?".replace(regex(r"\?", "g"), r"\?") == r"hello\?"); - assert("hello?".replace(regex(r"\?", "g"), r"\\?") != r"hello\?"); -} -@safe unittest -{// bugzilla 7679 - import std.algorithm.comparison : equal; - foreach (S; AliasSeq!(string, wstring, dstring)) - (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396 - enum re = ctRegex!(to!S(r"\.")); - auto str = to!S("a.b"); - assert(equal(std.regex.splitter(str, re), [to!S("a"), to!S("b")])); - assert(split(str, re) == [to!S("a"), to!S("b")]); - }(); -} -@safe unittest -{//bugzilla 8203 - string data = " - NAME = XPAW01_STA:STATION - NAME = XPAW01_STA - "; - auto uniFileOld = data; - auto r = regex( - r"^NAME = (?P<comp>[a-zA-Z0-9_]+):*(?P<blk>[a-zA-Z0-9_]*)","gm"); - auto uniCapturesNew = match(uniFileOld, r); - for (int i = 0; i < 20; i++) - foreach (matchNew; uniCapturesNew) {} - //a second issue with same symptoms - auto r2 = regex(`([а-яА-Я\-_]+\s*)+(?<=[\s\.,\^])`); - match("аллея Театральная", r2); -} -@safe unittest -{// bugzilla 8637 purity of enforce - auto m = match("hello world", regex("world")); - enforce(m); -} - -// bugzilla 8725 -@safe unittest -{ - static italic = regex( r"\* - (?!\s+) - (.*?) - (?!\s+) - \*", "gx" ); - string input = "this * is* interesting, *very* interesting"; - assert(replace(input, italic, "<i>$1</i>") == - "this * is* interesting, <i>very</i> interesting"); -} - -// bugzilla 8349 -@safe unittest -{ - enum peakRegexStr = r"\>(wgEncode.*Tfbs.*\.(?:narrow)|(?:broad)Peak.gz)</a>"; - enum peakRegex = ctRegex!(peakRegexStr); - //note that the regex pattern itself is probably bogus - assert(match(r"\>wgEncode-blah-Tfbs.narrow</a>", peakRegex)); -} - -// bugzilla 9211 -@safe unittest -{ - import std.algorithm.comparison : equal; - auto rx_1 = regex(r"^(\w)*(\d)"); - auto m = match("1234", rx_1); - assert(equal(m.front, ["1234", "3", "4"])); - auto rx_2 = regex(r"^([0-9])*(\d)"); - auto m2 = match("1234", rx_2); - assert(equal(m2.front, ["1234", "3", "4"])); -} - -// bugzilla 9280 -@safe unittest -{ - string tomatch = "a!b@c"; - static r = regex(r"^(?P<nick>.*?)!(?P<ident>.*?)@(?P<host>.*?)$"); - auto nm = match(tomatch, r); - assert(nm); - auto c = nm.captures; - assert(c[1] == "a"); - assert(c["nick"] == "a"); -} - - -// bugzilla 9579 -@safe unittest -{ - char[] input = ['a', 'b', 'c']; - string format = "($1)"; - // used to give a compile error: - auto re = regex(`(a)`, "g"); - auto r = replace(input, re, format); - assert(r == "(a)bc"); -} - -// bugzilla 9634 -@safe unittest -{ - auto re = ctRegex!"(?:a+)"; - assert(match("aaaa", re).hit == "aaaa"); -} - -//bugzilla 10798 -@safe unittest -{ - auto cr = ctRegex!("[abcd--c]*"); - auto m = "abc".match(cr); - assert(m); - assert(m.hit == "ab"); -} - -// bugzilla 10913 -@system unittest -{ - @system static string foo(const(char)[] s) - { - return s.dup; - } - @safe static string bar(const(char)[] s) - { - return s.dup; - } - () @system { - replace!((a) => foo(a.hit))("blah", regex(`a`)); - }(); - () @safe { - replace!((a) => bar(a.hit))("blah", regex(`a`)); - }(); -} - -// bugzilla 11262 -@safe unittest -{ - enum reg = ctRegex!(r",", "g"); - auto str = "This,List"; - str = str.replace(reg, "-"); - assert(str == "This-List"); -} - -// bugzilla 11775 -@safe unittest -{ - assert(collectException(regex("a{1,0}"))); -} - -// bugzilla 11839 -@safe unittest -{ - import std.algorithm.comparison : equal; - assert(regex(`(?P<var1>\w+)`).namedCaptures.equal(["var1"])); - assert(collectException(regex(`(?P<1>\w+)`))); - assert(regex(`(?P<v1>\w+)`).namedCaptures.equal(["v1"])); - assert(regex(`(?P<__>\w+)`).namedCaptures.equal(["__"])); - assert(regex(`(?P<я>\w+)`).namedCaptures.equal(["я"])); -} - -// bugzilla 12076 -@safe unittest -{ - auto RE = ctRegex!(r"(?<!x[a-z]+)\s([a-z]+)"); - string s = "one two"; - auto m = match(s, RE); -} - -// bugzilla 12105 -@safe unittest -{ - auto r = ctRegex!`.*?(?!a)`; - assert("aaab".matchFirst(r).hit == "aaa"); - auto r2 = ctRegex!`.*(?!a)`; - assert("aaab".matchFirst(r2).hit == "aaab"); -} - -//bugzilla 11784 -@safe unittest -{ - assert("abcdefghijklmnopqrstuvwxyz" - .matchFirst("[a-z&&[^aeiuo]]").hit == "b"); -} - -//bugzilla 12366 -@safe unittest -{ - auto re = ctRegex!(`^((?=(xx+?)\2+$)((?=\2+$)(?=(x+)(\4+$))\5){2})*x?$`); - assert("xxxxxxxx".match(re).empty); - assert(!"xxxx".match(re).empty); -} - -// bugzilla 12582 -@safe unittest -{ - auto r = regex(`(?P<a>abc)`); - assert(collectException("abc".matchFirst(r)["b"])); -} - -// bugzilla 12691 -@safe unittest -{ - assert(bmatch("e@", "^([a-z]|)*$").empty); - assert(bmatch("e@", ctRegex!`^([a-z]|)*$`).empty); -} - -//bugzilla 12713 -@safe unittest -{ - assertThrown(regex("[[a-z]([a-z]|(([[a-z])))")); -} - -//bugzilla 12747 -@safe unittest -{ - assertThrown(regex(`^x(\1)`)); - assertThrown(regex(`^(x(\1))`)); - assertThrown(regex(`^((x)(?=\1))`)); -} - -// bugzilla 14504 -@safe unittest -{ - auto p = ctRegex!("a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?" ~ - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); -} - -// bugzilla 14529 -@safe unittest -{ - auto ctPat2 = regex(r"^[CDF]$", "i"); - foreach (v; ["C", "c", "D", "d", "F", "f"]) - assert(matchAll(v, ctPat2).front.hit == v); -} - -// bugzilla 14615 -@safe unittest -{ - import std.array : appender; - import std.regex : replaceFirst, replaceFirstInto, regex; - import std.stdio : writeln; - - auto example = "Hello, world!"; - auto pattern = regex("^Hello, (bug)"); // won't find this one - auto result = replaceFirst(example, pattern, "$1 Sponge Bob"); - assert(result == "Hello, world!"); // Ok. - - auto sink = appender!string; - replaceFirstInto(sink, example, pattern, "$1 Sponge Bob"); - assert(sink.data == "Hello, world!"); - replaceAllInto(sink, example, pattern, "$1 Sponge Bob"); - assert(sink.data == "Hello, world!Hello, world!"); -} - -// bugzilla 15573 -@safe unittest -{ - auto rx = regex("[c d]", "x"); - assert("a b".matchFirst(rx)); -} - -// bugzilla 15864 -@safe unittest -{ - regex(`(<a (?:(?:\w+=\"[^"]*\")?\s*)*href="\.\.?)"`); -} - -@safe unittest -{ - auto r = regex("(?# comment)abc(?# comment2)"); - assert("abc".matchFirst(r)); - assertThrown(regex("(?#...")); -} - -// bugzilla 17075 -@safe unittest -{ - enum titlePattern = `<title>(.+)</title>`; - static titleRegex = ctRegex!titlePattern; - string input = "<title>" ~ "<".repeat(100_000).join; - assert(input.matchFirst(titleRegex).empty); -} - -// bugzilla 17212 -@safe unittest -{ - auto r = regex(" [a] ", "x"); - assert("a".matchFirst(r)); -} - -// bugzilla 17157 -@safe unittest -{ - import std.algorithm.comparison : equal; - auto ctr = ctRegex!"(a)|(b)|(c)|(d)"; - auto r = regex("(a)|(b)|(c)|(d)", "g"); - auto s = "--a--b--c--d--"; - auto outcomes = [ - ["a", "a", "", "", ""], - ["b", "", "b", "", ""], - ["c", "", "", "c", ""], - ["d", "", "", "", "d"] - ]; - assert(equal!equal(s.matchAll(ctr), outcomes)); - assert(equal!equal(s.bmatch(r), outcomes)); -} - -// bugzilla 17667 -@safe unittest -{ - import std.algorithm.searching : canFind; - void willThrow(T, size_t line = __LINE__)(T arg, string msg) - { - auto e = collectException(regex(arg)); - assert(e.msg.canFind(msg), to!string(line) ~ ": " ~ e.msg); - } - willThrow([r".", r"[\(\{[\]\}\)]"], "no matching ']' found while parsing character class"); - willThrow([r"[\", r"123"], "no matching ']' found while parsing character class"); - willThrow([r"[a-", r"123"], "no matching ']' found while parsing character class"); - willThrow([r"[a-\", r"123"], "invalid escape sequence"); - willThrow([r"\", r"123"], "invalid escape sequence"); -} - -// bugzilla 17668 -@safe unittest -{ - import std.algorithm.searching; - auto e = collectException!RegexException(regex(q"<[^]>")); - assert(e.msg.canFind("no operand for '^'")); -} - -// bugzilla 17673 -@safe unittest -{ - string str = `<">`; - string[] regexps = ["abc", "\"|x"]; - auto regexp = regex(regexps); - auto c = matchFirst(str, regexp); - assert(c); - assert(c.whichPattern == 2); -} - diff --git a/libphobos/src/std/regex/internal/tests2.d b/libphobos/src/std/regex/internal/tests2.d new file mode 100644 index 0000000..420f8d3 --- /dev/null +++ b/libphobos/src/std/regex/internal/tests2.d @@ -0,0 +1,662 @@ +// Split-up due to DMD's enormous memory consumption + +module std.regex.internal.tests2; + +package(std.regex): + +import std.conv, std.exception, std.meta, std.range, + std.typecons, std.regex; + +import std.regex.internal.ir : Escapables; // characters that need escaping + +@safe unittest +{ + auto cr = ctRegex!("abc"); + assert(bmatch("abc",cr).hit == "abc"); + auto cr2 = ctRegex!("ab*c"); + assert(bmatch("abbbbc",cr2).hit == "abbbbc"); +} +@safe unittest +{ + auto cr3 = ctRegex!("^abc$"); + assert(bmatch("abc",cr3).hit == "abc"); + auto cr4 = ctRegex!(`\b(a\B[a-z]b)\b`); + assert(array(match("azb",cr4).captures) == ["azb", "azb"]); +} + +@safe unittest +{ + auto cr5 = ctRegex!("(?:a{2,4}b{1,3}){1,2}"); + assert(bmatch("aaabaaaabbb", cr5).hit == "aaabaaaabbb"); + auto cr6 = ctRegex!("(?:a{2,4}b{1,3}){1,2}?"w); + assert(bmatch("aaabaaaabbb"w, cr6).hit == "aaab"w); +} + +@safe unittest +{ + auto cr7 = ctRegex!(`\r.*?$`,"sm"); + assert(bmatch("abc\r\nxy", cr7).hit == "\r\nxy"); + auto greed = ctRegex!("<packet.*?/packet>"); + assert(bmatch("<packet>text</packet><packet>text</packet>", greed).hit + == "<packet>text</packet>"); +} + +@safe unittest +{ + import std.algorithm.comparison : equal; + auto cr8 = ctRegex!("^(a)(b)?(c*)"); + auto m8 = bmatch("abcc",cr8); + assert(m8); + assert(m8.captures[1] == "a"); + assert(m8.captures[2] == "b"); + assert(m8.captures[3] == "cc"); + auto cr9 = ctRegex!("q(a|b)*q"); + auto m9 = match("xxqababqyy",cr9); + assert(m9); + assert(equal(bmatch("xxqababqyy",cr9).captures, ["qababq", "b"])); +} + +@safe unittest +{ + import std.algorithm.comparison : equal; + auto rtr = regex("a|b|c"); + enum ctr = regex("a|b|c"); + assert(equal(rtr.ir,ctr.ir)); + //CTFE parser BUG is triggered by group + //in the middle of alternation (at least not first and not last) + enum testCT = regex(`abc|(edf)|xyz`); + auto testRT = regex(`abc|(edf)|xyz`); + assert(equal(testCT.ir,testRT.ir)); +} + +@safe unittest +{ + import std.algorithm.comparison : equal; + import std.algorithm.iteration : map; + enum cx = ctRegex!"(A|B|C)"; + auto mx = match("B",cx); + assert(mx); + assert(equal(mx.captures, [ "B", "B"])); + enum cx2 = ctRegex!"(A|B)*"; + assert(match("BAAA",cx2)); + + enum cx3 = ctRegex!("a{3,4}","i"); + auto mx3 = match("AaA",cx3); + assert(mx3); + assert(mx3.captures[0] == "AaA"); + enum cx4 = ctRegex!(`^a{3,4}?[a-zA-Z0-9~]{1,2}`,"i"); + auto mx4 = match("aaaabc", cx4); + assert(mx4); + assert(mx4.captures[0] == "aaaab"); + auto cr8 = ctRegex!("(a)(b)?(c*)"); + auto m8 = bmatch("abcc",cr8); + assert(m8); + assert(m8.captures[1] == "a"); + assert(m8.captures[2] == "b"); + assert(m8.captures[3] == "cc"); + auto cr9 = ctRegex!(".*$", "gm"); + auto m9 = match("First\rSecond", cr9); + assert(m9); + assert(equal(map!"a.hit"(m9), ["First", "", "Second"])); +} + +@safe unittest +{ + import std.algorithm.comparison : equal; + import std.algorithm.iteration : map; +//global matching + void test_body(alias matchFn)() + { + string s = "a quick brown fox jumps over a lazy dog"; + auto r1 = regex("\\b[a-z]+\\b","g"); + string[] test; + foreach (m; matchFn(s, r1)) + test ~= m.hit; + assert(equal(test, [ "a", "quick", "brown", "fox", "jumps", "over", "a", "lazy", "dog"])); + auto free_reg = regex(` + + abc + \s+ + " + ( + [^"]+ + | \\ " + )+ + " + z + `, "x"); + auto m = match(`abc "quoted string with \" inside"z`,free_reg); + assert(m); + string mails = " hey@you.com no@spam.net "; + auto rm = regex(`@(?<=\S+@)\S+`,"g"); + assert(equal(map!"a[0]"(matchFn(mails, rm)), ["@you.com", "@spam.net"])); + auto m2 = matchFn("First line\nSecond line",regex(".*$","gm")); + assert(equal(map!"a[0]"(m2), ["First line", "", "Second line"])); + auto m2a = matchFn("First line\nSecond line",regex(".+$","gm")); + assert(equal(map!"a[0]"(m2a), ["First line", "Second line"])); + auto m2b = matchFn("First line\nSecond line",regex(".+?$","gm")); + assert(equal(map!"a[0]"(m2b), ["First line", "Second line"])); + debug(std_regex_test) writeln("!!! FReD FLAGS test done "~matchFn.stringof~" !!!"); + } + test_body!bmatch(); + test_body!match(); +} + +//tests for accumulated std.regex issues and other regressions +@safe unittest +{ + import std.algorithm.comparison : equal; + import std.algorithm.iteration : map; + void test_body(alias matchFn)() + { + //issue 5857 + //matching goes out of control if ... in (...){x} has .*/.+ + auto c = matchFn("axxxzayyyyyzd",regex("(a.*z){2}d")).captures; + assert(c[0] == "axxxzayyyyyzd"); + assert(c[1] == "ayyyyyz"); + auto c2 = matchFn("axxxayyyyyd",regex("(a.*){2}d")).captures; + assert(c2[0] == "axxxayyyyyd"); + assert(c2[1] == "ayyyyy"); + //issue 2108 + //greedy vs non-greedy + auto nogreed = regex("<packet.*?/packet>"); + assert(matchFn("<packet>text</packet><packet>text</packet>", nogreed).hit + == "<packet>text</packet>"); + auto greed = regex("<packet.*/packet>"); + assert(matchFn("<packet>text</packet><packet>text</packet>", greed).hit + == "<packet>text</packet><packet>text</packet>"); + //issue 4574 + //empty successful match still advances the input + string[] pres, posts, hits; + foreach (m; matchFn("abcabc", regex("","g"))) + { + pres ~= m.pre; + posts ~= m.post; + assert(m.hit.empty); + + } + auto heads = [ + "abcabc", + "abcab", + "abca", + "abc", + "ab", + "a", + "" + ]; + auto tails = [ + "abcabc", + "bcabc", + "cabc", + "abc", + "bc", + "c", + "" + ]; + assert(pres == array(retro(heads))); + assert(posts == tails); + //issue 6076 + //regression on .* + auto re = regex("c.*|d"); + auto m = matchFn("mm", re); + assert(!m); + debug(std_regex_test) writeln("!!! FReD REGRESSION test done "~matchFn.stringof~" !!!"); + auto rprealloc = regex(`((.){5}.{1,10}){5}`); + auto arr = array(repeat('0',100)); + auto m2 = matchFn(arr, rprealloc); + assert(m2); + assert(collectException( + regex(r"^(import|file|binary|config)\s+([^\(]+)\(?([^\)]*)\)?\s*$") + ) is null); + foreach (ch; [Escapables]) + { + assert(match(to!string(ch),regex(`[\`~ch~`]`))); + assert(!match(to!string(ch),regex(`[^\`~ch~`]`))); + assert(match(to!string(ch),regex(`[\`~ch~`-\`~ch~`]`))); + } + //bugzilla 7718 + string strcmd = "./myApp.rb -os OSX -path \"/GIT/Ruby Apps/sec\" -conf 'notimer'"; + auto reStrCmd = regex (`(".*")|('.*')`, "g"); + assert(equal(map!"a[0]"(matchFn(strcmd, reStrCmd)), + [`"/GIT/Ruby Apps/sec"`, `'notimer'`])); + } + test_body!bmatch(); + test_body!match(); +} + +// tests for replace +@safe unittest +{ + void test(alias matchFn)() + { + import std.uni : toUpper; + + foreach (i, v; AliasSeq!(string, wstring, dstring)) + { + auto baz(Cap)(Cap m) + if (is(Cap == Captures!(Cap.String))) + { + return toUpper(m.hit); + } + alias String = v; + assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r")), to!String("c")) + == to!String("ack rapacity")); + assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r"), "g"), to!String("c")) + == to!String("ack capacity")); + assert(std.regex.replace!(matchFn)(to!String("noon"), regex(to!String("^n")), to!String("[$&]")) + == to!String("[n]oon")); + assert(std.regex.replace!(matchFn)( + to!String("test1 test2"), regex(to!String(`\w+`),"g"), to!String("$`:$'") + ) == to!String(": test2 test1 :")); + auto s = std.regex.replace!(baz!(Captures!(String)))(to!String("Strap a rocket engine on a chicken."), + regex(to!String("[ar]"), "g")); + assert(s == "StRAp A Rocket engine on A chicken."); + } + debug(std_regex_test) writeln("!!! Replace test done "~matchFn.stringof~" !!!"); + } + test!(bmatch)(); + test!(match)(); +} + +// tests for splitter +@safe unittest +{ + import std.algorithm.comparison : equal; + auto s1 = ", abc, de, fg, hi, "; + auto sp1 = splitter(s1, regex(", *")); + auto w1 = ["", "abc", "de", "fg", "hi", ""]; + assert(equal(sp1, w1)); + + auto s2 = ", abc, de, fg, hi"; + auto sp2 = splitter(s2, regex(", *")); + auto w2 = ["", "abc", "de", "fg", "hi"]; + + uint cnt; + foreach (e; sp2) + { + assert(w2[cnt++] == e); + } + assert(equal(sp2, w2)); +} + +@safe unittest +{ + char[] s1 = ", abc, de, fg, hi, ".dup; + auto sp2 = splitter(s1, regex(", *")); +} + +@safe unittest +{ + import std.algorithm.comparison : equal; + auto s1 = ", abc, de, fg, hi, "; + auto w1 = ["", "abc", "de", "fg", "hi", ""]; + assert(equal(split(s1, regex(", *")), w1[])); +} + +@safe unittest +{ // bugzilla 7141 + string pattern = `[a\--b]`; + assert(match("-", pattern)); + assert(match("b", pattern)); + string pattern2 = `[&-z]`; + assert(match("b", pattern2)); +} +@safe unittest +{//bugzilla 7111 + assert(match("", regex("^"))); +} +@safe unittest +{//bugzilla 7300 + assert(!match("a"d, "aa"d)); +} + +// bugzilla 7551 +@safe unittest +{ + auto r = regex("[]abc]*"); + assert("]ab".matchFirst(r).hit == "]ab"); + assertThrown(regex("[]")); + auto r2 = regex("[]abc--ab]*"); + assert("]ac".matchFirst(r2).hit == "]"); +} + +@safe unittest +{//bugzilla 7674 + assert("1234".replace(regex("^"), "$$") == "$1234"); + assert("hello?".replace(regex(r"\?", "g"), r"\?") == r"hello\?"); + assert("hello?".replace(regex(r"\?", "g"), r"\\?") != r"hello\?"); +} +@safe unittest +{// bugzilla 7679 + import std.algorithm.comparison : equal; + foreach (S; AliasSeq!(string, wstring, dstring)) + (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396 + enum re = ctRegex!(to!S(r"\.")); + auto str = to!S("a.b"); + assert(equal(std.regex.splitter(str, re), [to!S("a"), to!S("b")])); + assert(split(str, re) == [to!S("a"), to!S("b")]); + }(); +} +@safe unittest +{//bugzilla 8203 + string data = " + NAME = XPAW01_STA:STATION + NAME = XPAW01_STA + "; + auto uniFileOld = data; + auto r = regex( + r"^NAME = (?P<comp>[a-zA-Z0-9_]+):*(?P<blk>[a-zA-Z0-9_]*)","gm"); + auto uniCapturesNew = match(uniFileOld, r); + for (int i = 0; i < 20; i++) + foreach (matchNew; uniCapturesNew) {} + //a second issue with same symptoms + auto r2 = regex(`([а-яА-Я\-_]+\s*)+(?<=[\s\.,\^])`); + match("аллея Театральная", r2); +} +@safe unittest +{// bugzilla 8637 purity of enforce + auto m = match("hello world", regex("world")); + enforce(m); +} + +// bugzilla 8725 +@safe unittest +{ + static italic = regex( r"\* + (?!\s+) + (.*?) + (?!\s+) + \*", "gx" ); + string input = "this * is* interesting, *very* interesting"; + assert(replace(input, italic, "<i>$1</i>") == + "this * is* interesting, <i>very</i> interesting"); +} + +// bugzilla 8349 +@safe unittest +{ + enum peakRegexStr = r"\>(wgEncode.*Tfbs.*\.(?:narrow)|(?:broad)Peak.gz)</a>"; + enum peakRegex = ctRegex!(peakRegexStr); + //note that the regex pattern itself is probably bogus + assert(match(r"\>wgEncode-blah-Tfbs.narrow</a>", peakRegex)); +} + +// bugzilla 9211 +@safe unittest +{ + import std.algorithm.comparison : equal; + auto rx_1 = regex(r"^(\w)*(\d)"); + auto m = match("1234", rx_1); + assert(equal(m.front, ["1234", "3", "4"])); + auto rx_2 = regex(r"^([0-9])*(\d)"); + auto m2 = match("1234", rx_2); + assert(equal(m2.front, ["1234", "3", "4"])); +} + +// bugzilla 9280 +@safe unittest +{ + string tomatch = "a!b@c"; + static r = regex(r"^(?P<nick>.*?)!(?P<ident>.*?)@(?P<host>.*?)$"); + auto nm = match(tomatch, r); + assert(nm); + auto c = nm.captures; + assert(c[1] == "a"); + assert(c["nick"] == "a"); +} + + +// bugzilla 9579 +@safe unittest +{ + char[] input = ['a', 'b', 'c']; + string format = "($1)"; + // used to give a compile error: + auto re = regex(`(a)`, "g"); + auto r = replace(input, re, format); + assert(r == "(a)bc"); +} + +// bugzilla 9634 +@safe unittest +{ + auto re = ctRegex!"(?:a+)"; + assert(match("aaaa", re).hit == "aaaa"); +} + +//bugzilla 10798 +@safe unittest +{ + auto cr = ctRegex!("[abcd--c]*"); + auto m = "abc".match(cr); + assert(m); + assert(m.hit == "ab"); +} + +// bugzilla 10913 +@system unittest +{ + @system static string foo(const(char)[] s) + { + return s.dup; + } + @safe static string bar(const(char)[] s) + { + return s.dup; + } + () @system { + replace!((a) => foo(a.hit))("blah", regex(`a`)); + }(); + () @safe { + replace!((a) => bar(a.hit))("blah", regex(`a`)); + }(); +} + +// bugzilla 11262 +@safe unittest +{ + enum reg = ctRegex!(r",", "g"); + auto str = "This,List"; + str = str.replace(reg, "-"); + assert(str == "This-List"); +} + +// bugzilla 11775 +@safe unittest +{ + assert(collectException(regex("a{1,0}"))); +} + +// bugzilla 11839 +@safe unittest +{ + import std.algorithm.comparison : equal; + assert(regex(`(?P<var1>\w+)`).namedCaptures.equal(["var1"])); + assert(collectException(regex(`(?P<1>\w+)`))); + assert(regex(`(?P<v1>\w+)`).namedCaptures.equal(["v1"])); + assert(regex(`(?P<__>\w+)`).namedCaptures.equal(["__"])); + assert(regex(`(?P<я>\w+)`).namedCaptures.equal(["я"])); +} + +// bugzilla 12076 +@safe unittest +{ + auto RE = ctRegex!(r"(?<!x[a-z]+)\s([a-z]+)"); + string s = "one two"; + auto m = match(s, RE); +} + +// bugzilla 12105 +@safe unittest +{ + auto r = ctRegex!`.*?(?!a)`; + assert("aaab".matchFirst(r).hit == "aaa"); + auto r2 = ctRegex!`.*(?!a)`; + assert("aaab".matchFirst(r2).hit == "aaab"); +} + +//bugzilla 11784 +@safe unittest +{ + assert("abcdefghijklmnopqrstuvwxyz" + .matchFirst("[a-z&&[^aeiuo]]").hit == "b"); +} + +//bugzilla 12366 +@safe unittest +{ + auto re = ctRegex!(`^((?=(xx+?)\2+$)((?=\2+$)(?=(x+)(\4+$))\5){2})*x?$`); + assert("xxxxxxxx".match(re).empty); + assert(!"xxxx".match(re).empty); +} + +// bugzilla 12582 +@safe unittest +{ + auto r = regex(`(?P<a>abc)`); + assert(collectException("abc".matchFirst(r)["b"])); +} + +// bugzilla 12691 +@safe unittest +{ + assert(bmatch("e@", "^([a-z]|)*$").empty); + assert(bmatch("e@", ctRegex!`^([a-z]|)*$`).empty); +} + +//bugzilla 12713 +@safe unittest +{ + assertThrown(regex("[[a-z]([a-z]|(([[a-z])))")); +} + +//bugzilla 12747 +@safe unittest +{ + assertThrown(regex(`^x(\1)`)); + assertThrown(regex(`^(x(\1))`)); + assertThrown(regex(`^((x)(?=\1))`)); +} + +// bugzilla 14504 +@safe unittest +{ + auto p = ctRegex!("a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?" ~ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); +} + +// bugzilla 14529 +@safe unittest +{ + auto ctPat2 = regex(r"^[CDF]$", "i"); + foreach (v; ["C", "c", "D", "d", "F", "f"]) + assert(matchAll(v, ctPat2).front.hit == v); +} + +// bugzilla 14615 +@safe unittest +{ + import std.array : appender; + import std.regex : replaceFirst, replaceFirstInto, regex; + import std.stdio : writeln; + + auto example = "Hello, world!"; + auto pattern = regex("^Hello, (bug)"); // won't find this one + auto result = replaceFirst(example, pattern, "$1 Sponge Bob"); + assert(result == "Hello, world!"); // Ok. + + auto sink = appender!string; + replaceFirstInto(sink, example, pattern, "$1 Sponge Bob"); + assert(sink.data == "Hello, world!"); + replaceAllInto(sink, example, pattern, "$1 Sponge Bob"); + assert(sink.data == "Hello, world!Hello, world!"); +} + +// bugzilla 15573 +@safe unittest +{ + auto rx = regex("[c d]", "x"); + assert("a b".matchFirst(rx)); +} + +// bugzilla 15864 +@safe unittest +{ + regex(`(<a (?:(?:\w+=\"[^"]*\")?\s*)*href="\.\.?)"`); +} + +@safe unittest +{ + auto r = regex("(?# comment)abc(?# comment2)"); + assert("abc".matchFirst(r)); + assertThrown(regex("(?#...")); +} + +// bugzilla 17075 +@safe unittest +{ + enum titlePattern = `<title>(.+)</title>`; + static titleRegex = ctRegex!titlePattern; + string input = "<title>" ~ "<".repeat(100_000).join; + assert(input.matchFirst(titleRegex).empty); +} + +// bugzilla 17212 +@safe unittest +{ + auto r = regex(" [a] ", "x"); + assert("a".matchFirst(r)); +} + +// bugzilla 17157 +@safe unittest +{ + import std.algorithm.comparison : equal; + auto ctr = ctRegex!"(a)|(b)|(c)|(d)"; + auto r = regex("(a)|(b)|(c)|(d)", "g"); + auto s = "--a--b--c--d--"; + auto outcomes = [ + ["a", "a", "", "", ""], + ["b", "", "b", "", ""], + ["c", "", "", "c", ""], + ["d", "", "", "", "d"] + ]; + assert(equal!equal(s.matchAll(ctr), outcomes)); + assert(equal!equal(s.bmatch(r), outcomes)); +} + +// bugzilla 17667 +@safe unittest +{ + import std.algorithm.searching : canFind; + void willThrow(T, size_t line = __LINE__)(T arg, string msg) + { + auto e = collectException(regex(arg)); + assert(e.msg.canFind(msg), to!string(line) ~ ": " ~ e.msg); + } + willThrow([r".", r"[\(\{[\]\}\)]"], "no matching ']' found while parsing character class"); + willThrow([r"[\", r"123"], "no matching ']' found while parsing character class"); + willThrow([r"[a-", r"123"], "no matching ']' found while parsing character class"); + willThrow([r"[a-\", r"123"], "invalid escape sequence"); + willThrow([r"\", r"123"], "invalid escape sequence"); +} + +// bugzilla 17668 +@safe unittest +{ + import std.algorithm.searching; + auto e = collectException!RegexException(regex(q"<[^]>")); + assert(e.msg.canFind("no operand for '^'")); +} + +// bugzilla 17673 +@safe unittest +{ + string str = `<">`; + string[] regexps = ["abc", "\"|x"]; + auto regexp = regex(regexps); + auto c = matchFirst(str, regexp); + assert(c); + assert(c.whichPattern == 2); +} + diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d index ecb2c8b..d7de153 100644 --- a/libphobos/src/std/socket.d +++ b/libphobos/src/std/socket.d @@ -85,10 +85,10 @@ else version (Posix) } } + public import core.sys.posix.netinet.in_; import core.sys.posix.arpa.inet; import core.sys.posix.fcntl; import core.sys.posix.netdb; - import core.sys.posix.netinet.in_; import core.sys.posix.netinet.tcp; import core.sys.posix.sys.select; import core.sys.posix.sys.socket; diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d index a63227c..84e876f 100644 --- a/libphobos/src/std/typecons.d +++ b/libphobos/src/std/typecons.d @@ -4204,10 +4204,11 @@ package template OverloadSet(string nam, T...) /* Used by MemberFunctionGenerator. */ -package template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func)) +package template FuncInfo(alias func) +if (is(typeof(&func))) { - alias RT = ReturnType!T; - alias PT = Parameters!T; + alias RT = ReturnType!(typeof(&func)); + alias PT = Parameters!(typeof(&func)); } package template FuncInfo(Func) { @@ -4248,6 +4249,7 @@ private static: // Internal stuffs //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// import std.format; + alias format = std.format.format; enum CONSTRUCTOR_NAME = "__ctor"; @@ -5024,7 +5026,7 @@ package template GetOverloadedMethods(T) enum isMethod = false; } alias follows = AliasSeq!( - std.meta.Filter!(isMethod, __traits(getOverloads, T, name)), + Filter!(isMethod, __traits(getOverloads, T, name)), follows!(i + 1)); } } @@ -5933,13 +5935,7 @@ mixin template Proxy(alias a) // built-in type field, manifest constant, and static non-mutable field enum opDispatch = mixin("a."~name); } - else static if (is(typeof(mixin("a."~name))) || __traits(getOverloads, a, name).length != 0) - { - // field or property function - @property auto ref opDispatch(this X)() { return mixin("a."~name); } - @property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); } - } - else + else static if (__traits(isTemplate, mixin("a."~name))) { // member template template opDispatch(T...) @@ -5948,6 +5944,13 @@ mixin template Proxy(alias a) auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); } } } + else + { + // field or property function + @property auto ref opDispatch(this X)() { return mixin("a."~name); } + @property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); } + } + } import std.traits : isArray; diff --git a/libphobos/src/std/zip.d b/libphobos/src/std/zip.d index 8b130ea..9e55d19 100644 --- a/libphobos/src/std/zip.d +++ b/libphobos/src/std/zip.d @@ -263,8 +263,8 @@ final class ArchiveMember { void print() { - printf("name = '%.*s'\n", name.length, name.ptr); - printf("\tcomment = '%.*s'\n", comment.length, comment.ptr); + printf("name = '%.*s'\n", cast(int) name.length, name.ptr); + printf("\tcomment = '%.*s'\n", cast(int) comment.length, comment.ptr); printf("\tmadeVersion = x%04x\n", _madeVersion); printf("\textractVersion = x%04x\n", extractVersion); printf("\tflags = x%04x\n", flags); @@ -348,7 +348,7 @@ final class ZipArchive printf("\tdiskStartDir = %u\n", diskStartDir); printf("\tnumEntries = %u\n", numEntries); printf("\ttotalEntries = %u\n", totalEntries); - printf("\tcomment = '%.*s'\n", comment.length, comment.ptr); + printf("\tcomment = '%.*s'\n", cast(int) comment.length, comment.ptr); } } diff --git a/libphobos/testsuite/Makefile.in b/libphobos/testsuite/Makefile.in index c38a468..8855480 100644 --- a/libphobos/testsuite/Makefile.in +++ b/libphobos/testsuite/Makefile.in @@ -215,6 +215,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +SECTION_FLAGS = @SECTION_FLAGS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -242,6 +243,8 @@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ +enable_shared = @enable_shared@ +enable_static = @enable_static@ exec_prefix = @exec_prefix@ gcc_version = @gcc_version@ gdc_include_dir = @gdc_include_dir@ @@ -271,6 +274,7 @@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ phobos_compiler_pic_flag = @phobos_compiler_pic_flag@ phobos_compiler_shared_flag = @phobos_compiler_shared_flag@ +phobos_lt_pic_flag = @phobos_lt_pic_flag@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ diff --git a/libphobos/testsuite/libphobos.druntime/druntime.exp b/libphobos/testsuite/libphobos.druntime/druntime.exp index 2f3a36f..daedfd7 100644 --- a/libphobos/testsuite/libphobos.druntime/druntime.exp +++ b/libphobos/testsuite/libphobos.druntime/druntime.exp @@ -15,7 +15,7 @@ # <http://www.gnu.org/licenses/>. # Immediately exit if we can't run target executables. -if { ![isnative] || ![is-effective-target static] } { +if { ![isnative] } { return } @@ -34,7 +34,8 @@ dg-init # Main loop. foreach test $tests { set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../libdruntime $test]" - dg-runtest $test "" "-fmain -fbuilding-libphobos-tests $version_flags" + dg-runtest $test "-static-libphobos" \ + "-fmain -fbuilding-libphobos-tests $version_flags" set libphobos_test_name "" } diff --git a/libphobos/testsuite/libphobos.druntime_shared/druntime_shared.exp b/libphobos/testsuite/libphobos.druntime_shared/druntime_shared.exp index 6ca62a3..51f9c2c 100644 --- a/libphobos/testsuite/libphobos.druntime_shared/druntime_shared.exp +++ b/libphobos/testsuite/libphobos.druntime_shared/druntime_shared.exp @@ -34,7 +34,7 @@ dg-init # Main loop. foreach test $tests { set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../libdruntime $test]" - dg-runtest $test "-fversion=Shared -shared-libphobos" \ + dg-runtest $test "-shared-libphobos" \ "-fmain -fbuilding-libphobos-tests -fno-moduleinfo $version_flags" set libphobos_test_name "" } diff --git a/libphobos/testsuite/libphobos.exceptions/chain.d b/libphobos/testsuite/libphobos.exceptions/chain.d index 462ba24..0305707 100644 --- a/libphobos/testsuite/libphobos.exceptions/chain.d +++ b/libphobos/testsuite/libphobos.exceptions/chain.d @@ -65,14 +65,14 @@ void main() string prefix = ""; for ({ size_t i; Throwable ex = original; } ex; ex = ex.next, ++i) { - printf("%.*s%.*s\n", prefix.length, prefix.ptr, ex.msg.length, ex.msg.ptr); + printf("%.*s%.*s\n", cast(int)prefix.length, prefix.ptr, cast(int)ex.msg.length, ex.msg.ptr); prefix = prefix~" "; } printf("Bypassed chain was:\n"); prefix = ""; for ({ size_t i; Throwable ex = original.bypassedException; } ex; ex = ex.next, ++i) { - printf("%.*s%.*s\n", prefix.length, prefix.ptr, ex.msg.length, ex.msg.ptr); + printf("%.*s%.*s\n", cast(int)prefix.length, prefix.ptr, cast(int)ex.msg.length, ex.msg.ptr); prefix = prefix~" "; } } diff --git a/libphobos/testsuite/libphobos.exceptions/line_trace.d b/libphobos/testsuite/libphobos.exceptions/line_trace.d index 7b75d3a..70762ff 100644 --- a/libphobos/testsuite/libphobos.exceptions/line_trace.d +++ b/libphobos/testsuite/libphobos.exceptions/line_trace.d @@ -9,7 +9,7 @@ void main() { import core.stdc.stdio; auto str = e.toString(); - printf("%.*s\n", str.length, str.ptr); + printf("%.*s\n", cast(int)str.length, str.ptr); } } diff --git a/libphobos/testsuite/libphobos.phobos/phobos.exp b/libphobos/testsuite/libphobos.phobos/phobos.exp index 0975ab1..937849e 100644 --- a/libphobos/testsuite/libphobos.phobos/phobos.exp +++ b/libphobos/testsuite/libphobos.phobos/phobos.exp @@ -15,7 +15,7 @@ # <http://www.gnu.org/licenses/>. # Immediately exit if we can't run target executables. -if { ![isnative] || ![is-effective-target static] } { +if { ![isnative] } { return } @@ -45,7 +45,8 @@ dg-init # Main loop. foreach test $tests { set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../src $test]" - dg-runtest $test "" "-fmain -fbuilding-libphobos-tests $version_flags" + dg-runtest $test "-static-libphobos" \ + "-fmain -fbuilding-libphobos-tests $version_flags" set libphobos_test_name "" } diff --git a/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp b/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp index da31304..8498522 100644 --- a/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp +++ b/libphobos/testsuite/libphobos.phobos_shared/phobos_shared.exp @@ -45,7 +45,7 @@ dg-init # Main loop. foreach test $tests { set libphobos_test_name "$subdir/[dg-trim-dirname $srcdir/../src $test]" - dg-runtest $test "-fversion=Shared -shared-libphobos" \ + dg-runtest $test "-shared-libphobos" \ "-fmain -fbuilding-libphobos-tests -fno-moduleinfo $version_flags" set libphobos_test_name "" } diff --git a/libphobos/testsuite/libphobos.thread/fiber_guard_page.d b/libphobos/testsuite/libphobos.thread/fiber_guard_page.d index 9f754e1..ca54a19 100644 --- a/libphobos/testsuite/libphobos.thread/fiber_guard_page.d +++ b/libphobos/testsuite/libphobos.thread/fiber_guard_page.d @@ -1,13 +1,15 @@ // { dg-options "-O0" } // { dg-shouldfail "segv or bus error" } import core.thread; +import core.sys.posix.signal; import core.sys.posix.sys.mman; // this should be true for most architectures // (taken from core.thread) -version = StackGrowsDown; +version (GNU_StackGrowsDown) + version = StackGrowsDown; -enum stackSize = 4096; +enum stackSize = MINSIGSTKSZ; // Simple method that causes a stack overflow void stackMethod() diff --git a/libphobos/testsuite/testsuite_flags.in b/libphobos/testsuite/testsuite_flags.in index 6a2d79f..bafd5ad4 100755 --- a/libphobos/testsuite/testsuite_flags.in +++ b/libphobos/testsuite/testsuite_flags.in @@ -28,7 +28,8 @@ case ${query} in ;; --gdcflags) GDCFLAGS_default="-fmessage-length=0 -fno-show-column" - GDCFLAGS_config="@WARN_DFLAGS@ @GDCFLAGS@ @CET_DFLAGS@ -fno-release -funittest" + GDCFLAGS_config="@WARN_DFLAGS@ @GDCFLAGS@ @CET_DFLAGS@ + @phobos_compiler_shared_flag@ -fno-release -funittest" echo ${GDCFLAGS_default} ${GDCFLAGS_config} ;; --gdcpaths) |