summaryrefslogtreecommitdiff
path: root/win32/win32.h
diff options
context:
space:
mode:
authorDaniel Dragan <bulk88@hotmail.com>2018-04-06 18:41:22 -0400
committerSteve Hay <steve.m.hay@googlemail.com>2018-04-12 17:58:27 +0100
commit1b30b4a8259a74c5ffaee362bc1d881c40fc5279 (patch)
tree3bd916526289b3621fb8cae441fbf8fbd8967bd8 /win32/win32.h
parent00c1316e738f63fb8f488ffc1fc410ef289cd50a (diff)
downloadperl-1b30b4a8259a74c5ffaee362bc1d881c40fc5279.tar.gz
fix win32 with Ming.org GCC 3.4.5 build
dlltool 2.20.51.20100123 from Strawberry 5.12 and dlltool 2.17.50 20060824 from Strawberry 5.8.9 were making a libperl527.a that caused perl.exe and all XS DLLs to import "perl527.exp.dll" while the disk file is called perl527.dll. This bug was eventually fixed, since in my testing dlltool 2.25 no date code, Copyright 2014 from Strawberry 5.22.1 doesn't have this problem. I suspect the bug was fixed in binutils commit 04276a0cf5 "2010-12-01 Kai Tietz <kai.tietz@onevision.com>" https://sourceware.org/bugzilla/show_bug.cgi?id=11065 in version "AM_INIT_AUTOMAKE(bfd, 2.21.51)" or 1 ver bump higher. Just always pass an explicit DLL name to dlltool instead of any kind of dlltool version checking at build time and then optional arg. The breakage for Mingw.org 3.4.5 was introduced in commit bf543eaf90d "add parallelness to win32/GNUmakefile" where I added parallelness by making the import lib .a file from just perldll.def, rather than the import lib being a build product coming out of g++ linking perl527.dll. The old serial build recipie passed --dllname to dlltool, my newer code didn't. Passing $(PERLDLL) to dlltool's -D causes this harmless but scary warning "dlltool: Path components stripped from dllname, '..\perl527.dll'." So create PERLDLLBASE to silence the warning. win32.h: In old GCCs, https://sourceforge.net/p/mingw/mailman/message/22184185/ a function marked declspec(dllimport) is not a constant. VC from day 1, and newer GCCs use the address of a 1 instruction jump stub function if a constant function pointer is needed to a function from a DLL that wont be known till runtime. This can be worked around in older GCCs by deoptimizing them to always use the jump stub for all references, and not the newer GCC and VC way where x86 call instructions directly read the import table in the caller, while constant functions ptrs in data or vars always refer to the jump stubs. Since these are old GCCs, performance isn't the highest priority and building at all is a more important goal. I suspect gcc 3.4.5 has been broken since 5.13.6 when the declspec(dllimport) code was added.
Diffstat (limited to 'win32/win32.h')
-rw-r--r--win32/win32.h43
1 files changed, 31 insertions, 12 deletions
diff --git a/win32/win32.h b/win32/win32.h
index cdfadfe4c5..29621c0cd3 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -103,23 +103,42 @@
* The XS code in the re extension is special, in that it redefines
* core APIs locally, so don't mark them as "dllimport" because GCC
* cannot handle this situation.
+ *
+ * Certain old GCCs will not allow the function pointer of dllimport marked
+ * function to be "const". This was fixed later on. Since this is a
+ * deoptimization, target "gcc version 3.4.5 (mingw-vista special r3)" only,
+ * The GCC bug was fixed in GCC patch "varasm.c (initializer_constant_valid_p):
+ * Don't deny DECL_DLLIMPORT_P on functions", which probably was first released
+ * in GCC 4.3.0, this #if can be expanded upto but not including 4.3.0 if more
+ * deployed GCC are found that wont build with the follow error, initializer
+ * element is a PerlIO func exported from perl5xx.dll.
+ *
+ * encoding.xs:610: error: initializer element is not constant
+ * encoding.xs:610: error: (near initialization for `PerlIO_encode.Open')
*/
-#if !defined(PERLDLL) && !defined(PERL_EXT_RE_BUILD)
-# ifdef __cplusplus
-# define PERL_CALLCONV extern "C" __declspec(dllimport)
-# ifdef _MSC_VER
-# define PERL_CALLCONV_NO_RET extern "C" __declspec(dllimport) __declspec(noreturn)
+
+#if (defined(__GNUC__) && defined(__MINGW32__) && \
+ !defined(__MINGW64_VERSION_MAJOR) && !defined(__clang__) && \
+ ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ <= 5))))
+/* use default fallbacks from perl.h for this particular GCC */
+#else
+# if !defined(PERLDLL) && !defined(PERL_EXT_RE_BUILD)
+# ifdef __cplusplus
+# define PERL_CALLCONV extern "C" __declspec(dllimport)
+# ifdef _MSC_VER
+# define PERL_CALLCONV_NO_RET extern "C" __declspec(dllimport) __declspec(noreturn)
+# endif
+# else
+# define PERL_CALLCONV __declspec(dllimport)
+# ifdef _MSC_VER
+# define PERL_CALLCONV_NO_RET __declspec(dllimport) __declspec(noreturn)
+# endif
# endif
-# else
-# define PERL_CALLCONV __declspec(dllimport)
+# else /* MSVC noreturn support inside the interp */
# ifdef _MSC_VER
-# define PERL_CALLCONV_NO_RET __declspec(dllimport) __declspec(noreturn)
+# define PERL_CALLCONV_NO_RET __declspec(noreturn)
# endif
# endif
-#else /* MSVC noreturn support inside the interp */
-# ifdef _MSC_VER
-# define PERL_CALLCONV_NO_RET __declspec(noreturn)
-# endif
#endif
#ifdef _MSC_VER