repair MinGW32 builds

Also, change floating-point handling to be like the MSVC build by
default, where the process is left in double-precision mode and
the mode is changed for exfl operations.

Includes repairs for integer-size mismatches in uses of Windows
threads.
This commit is contained in:
Matthew Flatt 2015-08-25 16:43:56 -06:00
parent fadcb78ffa
commit ba7e2f11ec
17 changed files with 180 additions and 49 deletions

View File

@ -36,13 +36,6 @@ result is a Unix-style build, not a Windows-style build (e.g.,
Racket's `system-type' procedure returns 'unix, not 'windows, and
`racket/gui' uses Gtk instead of Win32).
Beware that MinGW/Cygwin builds different from the MSVC build when
SSE-based floating-point math is enabled in the C compiler. In that
case, Racket includes sets the floating-point mode to extended
precision to support extflonums, and changing precision may affect
other libraries. To avoid the floating-point mode change, disable
extflonum support with `--disable-extflonum'.
========================================================================
Compiling for Mac OS X
========================================================================

View File

@ -3877,7 +3877,7 @@ typedef struct Queued_Callback {
typedef struct FFI_Sync_Queue {
Queued_Callback *callbacks; /* malloc()ed list */
mzrt_mutex *lock;
mzrt_thread_id orig_thread;
mzrt_os_thread_id orig_thread;
void *sig_hand;
} FFI_Sync_Queue;
@ -3987,7 +3987,7 @@ static void ffi_queue_callback(ffi_cif* cif, void* resultp, void** args, void *u
queue = (FFI_Sync_Queue *)(data)[1];
userdata = (data)[0];
if (queue->orig_thread != mz_proc_thread_self()) {
if (queue->orig_thread != mz_proc_os_thread_self()) {
if (data[2]) {
/* constant result */
memcpy(resultp, data[2], (intptr_t)data[3]);
@ -4141,11 +4141,11 @@ static Scheme_Object *foreign_ffi_callback(int argc, Scheme_Object *argv[])
if (((argc > 5) && SCHEME_TRUEP(argv[5]))) {
# ifdef MZ_USE_MZRT
if (!ffi_sync_queue) {
mzrt_thread_id tid;
mzrt_os_thread_id tid;
void *sig_hand;
ffi_sync_queue = (FFI_Sync_Queue *)malloc(sizeof(FFI_Sync_Queue));
tid = mz_proc_thread_self();
tid = mz_proc_os_thread_self();
ffi_sync_queue->orig_thread = tid;
mzrt_mutex_create(&ffi_sync_queue->lock);
sig_hand = scheme_get_signal_handle();

View File

@ -3039,7 +3039,7 @@ typedef struct Queued_Callback {
typedef struct FFI_Sync_Queue {
Queued_Callback *callbacks; /* malloc()ed list */
mzrt_mutex *lock;
mzrt_thread_id orig_thread;
mzrt_os_thread_id orig_thread;
void *sig_hand;
} FFI_Sync_Queue;
@ -3149,7 +3149,7 @@ static void ffi_queue_callback(ffi_cif* cif, void* resultp, void** args, void *u
queue = (FFI_Sync_Queue *)(data)[1];
userdata = (data)[0];
if (queue->orig_thread != mz_proc_thread_self()) {
if (queue->orig_thread != mz_proc_os_thread_self()) {
if (data[2]) {
/* constant result */
memcpy(resultp, data[2], (intptr_t)data[3]);
@ -3301,11 +3301,11 @@ static void free_cl_cif_queue_args(void *ignored, void *p)
if (((argc > 5) && SCHEME_TRUEP(argv[5]))) {
@@IFDEF{MZ_USE_MZRT}{
if (!ffi_sync_queue) {
mzrt_thread_id tid;
mzrt_os_thread_id tid;
void *sig_hand;
ffi_sync_queue = (FFI_Sync_Queue *)malloc(sizeof(FFI_Sync_Queue));
tid = mz_proc_thread_self();
tid = mz_proc_os_thread_self();
ffi_sync_queue->orig_thread = tid;
mzrt_mutex_create(&ffi_sync_queue->lock);
sig_hand = scheme_get_signal_handle();

View File

@ -401,11 +401,16 @@ mingw-install:
cd ..; rm -f "$(DESTDIR)@MZINSTALLBINDIR@/racket@MMM_INSTALLED@"
cd ..; cp racket/starter@EXE_SUFFIX@ "$(DESTDIR)$(libpltdir)/MzStart@EXE_SUFFIX@"
cd ..; cp racket/mrstarter@EXE_SUFFIX@ "$(DESTDIR)$(libpltdir)/MrStart@EXE_SUFFIX@"
cd ..; $(STRIP_DEBUG) "$(DESTDIR)$(libpltdir)/MzStart@EXE_SUFFIX@"
cd ..; $(STRIP_DEBUG) "$(DESTDIR)$(libpltdir)/MrStart@EXE_SUFFIX@"
mingw-install-cgc:
cd ..; $(ICP) racket/lib/libmzgcxxxxxxx.dll "$(DESTDIR)$(libdir)/libmzgcxxxxxxx.dll"
cd ..; $(ICP) racket/lib/libracketxxxxxxx.dll "$(DESTDIR)$(libdir)/libracketxxxxxxx.dll"
cd ..; $(ICP) racket/racket@CGC@ "$(DESTDIR)@MZINSTALLBINDIR@/Racket@CGC_INSTALLED@@EXE_SUFFIX@"
cd ..; $(STRIP_DEBUG) "$(DESTDIR)$(libdir)/libmzgcxxxxxxx.dll"
cd ..; $(STRIP_DEBUG) "$(DESTDIR)$(libdir)/libracketxxxxxxx.dll"
cd ..; $(STRIP_DEBUG) "$(DESTDIR)@MZINSTALLBINDIR@/Racket@CGC_INSTALLED@@EXE_SUFFIX@"
@RUN_RACKET_CGC@ -cu "$(srcdir)/collects-path.rkt" @DIRCVTPRE@"$(DESTDIR)@MZINSTALLBINDIR@/Racket@CGC_INSTALLED@@EXE_SUFFIX@"@DIRCVTPOST@ $(DESTDIR)@COLLECTS_PATH@ $(DESTDIR)@CONFIG_PATH@
mingw-install-cgc-final:
@ -414,6 +419,8 @@ mingw-install-cgc-final:
mingw-install-3m:
cd ..; $(ICP) racket/racket@MMM@ "$(DESTDIR)@MZINSTALLBINDIR@/Racket@MMM_INSTALLED@@EXE_SUFFIX@"
cd ..; $(ICP) racket/lib/libracket3mxxxxxxx.dll "$(DESTDIR)$(libdir)/libracket3mxxxxxxx.dll"
cd ..; $(STRIP_DEBUG) "$(DESTDIR)@MZINSTALLBINDIR@/Racket@MMM_INSTALLED@@EXE_SUFFIX@"
cd ..; $(STRIP_DEBUG) "$(DESTDIR)$(libdir)/libracket3mxxxxxxx.dll"
@RUN_RACKET_MMM@ -cu "$(srcdir)/collects-path.rkt" @DIRCVTPRE@"$(DESTDIR)@MZINSTALLBINDIR@/Racket@MMM_INSTALLED@@EXE_SUFFIX@"@DIRCVTPOST@ $(DESTDIR)@COLLECTS_PATH@ $(DESTDIR)@CONFIG_PATH@
mingw-install-3m-final:

View File

@ -159,7 +159,7 @@ wchar_t *get_self_executable_path()
static DWORD find_by_id(HANDLE fd, DWORD rsrcs, DWORD pos, int id)
{
DWORD got, val;
WORD name_count, id_count, i;
WORD name_count, id_count;
SetFilePointer(fd, pos + 12, 0, FILE_BEGIN);
ReadFile(fd, &name_count, 2, &got, NULL);

View File

@ -181,7 +181,11 @@ xsrc:
xobjects: $(OBJS) main.@LTO@
XFORMDEP_NOPRE = $(srcdir)/xform.rkt $(srcdir)/xform-mod.rkt
# These headers have only preprocessor definitions, so they're not
# picked up in ".sdep":
QUIET_DEPS = $(srcdir)/../src/schvers.h $(srcdir)/../sconfig.h ../mzconfig.h
XFORMDEP_NOPRE = $(srcdir)/xform.rkt $(srcdir)/xform-mod.rkt $(QUIET_DEPS)
XFORMDEP = $(XFORMDEP_NOPRE) $(XSRCDIR)/precomp.h
MZRTDEP = $(srcdir)/../src/schpriv.h $(srcdir)/../include/scheme.h \
@ -193,7 +197,7 @@ MZRTDEP = $(srcdir)/../src/schpriv.h $(srcdir)/../include/scheme.h \
check-sdep :
@RUN_RACKET_CGC@ $(SELF_RACKET_FLAGS) -cqu $(srcdir)/check-sdep.rkt
$(XSRCDIR)/precomp.h : $(XFORMDEP_NOPRE) $(srcdir)/../src/schvers.h
$(XSRCDIR)/precomp.h : $(XFORMDEP_NOPRE)
env XFORM_PRECOMP=yes $(XFORM_NOPRECOMP) $(XSRCDIR)/precomp.h $(srcdir)/precomp.c
$(XSRCDIR)/salloc.c: $(XFORMDEP)

View File

@ -84,7 +84,7 @@
#endif
#ifdef MZ_LONG_DOUBLE
# if defined(_MSC_VER)
# ifdef MZ_LONG_DOUBLE_API_IS_EXTERNAL
# define BYTES_RESERVED_FOR_LONG_DOUBLE 16
typedef struct {
char bytes[BYTES_RESERVED_FOR_LONG_DOUBLE];

View File

@ -660,7 +660,7 @@
# define DO_STACK_CHECK
# define WINDOWS_FIND_STACK_BOUNDS
# if !defined(_WIN64) || (_MSC_VER >= 1600)
# if !defined(_WIN64) || (_MSC_VER >= 1600) || defined(__MINGW32__)
# define USE_MZ_SETJMP
# endif
@ -729,14 +729,18 @@
# define IGNORE_BY_BORLAND_CONTROL_87
#endif
#if defined(_MSC_VER)
#if defined(__MINGW32__) && defined(USE_DIRECT_LONG_DOUBLE)
/* Beware: different from the MSVC build when SSE-based floating-point
math is enabled in the C compiler. Sets the floating-point mode to
extended precision to support extflonums, and changing precision
may affect other libraries. */
# define MZ_TRY_EXTFLONUMS
# define ASM_DBLPREC_CONTROL_87
#else
# define MZ_LONG_DOUBLE
# define IGNORE_BY_MS_CONTROL_87
# define MZ_NEED_SET_EXTFL_MODE
#endif
#if defined(__MINGW32__)
# define MZ_TRY_EXTFLONUMS
# define ASM_DBLPREC_CONTROL_87
# define MZ_LONG_DOUBLE_API_IS_EXTERNAL
#endif
# define REGISTER_POOR_MACHINE

View File

@ -740,7 +740,7 @@ void set_long_double(long_double a, long_double b) { _imp_set_long_double(a, b);
long_double long_double_from_int(int a) { return _imp_long_double_from_int(a); }
long_double long_double_from_float(float a) { return _imp_long_double_from_float(a); }
long_double long_double_from_double(double a) { return _imp_long_double_from_double(a); }
long_double long_double_from_intptr(uintptr_t a) { return _imp_long_double_from_intptr(a); }
long_double long_double_from_intptr(intptr_t a) { return _imp_long_double_from_intptr(a); }
long_double long_double_from_uintptr(uintptr_t a) { return _imp_long_double_from_uintptr(a); }
double double_from_long_double(long_double a) { return _imp_double_from_long_double(a); }

View File

@ -1,12 +1,10 @@
#ifndef MZ_LONGDOUBLE_H
#define MZ_LONGDOUBLE_H
#if defined(_MSC_VER)
# define MZ_LONG_DOUBLE_API_IS_EXTERNAL
#endif
#if defined(__MINGW32__) && defined(MZ_LONG_DOUBLE)
# define LONG_DOUBLE_STRING_OP_API_IS_EXTERNAL
#ifndef MZ_LONG_DOUBLE_API_IS_EXTERNAL
# if defined(__MINGW32__) && defined(MZ_LONG_DOUBLE)
# define LONG_DOUBLE_STRING_OP_API_IS_EXTERNAL
# endif
#endif
#if defined(MZ_LONG_DOUBLE_API_IS_EXTERNAL) \

View File

@ -153,6 +153,9 @@ typedef struct mzrt_thread_stub_data {
mz_proc_thread_start start_proc;
void *data;
mz_proc_thread *thread;
#ifdef WIN32
void *res;
#endif
} mzrt_thread_stub_data;
void *mzrt_thread_stub(void *data){
@ -169,6 +172,10 @@ void *mzrt_thread_stub(void *data){
res = start_proc(start_proc_data);
#ifdef WIN32
proc_thread_self->res = res;
#endif
if (!--proc_thread_self->refcount)
free(proc_thread_self);
@ -178,15 +185,18 @@ void *mzrt_thread_stub(void *data){
}
#ifdef WIN32
DWORD WINAPI mzrt_win_thread_stub(void *data)
unsigned int WINAPI mzrt_win_thread_stub(void *data)
{
return (DWORD)mzrt_thread_stub(data);
(void)mzrt_thread_stub(data);
return 0;
}
#endif
mzrt_thread_id mz_proc_thread_self() {
mzrt_os_thread_id mz_proc_os_thread_self() {
#ifdef WIN32
/* For Windows, this result is not compatible with mz_proc_thread_id(),
so don't mix them up! */
return GetCurrentThreadId();
#else
return pthread_self();
@ -201,7 +211,14 @@ mzrt_thread_id mz_proc_thread_id(mz_proc_thread* thread) {
mz_proc_thread* mzrt_proc_first_thread_init() {
/* initialize mz_proc_thread struct for first thread that wasn't created with mz_proc_thread_create */
mz_proc_thread *thread = (mz_proc_thread*)malloc(sizeof(mz_proc_thread));
#ifdef WIN32
/* This pseudo-handle is not valid as a reference from any other thread,
but it will be distinct from all other IDs: */
thread->threadid = GetCurrentThread();
#else
thread->threadid = mz_proc_thread_self();
#endif
proc_thread_self = thread;
thread->refcount = 1;
return thread;
@ -234,7 +251,7 @@ mz_proc_thread* mz_proc_thread_create_w_stacksize(mz_proc_thread_start start_pro
stub_data->thread = thread;
# ifdef WIN32
thread->threadid = (HANDLE)_beginthreadex(NULL, stacksize, mzrt_win_thread_stub, stub_data, 0, NULL);
ok = (thread->threadid != -1L);
ok = (thread->threadid != (HANDLE)-1L);
# else
# ifdef NEED_GC_THREAD_OPS
ok = !GC_pthread_create(&thread->threadid, attr, mzrt_thread_stub, stub_data);
@ -277,10 +294,8 @@ mz_proc_thread* mz_proc_thread_create(mz_proc_thread_start start_proc, void* dat
void * mz_proc_thread_wait(mz_proc_thread *thread) {
void *rc;
#ifdef WIN32
DWORD rcw;
WaitForSingleObject(thread->threadid,INFINITE);
GetExitCodeThread(thread->threadid, &rcw);
rc = (void *)rcw;
rc = proc_thread_self->res;
CloseHandle(thread->threadid);
#else
# ifdef NEED_GC_THREAD_OPS
@ -613,7 +628,7 @@ int mzrt_sema_destroy(mzrt_sema *s)
#ifdef WIN32
typedef struct mzrt_rwlock {
struct mzrt_rwlock {
HANDLE readEvent;
HANDLE writeMutex;
LONG readers;

View File

@ -21,16 +21,21 @@ void mzrt_set_user_break_handler(void (*user_break_handler)(int));
#if (defined(__WIN32__) || defined(WIN32) || defined(_WIN32))
# include <winsock2.h>
typedef DWORD mzrt_thread_id;
typedef HANDLE mzrt_thread_id;
typedef DWORD mzrt_os_thread_id;
#else
#include <pthread.h>
typedef pthread_t mzrt_thread_id;
typedef pthread_t mzrt_os_thread_id;
#endif
typedef struct mz_proc_thread {
mzrt_thread_id threadid;
int refcount;
#if (defined(__WIN32__) || defined(WIN32) || defined(_WIN32))
void *res;
#endif
} mz_proc_thread;
@ -45,7 +50,7 @@ void mz_proc_thread_exit(void *rc);
void mzrt_sleep(int seconds);
mzrt_thread_id mz_proc_thread_self();
mzrt_os_thread_id mz_proc_os_thread_self();
mzrt_thread_id mz_proc_thread_id(mz_proc_thread* thread);
/****************** THREAD RWLOCK ******************************************/

View File

@ -1,8 +1,65 @@
#ifndef _WIN64
#ifdef _WIN64
.globl _scheme_mz_setjmp
_scheme_mz_setjmp:
push %EBP
mov %RBX, (%RCX)
mov %RBP, 0x08(%RCX)
mov %RDI, 0x10(%RCX)
mov %RSI, 0x18(%RCX)
mov %RSP, 0x20(%RCX)
mov %R12, 0x28(%RCX)
mov %R13, 0x30(%RCX)
mov %R14, 0x38(%RCX)
mov %R15, 0x40(%RCX)
stmxcsr 0x48(%RCX)
movdqu %XMM6, 0x50(%RCX)
movdqu %XMM7, 0x60(%RCX)
movdqu %XMM8, 0x70(%RCX)
movdqu %XMM9, 0x80(%RCX)
movdqu %XMM10, 0x90(%RCX)
movdqu %XMM11, 0x0A0(%RCX)
movdqu %XMM12, 0x0B0(%RCX)
movdqu %XMM13, 0x0C0(%RCX)
movdqu %XMM14, 0x0D0(%RCX)
movdqu %XMM15, 0x0E0(%RCX)
mov (%RSP), %RAX
mov %RAX, 0x0F0(%RCX)
mov $0, %RAX
ret
.globl _scheme_mz_longjmp
_scheme_mz_longjmp:
mov (%RCX), %RBX
mov 0x08(%RCX), %RBP
mov 0x10(%RCX), %RDI
mov 0x18(%RCX), %RSI
mov 0x20(%RCX), %RSP
mov 0x28(%RCX), %R12
mov 0x30(%RCX), %R13
mov 0x38(%RCX), %R14
mov 0x40(%RCX), %R15
ldmxcsr 0x48(%RCX)
movdqu 0x50(%RCX), %XMM6
movdqu 0x60(%RCX), %XMM7
movdqu 0x70(%RCX), %XMM8
movdqu 0x80(%RCX), %XMM9
movdqu 0x90(%RCX), %XMM10
movdqu 0x0A0(%RCX), %XMM11
movdqu 0x0B0(%RCX), %XMM12
movdqu 0x0C0(%RCX), %XMM13
movdqu 0x0D0(%RCX), %XMM14
movdqu 0x0E0(%RCX), %XMM15
mov 0x0F0(%RCX), %RAX
mov %RAX, (%RSP)
mov %RDX, %RAX
ret
#else
.globl _scheme_mz_setjmp
_scheme_mz_setjmp:
push %EBP
mov %ESP, %EBP
mov 4(%EBP), %ECX # return address
mov 8(%EBP), %EAX # jmp_buf ptr
@ -34,10 +91,10 @@ _scheme_mz_longjmp:
mov %ECX, 4(%EBP)
pop %EBP
ret
#endif
.section .drectve,"r"
.ascii " -export:scheme_mz_setjmp"
.section .drectve,"r"
.ascii " -export:scheme_mz_longjmp"
#endif

View File

@ -597,6 +597,14 @@ static intptr_t getaddrinfo_in_thread(void *_data)
return 1;
}
#ifdef USE_WINSOCK_TCP
static unsigned int WINAPI win_getaddrinfo_in_thread(void *_data)
XFORM_SKIP_PROC
{
return (unsigned int)getaddrinfo_in_thread(_data);
}
#endif
static void release_ghbn_lock(GHBN_Rec *rec)
{
ghbn_thread_data->ghbn_lock = 0;
@ -701,13 +709,13 @@ static int MZ_GETADDRINFO(const char *name, const char *svc, struct mz_addrinfo
# ifdef USE_WINSOCK_TCP
{
HANDLE ready_sema;
DWORD id;
unsigned int id;
intptr_t th;
ready_sema = CreateSemaphore(NULL, 0, 1, NULL);
ghbn_thread_data->ready_sema = ready_sema;
th = _beginthreadex(NULL, 5000,
(MZ_LPTHREAD_START_ROUTINE)getaddrinfo_in_thread,
win_getaddrinfo_in_thread,
ghbn_thread_data, 0, &id);
WaitForSingleObject(ghbn_thread_data->ready_sema, INFINITE);
CloseHandle(ghbn_thread_data->ready_sema);

View File

@ -739,3 +739,25 @@ Scheme_Setjmp_Proc scheme_get_mz_setjmp(void)
return NULL;
}
#endif
#if defined(USE_MZ_SETJMP_INDIRECT) && defined(__MINGW32__)
extern int _scheme_mz_setjmp(mz_pre_jmp_buf b);
extern void _scheme_mz_longjmp(mz_pre_jmp_buf b, int v);
Scheme_Setjmp_Proc scheme_get_mz_setjmp(void)
{
return _scheme_mz_setjmp;
}
void scheme_mz_longjmp(mz_pre_jmp_buf b, int v)
{
_scheme_mz_longjmp(b, v);
}
int scheme_mz_setjmp(mz_pre_jmp_buf b)
{
scheme_log_abort("internal error: setjmp wasn't indirect");
abort();
return 0;
}
#endif

View File

@ -8,6 +8,15 @@
APPLICATION ICON DISCARDABLE "gracket.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Manifest (for MinGW)
//
#ifdef __MINGW32__
1 RT_MANIFEST "gracket.manifest"
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Version

View File

@ -8,6 +8,15 @@
APPLICATION ICON DISCARDABLE "racket.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Manifest (for MinGW)
//
#ifdef __MINGW32__
1 RT_MANIFEST "racket.manifest"
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Version