Make idlib build with MinGW

but it probably is buggy and still has a lot of warnings.

The rest still has errors, i.e. you can't build a doom executable with
MinGW yet
This commit is contained in:
Daniel Gibson 2012-12-01 05:37:17 +01:00
parent 174a69d1cc
commit 259f164d28
14 changed files with 206 additions and 25 deletions

View file

@ -18,6 +18,10 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
add_definitions(-Wall)
add_definitions(-mmmx -msse -msse2)
if(WIN32)
# require msvcr70.dll or newer for _aligned_malloc etc
# I think it is from Visual C++ .NET 2002, so it should be available on any modern system.
add_definitions(-D__MSVCRT_VERSION__=0x0700)
find_package(DirectX REQUIRED)
include_directories(libs/mingw-hacks)
include_directories(${DirectX_INCLUDE_DIR})

View file

@ -34,7 +34,7 @@ If you have questions concerning this license or the applicable additional terms
// memory allocation all in one place
//
//===============================================================
#include <malloc.h>
#undef new
/*
@ -49,7 +49,16 @@ void* Mem_Alloc16( const int size, const memTag_t tag )
return NULL;
}
const int paddedSize = ( size + 15 ) & ~15;
#ifdef _WIN32
// this should work with MSVC and mingw, as long as __MSVCRT_VERSION__ >= 0x0700
return _aligned_malloc( paddedSize, 16 );
#else // not _WIN32
// DG: the POSIX solution for linux etc
void* ret;
posix_memalign( &ret, 16, paddedSize );
return ret;
// DG end
#endif // _WIN32
}
/*
@ -63,7 +72,14 @@ void Mem_Free16( void* ptr )
{
return;
}
#ifdef _WIN32
_aligned_free( ptr );
#else // not _WIN32
// DG: Linux/POSIX compatibility
// can use normal free() for aligned memory
free( ptr );
// DG end
#endif // _WIN32
}
/*

View file

@ -45,11 +45,11 @@ If you have questions concerning this license or the applicable additional terms
#include <string.h>
#include <basetsd.h> // for UINT_PTR
#ifdef _MSC_VER
#include <intrin.h>
#pragma warning( disable : 4100 ) // unreferenced formal parameter
#pragma warning( disable : 4127 ) // conditional expression is constant
#endif

View file

@ -28,6 +28,10 @@ If you have questions concerning this license or the applicable additional terms
#include "ParallelJobList_JobHeaders.h"
#ifdef _WIN32
#include <windows.h> // for DebugBreak
#endif
/*
================================================================================================
@ -43,7 +47,19 @@ bool SpursEmulationAssertFailed( const char* filename, int line, const char* exp
static bool halt = true;
if( halt )
{
#ifdef _WIN32
#ifdef _MSC_VER
__debugbreak();
#else
// DG: mingw support
DebugBreak();
#endif
#else // not _WIN32
// DG: POSIX support
raise(SIGTRAP);
// DG: end
#endif // _WIN32
}
return true;
}

View file

@ -398,7 +398,7 @@ public:
static const int INVALID_POSITION = -1;
};
char* va( VERIFY_FORMAT_STRING const char* fmt, ... );
char* va( VERIFY_FORMAT_STRING const char* fmt, ... ) ATTRIBUTE_PRINTF(1, 2);
/*
================================================================================================

View file

@ -263,7 +263,8 @@ IsValid
========================
*/
template<>
ID_INLINE_EXTERN bool IsValid( const float& f ) // these parameter must be a reference for the function to be considered a specialization
ID_INLINE
bool IsValid( const float& f ) // these parameter must be a reference for the function to be considered a specialization
{
return !( IEEE_FLT_IS_NAN( f ) || IEEE_FLT_IS_INF( f ) || IEEE_FLT_IS_IND( f ) || IEEE_FLT_IS_DENORMAL( f ) );
}
@ -274,7 +275,8 @@ IsNAN
========================
*/
template<>
ID_INLINE_EXTERN bool IsNAN( const float& f ) // these parameter must be a reference for the function to be considered a specialization
ID_INLINE
bool IsNAN( const float& f ) // these parameter must be a reference for the function to be considered a specialization
{
if( IEEE_FLT_IS_NAN( f ) || IEEE_FLT_IS_INF( f ) || IEEE_FLT_IS_IND( f ) )
{
@ -291,7 +293,8 @@ Returns true if any scalar is greater than the range or less than the negative r
========================
*/
template<class type>
ID_INLINE_EXTERN bool IsInRange( const type& v, const float range )
ID_INLINE
bool IsInRange( const type& v, const float range )
{
for( int i = 0; i < v.GetDimension(); i++ )
{
@ -683,6 +686,7 @@ idMath::SinCos
*/
ID_INLINE void idMath::SinCos( float a, float& s, float& c )
{
#if defined(_MSC_VER) && defined(_M_IX86)
_asm
{
fld a
@ -692,6 +696,12 @@ ID_INLINE void idMath::SinCos( float a, float& s, float& c )
fstp dword ptr [ecx]
fstp dword ptr [edx]
}
#else
// DG: non-MSVC version
s = sinf(a);
c = cosf(a);
// DG end
#endif
}
/*
@ -1500,13 +1510,15 @@ ID_INLINE int idMath::FloatHash( const float* array, const int numFloats )
}
template< typename T >
ID_INLINE_EXTERN T Lerp( const T from, const T to, float f )
ID_INLINE
T Lerp( const T from, const T to, float f )
{
return from + ( ( to - from ) * f );
}
template<>
ID_INLINE_EXTERN int Lerp( const int from, const int to, float f )
ID_INLINE
int Lerp( const int from, const int to, float f )
{
return idMath::Ftoi( ( float ) from + ( ( ( float ) to - ( float ) from ) * f ) );
}

View file

@ -125,7 +125,7 @@ idSIMDProcessor *p_simd;
idSIMDProcessor *p_generic;
long baseClocks = 0;
#if defined(_MSC_VER) && defined(_M_IX86)
#define TIME_TYPE int
#pragma warning(disable : 4731) // frame pointer register 'ebx' modified by inline assembly code
@ -150,6 +150,29 @@ long saved_ebx = 0;
__asm xor eax, eax \
__asm cpuid
#elif MACOS_X // DG: versions for OSX and others from dhewm3
double ticksPerNanosecond;
#define TIME_TYPE uint64_t
#define StartRecordTime( start ) \
start = mach_absolute_time();
#define StopRecordTime( end ) \
end = mach_absolute_time();
#else // not _MSC_VER and _M_IX86 or MACOS_X
// FIXME: meaningful values/functions here for Linux?
#define TIME_TYPE int
#define StartRecordTime( start ) \
start = 0;
#define StopRecordTime( end ) \
end = 1;
#endif // DG end
#define GetBest( start, end, best ) \
if ( !best || end - start < best ) { \

View file

@ -84,7 +84,18 @@ bool AssertFailed( const char* file, int line, const char* expression )
if( IsDebuggerPresent() || com_assertOutOfDebugger.GetBool() )
{
#ifdef _WIN32
#ifdef _MSC_VERS
__debugbreak();
#else
// DG: mingw support
DebugBreak();
#endif
#else // not _WIN32
// DG: POSIX support
raise(SIGTRAP);
// DG: end
#endif // _WIN32
}
if( skipThisAssertion )

View file

@ -42,9 +42,20 @@ If you have questions concerning this license or the applicable additional terms
#define BUILD_STRING "win-" CPUSTRING
#define BUILD_OS_ID 0
#ifdef _MSC_VER
#define ALIGN16( x ) __declspec(align(16)) x
#define ALIGNTYPE16 __declspec(align(16))
#define ALIGNTYPE128 __declspec(align(128))
#else
// DG: mingw/GCC (and probably clang) support
#define ALIGN16( x ) x __attribute__ ((aligned (16)))
// FIXME: change ALIGNTYPE* ?
#define ALIGNTYPE16
#define ALIGNTYPE128
// DG end
#endif
#define FORMAT_PRINTF( x )
#define PATHSEPARATOR_STR "\\"
@ -52,8 +63,13 @@ If you have questions concerning this license or the applicable additional terms
#define NEWLINE "\r\n"
#define ID_INLINE inline
#ifdef _MSC_VER
#define ID_FORCE_INLINE __forceinline
#else
// DG: this should at least work with GCC/MinGW, probably with clang as well..
#define ID_FORCE_INLINE inline // TODO: always_inline?
// DG end
#endif
// lint complains that extern used with definition is a hazard, but it
// has the benefit (?) of making it illegal to take the address of the function
#ifdef _lint
@ -61,7 +77,13 @@ If you have questions concerning this license or the applicable additional terms
#define ID_FORCE_INLINE_EXTERN __forceinline
#else
#define ID_INLINE_EXTERN extern inline
#ifdef _MSC_VER
#define ID_FORCE_INLINE_EXTERN extern __forceinline
#else
// DG: GCC/MinGW, probably clang
#define ID_FORCE_INLINE_EXTERN extern inline // TODO: always_inline ?
// DG end
#endif
#endif
// we should never rely on this define in our code. this is here so dodgy external libraries don't get confused
@ -108,6 +130,7 @@ bulk of the codebase, so it is the best place for analyze pragmas.
================================================================================================
*/
#ifdef _MSC_VER
// disable some /analyze warnings here
#pragma warning( disable: 6255 ) // warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead. (Note: _malloca requires _freea.)
#pragma warning( disable: 6262 ) // warning C6262: Function uses '36924' bytes of stack: exceeds /analyze:stacksize'32768'. Consider moving some data to heap
@ -128,7 +151,16 @@ bulk of the codebase, so it is the best place for analyze pragmas.
// checking format strings catches a LOT of errors
#include <CodeAnalysis\SourceAnnotations.h>
#define VERIFY_FORMAT_STRING [SA_FormatString(Style="printf")]
// DG: alternative for GCC with attribute (NOOP for MSVC)
#define ATTRIBUTE_PRINTF(STRIDX, FIRSTARGIDX)
#elif defined(__GNUC__) // FIXME: what about clang?
#define VERIFY_FORMAT_STRING
// STRIDX: index of format string in function arguments (first arg == 1)
// FIRSTARGIDX: index of first argument for the format string
#define ATTRIBUTE_PRINTF(STRIDX, FIRSTARGIDX) __attribute__ ((format (printf, STRIDX, FIRSTARGIDX)))
// DG end
#endif // _MSC_VER
// We need to inform the compiler that Error() and FatalError() will
// never return, so any conditions that leeds to them being called are

View file

@ -53,12 +53,29 @@ If you have questions concerning this license or the applicable additional terms
#define DIRECTINPUT_VERSION 0x0800 // was 0x0700 with the old mssdk
#define DIRECTSOUND_VERSION 0x0800
#ifdef _MSC_VER
#include <dsound.h>
#else
// DG: MinGW is incompatible with the original dsound.h because it contains MSVC specific annotations
#include <wine-dsound.h>
#endif
#include <dinput.h>
#endif /* !GAME_DLL */
#endif /* !_D3SDK */
// DG: intrinsics for GCC
#if defined(__GNUC__) && defined(__SSE2__)
#include <emmintrin.h>
// TODO: else: alternative implementations?
#endif
// DG end
#ifdef _MSC_VER
#include <intrin.h> // needed for intrinsics like _mm_setzero_si28
#pragma warning(disable : 4100) // unreferenced formal parameter
@ -66,11 +83,13 @@ If you have questions concerning this license or the applicable additional terms
#pragma warning(disable : 4244) // conversion to smaller type, possible loss of data
#pragma warning(disable : 4714) // function marked as __forceinline not inlined
#pragma warning(disable : 4996) // unsafe string operations
#endif // _MSC_VER
#include <malloc.h> // no malloc.h on mac or unix
#include <windows.h> // for qgl.h
#undef FindText // fix namespace pollution
/*
================================================================================================

View file

@ -28,6 +28,8 @@ If you have questions concerning this license or the applicable additional terms
#ifndef __SYS_INTRIINSICS_H__
#define __SYS_INTRIINSICS_H__
#include <emmintrin.h>
/*
================================================================================================
@ -174,8 +176,24 @@ ID_INLINE_EXTERN int CACHE_LINE_CLEAR_OVERFLOW_COUNT( int size )
#define R_SHUFFLE_D( x, y, z, w ) (( (w) & 3 ) << 6 | ( (z) & 3 ) << 4 | ( (y) & 3 ) << 2 | ( (x) & 3 ))
#endif
// DG: _CRT_ALIGN seems to be MSVC specific, so provide implementation..
#ifndef _CRT_ALIGN
#if defined(__GNUC__) // also applies for clang
#define _CRT_ALIGN(x) __attribute__ ((__aligned__ (x)))
#elif defined(_MSC_VER) // also for MSVC, just to be sure
#define _CRT_ALIGN(x) __declspec(align(x))
#endif
#endif
// DG: make sure __declspec(intrin_type) is only used on MSVC (it's not available on GCC etc
#ifdef _MSC_VER
#define DECLSPEC_INTRINTYPE __declspec( intrin_type )
#else
#define DECLSPEC_INTRINTYPE
#endif
// DG end
// make the intrinsics "type unsafe"
typedef union __declspec( intrin_type ) _CRT_ALIGN( 16 ) __m128c
typedef union DECLSPEC_INTRINTYPE _CRT_ALIGN( 16 ) __m128c
{
__m128c() {}
__m128c( __m128 f )

View file

@ -45,9 +45,14 @@ typedef LONG interlockedInt_t;
// _ReadWriteBarrier() does not translate to any instructions but keeps the compiler
// from reordering read and write instructions across the barrier.
// MemoryBarrier() inserts and CPU instruction that keeps the CPU from reordering reads and writes.
#if defined(_MSC_VER)
#pragma intrinsic(_ReadWriteBarrier)
#define SYS_MEMORYBARRIER _ReadWriteBarrier(); MemoryBarrier()
#elif defined(__GNUC__) // FIXME: what about clang?
// according to http://en.wikipedia.org/wiki/Memory_ordering the following should be equivalent to the stuff above..
//#ifdef __sync_syncronize
#define SYS_MEMORYBARRIER asm volatile("" ::: "memory");__sync_synchronize()
#endif

View file

@ -161,7 +161,12 @@ ID_INLINE void WriteIndexPair( triIndex_t* dest, const triIndex_t a, const triIn
#if defined(_DEBUG) || defined(_lint)
#define NODEFAULT default: assert( 0 )
#else
#ifdef _MSVC
#define NODEFAULT default: __assume( 0 )
#else // not _MSVC
// TODO: is that __assume an important optimization? if so, is there a gcc equivalent?
#define NODEFAULT
#endif
#endif
/*

View file

@ -35,6 +35,11 @@ If you have questions concerning this license or the applicable additional terms
#define MS_VC_EXCEPTION 0x406D1388
#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
// MinGW doesn't seem to have this
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
#endif
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
@ -42,19 +47,31 @@ typedef struct tagTHREADNAME_INFO
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
/*
========================
Sys_SetThreadName
caedes: This should be seen as a helper-function for Sys_CreateThread() only.
(re)setting the name of a running thread seems like a bad idea and
currently (fresh d3 bfg source) isn't done anyway.
Furthermore SDL doesn't support it
========================
*/
void Sys_SetThreadName( DWORD threadID, const char* name )
static void Sys_SetThreadName( DWORD threadID, const char* name )
{
#ifdef _MSC_VER
// this ugly mess is the official way to set a thread name on windows..
// see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = threadID;
info.dwFlags = 0;
__try
{
RaiseException( MS_VC_EXCEPTION, 0, sizeof( info ) / sizeof( DWORD ), ( const ULONG_PTR* )&info );
@ -64,16 +81,7 @@ void Sys_SetThreadName( DWORD threadID, const char* name )
{
info.dwFlags = 0;
}
}
/*
========================
Sys_SetCurrentThreadName
========================
*/
void Sys_SetCurrentThreadName( const char* name )
{
Sys_SetThreadName( GetCurrentThreadId(), name );
#endif
}
/*
@ -113,6 +121,7 @@ uintptr_t Sys_CreateThread( xthread_t function, void* parms, xthreadPriority pri
idLib::common->FatalError( "CreateThread error: %i", GetLastError() );
return ( uintptr_t )0;
}
// TODO: when writing the SDL backend, just use this name when creating the thread
Sys_SetThreadName( threadId, name );
if( priority == THREAD_HIGHEST )
{
@ -314,7 +323,13 @@ Sys_InterlockedIncrement
*/
interlockedInt_t Sys_InterlockedIncrement( interlockedInt_t& value )
{
// TODO: SDL_AtomicIncRef
#ifdef InterlockedIncrementAcquire
// googling suggests that some experimental mingw code supports this too..
return InterlockedIncrementAcquire( & value );
#elif defined(__GNUC__)
return __sync_add_and_fetch( &value, 1 );
#endif
}
/*
@ -324,7 +339,12 @@ Sys_InterlockedDecrement
*/
interlockedInt_t Sys_InterlockedDecrement( interlockedInt_t& value )
{
// TODO: SDL_AtomicDecRef
#ifdef InterlockedDecrementRelease
return InterlockedDecrementRelease( & value );
#elif defined(__GNUC__)
return __sync_sub_and_fetch( &value, 1 );
#endif
}
/*