From 758234180a856302c7aa063a7fbb6cb06145cd56 Mon Sep 17 00:00:00 2001 From: mdejong Date: Sat, 25 Jan 2003 12:48:12 +0000 Subject: * win/configure: * win/configure.in: Define HAVE_ALLOCA_GCC_INLINE when we detect that no alloca function is found in malloc.h and we are compiling with GCC. Remove HAVE_NO_ALLOC_DECL define. * win/tclWin32Dll.c (TclpCheckStackSpace): Don't define alloca as a cdecl function. Doing this caused a tricky runtime bug because the _alloca function expects the size argument to be passed in a register and not on the stack. To fix this problem, we use inline ASM when compiling with gcc to invoke _alloca with the size argument loaded into a register. --- ChangeLog | 16 +++++++++++++ win/configure | 69 ++++++++++++++++++++++++++++++------------------------- win/configure.in | 17 ++++++++++---- win/tclWin32Dll.c | 16 ++++++++----- 4 files changed, 76 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b3fa79..37fbaef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2003-01-25 Mo DeJong + + * win/configure: + * win/configure.in: Define HAVE_ALLOCA_GCC_INLINE + when we detect that no alloca function is found + in malloc.h and we are compiling with GCC. + Remove HAVE_NO_ALLOC_DECL define. + * win/tclWin32Dll.c (TclpCheckStackSpace): + Don't define alloca as a cdecl function. + Doing this caused a tricky runtime bug because + the _alloca function expects the size argument + to be passed in a register and not on the stack. + To fix this problem, we use inline ASM when + compiling with gcc to invoke _alloca with the + size argument loaded into a register. + 2003-01-24 Jeff Hobbs * win/tclWinDde.c (Dde_Init): clarified use of tsdPtr. diff --git a/win/configure b/win/configure index aae48ca..a5d5bdc 100755 --- a/win/configure +++ b/win/configure @@ -1169,14 +1169,21 @@ fi # Check to see if malloc.h is missing the alloca function # declaration. This is known to be a problem with Mingw. +# If we compiled without the function declaration, it +# would work but we would get a warning message from gcc. +# If we add the function declaration ourselves, it +# would not compile correctly because the _alloca +# function expects the argument to be passed in a +# register and not on the stack. Instead, we just +# call it from inline asm code. echo $ac_n "checking for alloca declaration in malloc.h""... $ac_c" 1>&6 -echo "configure:1175: checking for alloca declaration in malloc.h" >&5 +echo "configure:1182: checking for alloca declaration in malloc.h" >&5 if eval "test \"`echo '$''{'tcl_cv_malloc_decl_alloca'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -1190,7 +1197,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:1194: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1201: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* tcl_cv_malloc_decl_alloca=yes else @@ -1204,26 +1211,26 @@ rm -f conftest* fi echo "$ac_t""$tcl_cv_malloc_decl_alloca" 1>&6 -if test "$tcl_cv_malloc_decl_alloca" = "no" ; then +if test "$tcl_cv_malloc_decl_alloca" = "no" && + test "${GCC}" = "yes" ; then cat >> confdefs.h <<\EOF -#define HAVE_NO_ALLOC_DECL 1 +#define HAVE_ALLOCA_GCC_INLINE 1 EOF fi - #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- echo $ac_n "checking for object suffix""... $ac_c" 1>&6 -echo "configure:1221: checking for object suffix" >&5 +echo "configure:1228: checking for object suffix" >&5 if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftest* echo 'int i = 1;' > conftest.$ac_ext -if { (eval echo configure:1227: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1234: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then for ac_file in conftest.*; do case $ac_file in *.c) ;; @@ -1241,19 +1248,19 @@ OBJEXT=$ac_cv_objext ac_objext=$ac_cv_objext echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 -echo "configure:1245: checking for mingw32 environment" >&5 +echo "configure:1252: checking for mingw32 environment" >&5 if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1264: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mingw32=yes else @@ -1272,7 +1279,7 @@ test "$ac_cv_mingw32" = yes && MINGW32=yes echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 -echo "configure:1276: checking for executable suffix" >&5 +echo "configure:1283: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1282,7 +1289,7 @@ else rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= - if { (eval echo configure:1286: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + if { (eval echo configure:1293: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.c | *.o | *.obj) ;; @@ -1309,7 +1316,7 @@ ac_exeext=$EXEEXT echo $ac_n "checking for building with threads""... $ac_c" 1>&6 -echo "configure:1313: checking for building with threads" >&5 +echo "configure:1320: checking for building with threads" >&5 # Check whether --enable-threads or --disable-threads was given. if test "${enable_threads+set}" = set; then enableval="$enable_threads" @@ -1346,7 +1353,7 @@ EOF echo $ac_n "checking how to build libraries""... $ac_c" 1>&6 -echo "configure:1350: checking how to build libraries" >&5 +echo "configure:1357: checking how to build libraries" >&5 # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" @@ -1387,7 +1394,7 @@ EOF # Step 0: Enable 64 bit support? echo $ac_n "checking if 64bit support is requested""... $ac_c" 1>&6 -echo "configure:1391: checking if 64bit support is requested" >&5 +echo "configure:1398: checking if 64bit support is requested" >&5 # Check whether --enable-64bit or --disable-64bit was given. if test "${enable_64bit+set}" = set; then enableval="$enable_64bit" @@ -1404,7 +1411,7 @@ fi # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1408: checking for $ac_word" >&5 +echo "configure:1415: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CYGPATH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1448,9 +1455,9 @@ fi echo "END" >> $conftest echo $ac_n "checking for Windows native path bug in windres""... $ac_c" 1>&6 -echo "configure:1452: checking for Windows native path bug in windres" >&5 +echo "configure:1459: checking for Windows native path bug in windres" >&5 cyg_conftest=`$CYGPATH $conftest` - if { ac_try='$RC -o conftest.res.o $cyg_conftest'; { (eval echo configure:1454: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } ; then + if { ac_try='$RC -o conftest.res.o $cyg_conftest'; { (eval echo configure:1461: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } ; then echo "$ac_t""no" 1>&6 else echo "$ac_t""yes" 1>&6 @@ -1469,7 +1476,7 @@ echo "configure:1452: checking for Windows native path bug in windres" >&5 # set various compiler flags depending on whether we are using gcc or cl echo $ac_n "checking compiler flags""... $ac_c" 1>&6 -echo "configure:1473: checking compiler flags" >&5 +echo "configure:1480: checking compiler flags" >&5 if test "${GCC}" = "yes" ; then if test "$do64bit" = "yes" ; then echo "configure: warning: "64bit mode not supported with GCC on Windows"" 1>&2 @@ -1685,7 +1692,7 @@ echo "configure:1473: checking compiler flags" >&5 echo $ac_n "checking for build with symbols""... $ac_c" 1>&6 -echo "configure:1689: checking for build with symbols" >&5 +echo "configure:1696: checking for build with symbols" >&5 # Check whether --enable-symbols or --disable-symbols was given. if test "${enable_symbols+set}" = set; then enableval="$enable_symbols" @@ -1745,7 +1752,7 @@ TCL_DBGX=${DBGX} #-------------------------------------------------------------------- echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1749: checking how to run the C preprocessor" >&5 +echo "configure:1756: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1760,13 +1767,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1770: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1777: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1777,13 +1784,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1787: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1794: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1794,13 +1801,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1804: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1811: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1826,17 +1833,17 @@ echo "$ac_t""$CPP" 1>&6 ac_safe=`echo "errno.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for errno.h""... $ac_c" 1>&6 -echo "configure:1830: checking for errno.h" >&5 +echo "configure:1837: checking for errno.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1840: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1847: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* diff --git a/win/configure.in b/win/configure.in index 0b99959..16591e6 100644 --- a/win/configure.in +++ b/win/configure.in @@ -3,7 +3,7 @@ # generate the file "configure", which is run during Tcl installation # to configure the system for the local environment. # -# RCS: @(#) $Id: configure.in,v 1.63 2003/01/24 08:04:28 mdejong Exp $ +# RCS: @(#) $Id: configure.in,v 1.64 2003/01/25 12:48:12 mdejong Exp $ AC_INIT(../generic/tcl.h) AC_PREREQ(2.13) @@ -196,6 +196,13 @@ fi # Check to see if malloc.h is missing the alloca function # declaration. This is known to be a problem with Mingw. +# If we compiled without the function declaration, it +# would work but we would get a warning message from gcc. +# If we add the function declaration ourselves, it +# would not compile correctly because the _alloca +# function expects the argument to be passed in a +# register and not on the stack. Instead, we just +# call it from inline asm code. AC_CACHE_CHECK(for alloca declaration in malloc.h, tcl_cv_malloc_decl_alloca, @@ -211,12 +218,12 @@ AC_TRY_COMPILE([ tcl_cv_malloc_decl_alloca=yes, tcl_cv_malloc_decl_alloca=no) ) -if test "$tcl_cv_malloc_decl_alloca" = "no" ; then - AC_DEFINE(HAVE_NO_ALLOC_DECL, 1, - [Defined when alloca decl is missing from malloc.h]) +if test "$tcl_cv_malloc_decl_alloca" = "no" && + test "${GCC}" = "yes" ; then + AC_DEFINE(HAVE_ALLOCA_GCC_INLINE, 1, + [Defined when gcc should use inline ASM to call alloca.]) fi - #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c index 1c029f8..13f2a4b 100644 --- a/win/tclWin32Dll.c +++ b/win/tclWin32Dll.c @@ -9,16 +9,11 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWin32Dll.c,v 1.21 2003/01/24 08:04:29 mdejong Exp $ + * RCS: @(#) $Id: tclWin32Dll.c,v 1.22 2003/01/25 12:48:12 mdejong Exp $ */ #include "tclWinInt.h" -#if defined(HAVE_NO_ALLOC_DECL) -void* __cdecl _alloca(size_t size); -#define alloca _alloca -#endif /* HAVE_NO_ALLOC_DECL */ - /* * The following data structures are used when loading the thunking * library for execing child processes under Win32s. @@ -395,7 +390,16 @@ TclpCheckStackSpace() #else __try { #endif /* HAVE_NO_SEH */ +#ifdef HAVE_ALLOCA_GCC_INLINE + __asm__ __volatile__ ( + "movl %0, %%eax" "\n\t" + "call __alloca" "\n\t" + : + : "i"(TCL_WIN_STACK_THRESHOLD) + : "%eax"); +#else alloca(TCL_WIN_STACK_THRESHOLD); +#endif /* HAVE_ALLOCA_GCC_INLINE */ retval = 1; #ifdef HAVE_NO_SEH __asm__ __volatile__ ( -- cgit v0.12