- Fixed: Modern versions of GCC on PowerPC inserted padding to the end of pragma packed structures.

- Worked aorund modern GCC bug where C++ exceptions in Objective-C++ code would result in an ICE (bug is already on their tracker, but I doubt it will be fixed unless I decide to dig into the issue myself).
- Turn off fused floating point instructions since these can cause slight deviations in floating point code.
- Use -static-libgcc when compiling on the Mac with GCC since we need to use a custom version of GCC to do so now.
- Note: ZDoom will currently still crash on exit on PowerPC since it seems to be deciding that NameManager needs to be destructed before the console commands.
This commit is contained in:
Braden Obrzut 2016-03-13 00:34:35 -05:00
parent 0269aeea80
commit 93be5aca05
10 changed files with 125 additions and 71 deletions

View file

@ -167,6 +167,11 @@ else()
set( ALL_C_FLAGS "" ) set( ALL_C_FLAGS "" )
set( REL_C_FLAGS "" ) set( REL_C_FLAGS "" )
set( DEB_C_FLAGS "" ) set( DEB_C_FLAGS "" )
# If we're compiling with a custom GCC on the Mac (which we know since g++-4.2 doesn't support C++11) statically link libgcc.
if( APPLE AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" )
set( ALL_C_FLAGS "-static-libgcc" )
endif()
endif() endif()
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${REL_LINKER_FLAGS}" ) set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${REL_LINKER_FLAGS}" )
@ -193,7 +198,7 @@ option(FORCE_INTERNAL_GME "Use internal gme" ON)
# Fast math flags, required by some subprojects # Fast math flags, required by some subprojects
set( ZD_FASTMATH_FLAG "" ) set( ZD_FASTMATH_FLAG "" )
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
set( ZD_FASTMATH_FLAG "-ffast-math" ) set( ZD_FASTMATH_FLAG "-ffast-math -ffp-contract=fast" )
elseif( MSVC ) elseif( MSVC )
set( ZD_FASTMATH_FLAG "/fp:fast" ) set( ZD_FASTMATH_FLAG "/fp:fast" )
endif() endif()

View file

@ -465,28 +465,28 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
set( CMAKE_C_FLAGS "-Wno-unused-result ${CMAKE_C_FLAGS}" ) set( CMAKE_C_FLAGS "-Wno-unused-result ${CMAKE_C_FLAGS}" )
set( CMAKE_CXX_FLAGS "-Wno-unused-result ${CMAKE_CXX_FLAGS}" ) set( CMAKE_CXX_FLAGS "-Wno-unused-result ${CMAKE_CXX_FLAGS}" )
endif() endif()
set( CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers ${CMAKE_C_FLAGS}" ) set( CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers -ffp-contract=off ${CMAKE_C_FLAGS}" )
set( CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS}" ) set( CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers -ffp-contract=off ${CMAKE_CXX_FLAGS}" )
# Use the highest C++ standard available since VS2015 compiles with C++14 # Use the highest C++ standard available since VS2015 compiles with C++14
# but we only require C++11. The recommended way to do this in CMake is to # but we only require C++11. The recommended way to do this in CMake is to
# probably to use target_compile_features, but I don't feel like maintaining # probably to use target_compile_features, but I don't feel like maintaining
# a list of features we use. # a list of features we use.
CHECK_CXX_COMPILER_FLAG( "-std=c++14" CAN_DO_CPP14 ) CHECK_CXX_COMPILER_FLAG( "-std=gnu++14" CAN_DO_CPP14 )
if ( CAN_DO_CPP14 ) if ( CAN_DO_CPP14 )
set ( CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}" ) set ( CMAKE_CXX_FLAGS "-std=gnu++14 ${CMAKE_CXX_FLAGS}" )
else () else ()
CHECK_CXX_COMPILER_FLAG( "-std=c++1y" CAN_DO_CPP1Y ) CHECK_CXX_COMPILER_FLAG( "-std=gnu++1y" CAN_DO_CPP1Y )
if ( CAN_DO_CPP1Y ) if ( CAN_DO_CPP1Y )
set ( CMAKE_CXX_FLAGS "-std=c++1y ${CMAKE_CXX_FLAGS}" ) set ( CMAKE_CXX_FLAGS "-std=gnu++1y ${CMAKE_CXX_FLAGS}" )
else () else ()
CHECK_CXX_COMPILER_FLAG( "-std=c++11" CAN_DO_CPP11 ) CHECK_CXX_COMPILER_FLAG( "-std=gnu++11" CAN_DO_CPP11 )
if ( CAN_DO_CPP11 ) if ( CAN_DO_CPP11 )
set ( CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}" ) set ( CMAKE_CXX_FLAGS "-std=gnu++11 ${CMAKE_CXX_FLAGS}" )
else () else ()
CHECK_CXX_COMPILER_FLAG( "-std=c++0x" CAN_DO_CPP0X ) CHECK_CXX_COMPILER_FLAG( "-std=gnu++0x" CAN_DO_CPP0X )
if ( CAN_DO_CPP0X ) if ( CAN_DO_CPP0X )
set ( CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}" ) set ( CMAKE_CXX_FLAGS "-std=gnu++0x ${CMAKE_CXX_FLAGS}" )
endif () endif ()
endif () endif ()
endif () endif ()
@ -645,6 +645,7 @@ set( PLAT_COCOA_SOURCES
posix/cocoa/i_input.mm posix/cocoa/i_input.mm
posix/cocoa/i_joystick.cpp posix/cocoa/i_joystick.cpp
posix/cocoa/i_main.mm posix/cocoa/i_main.mm
posix/cocoa/i_main_except.cpp
posix/cocoa/i_system.mm posix/cocoa/i_system.mm
posix/cocoa/i_timer.cpp posix/cocoa/i_timer.cpp
posix/cocoa/i_video.mm posix/cocoa/i_video.mm
@ -681,6 +682,7 @@ elseif( APPLE )
set_source_files_properties( posix/osx/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) set_source_files_properties( posix/osx/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources )
set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks ) set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks )
set_source_files_properties( posix/osx/iwadpicker_cocoa.mm PROPERTIES COMPILE_FLAGS -fobjc-exceptions )
else() else()
set( SYSTEM_SOURCES_DIR posix posix/sdl ) set( SYSTEM_SOURCES_DIR posix posix/sdl )
set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ) set( SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} )

View file

@ -123,6 +123,18 @@ typedef TMap<int, PClassActor *> FClassMap;
#define NO_SANITIZE #define NO_SANITIZE
#endif #endif
#if defined(__GNUC__)
// With versions of GCC newer than 4.2, it appears it was determined that the
// cost of an unaligned pointer on PPC was high enough to add padding to the
// end of packed structs. For whatever reason __packed__ and pragma pack are
// handled differently in this regard. Note that this only needs to be applied
// to types which are used in arrays or sizeof is needed. This also prevents
// code from taking references to the struct members.
#define FORCE_PACKED __attribute__((__packed__))
#else
#define FORCE_PACKED
#endif
#include "basictypes.h" #include "basictypes.h"
extern bool batchrun; extern bool batchrun;

View file

@ -149,6 +149,8 @@ static const NSOpenGLPixelFormatAttribute NSOpenGLPFAAllowOfflineRenderers = NSO
- (void)setCollectionBehavior:(NSUInteger)collectionBehavior; - (void)setCollectionBehavior:(NSUInteger)collectionBehavior;
@end @end
typedef NSUInteger NSWindowCollectionBehavior;
#endif // prior to 10.5 #endif // prior to 10.5

View file

@ -67,7 +67,6 @@ EXTERN_CVAR(Bool, fullscreen )
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
namespace namespace
{ {
@ -78,6 +77,9 @@ void (*TermFuncs[MAX_TERMS])();
const char *TermNames[MAX_TERMS]; const char *TermNames[MAX_TERMS];
size_t NumTerms; size_t NumTerms;
} // unnamed namespace
// Expose this for i_main_except.cpp
void call_terms() void call_terms()
{ {
while (NumTerms > 0) while (NumTerms > 0)
@ -86,8 +88,6 @@ void call_terms()
} }
} }
} // unnamed namespace
void addterm(void (*func)(), const char *name) void addterm(void (*func)(), const char *name)
{ {
@ -133,6 +133,41 @@ void Mac_I_FatalError(const char* const message)
DArgs* Args; // command line arguments DArgs* Args; // command line arguments
// Newer versions of GCC than 4.2 have a bug with C++ exceptions in Objective-C++ code.
// To work around we'll implement the try and catch in standard C++.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61759
void OriginalMainExcept(int argc, char** argv);
void OriginalMainTry(int argc, char** argv)
{
Args = new DArgs(argc, argv);
/*
killough 1/98:
This fixes some problems with exit handling
during abnormal situations.
The old code called I_Quit() to end program,
while now I_Quit() is installed as an exit
handler and exit() is called to exit, either
normally or abnormally. Seg faults are caught
and the error handler is used, to prevent
being left in graphics mode or having very
loud SFX noise because the sound card is
left in an unstable state.
*/
atexit(call_terms);
atterm(I_Quit);
NSString* exePath = [[NSBundle mainBundle] executablePath];
progdir = [[exePath stringByDeletingLastPathComponent] UTF8String];
progdir += "/";
C_InitConsole(80 * 8, 25 * 8, false);
D_DoomMain();
}
namespace namespace
{ {
@ -151,7 +186,6 @@ void NewFailure()
I_FatalError("Failed to allocate memory from system heap"); I_FatalError("Failed to allocate memory from system heap");
} }
int OriginalMain(int argc, char** argv) int OriginalMain(int argc, char** argv)
{ {
printf(GAMENAME" %s - %s - Cocoa version\nCompiled on %s\n\n", printf(GAMENAME" %s - %s - Cocoa version\nCompiled on %s\n\n",
@ -174,53 +208,7 @@ int OriginalMain(int argc, char** argv)
vid_vsync = true; vid_vsync = true;
fullscreen = true; fullscreen = true;
try OriginalMainExcept(argc, argv);
{
Args = new DArgs(argc, argv);
/*
killough 1/98:
This fixes some problems with exit handling
during abnormal situations.
The old code called I_Quit() to end program,
while now I_Quit() is installed as an exit
handler and exit() is called to exit, either
normally or abnormally. Seg faults are caught
and the error handler is used, to prevent
being left in graphics mode or having very
loud SFX noise because the sound card is
left in an unstable state.
*/
atexit(call_terms);
atterm(I_Quit);
NSString* exePath = [[NSBundle mainBundle] executablePath];
progdir = [[exePath stringByDeletingLastPathComponent] UTF8String];
progdir += "/";
C_InitConsole(80 * 8, 25 * 8, false);
D_DoomMain();
}
catch(const CDoomError& error)
{
const char* const message = error.GetMessage();
if (NULL != message)
{
fprintf(stderr, "%s\n", message);
Mac_I_FatalError(message);
}
exit(-1);
}
catch(...)
{
call_terms();
throw;
}
return 0; return 0;
} }

View file

@ -0,0 +1,34 @@
// Workaround for GCC Objective-C++ with C++ exceptions bug.
#include "doomerrors.h"
#include <stdlib.h>
// Import some functions from i_main.mm
void call_terms();
void Mac_I_FatalError(const char* const message);
void OriginalMainTry(int argc, char** argv);
void OriginalMainExcept(int argc, char** argv)
{
try
{
OriginalMainTry(argc, argv);
}
catch(const CDoomError& error)
{
const char* const message = error.GetMessage();
if (NULL != message)
{
fprintf(stderr, "%s\n", message);
Mac_I_FatalError(message);
}
exit(-1);
}
catch(...)
{
call_terms();
throw;
}
}

View file

@ -100,14 +100,14 @@ typedef struct tagITFILEHEADER
DWORD reserved2; DWORD reserved2;
BYTE chnpan[64]; BYTE chnpan[64];
BYTE chnvol[64]; BYTE chnvol[64];
} ITFILEHEADER, *PITFILEHEADER; } FORCE_PACKED ITFILEHEADER, *PITFILEHEADER;
typedef struct MODMIDICFG typedef struct MODMIDICFG
{ {
char szMidiGlb[9*32]; // changed from CHAR char szMidiGlb[9*32]; // changed from CHAR
char szMidiSFXExt[16*32]; // changed from CHAR char szMidiSFXExt[16*32]; // changed from CHAR
char szMidiZXXExt[128*32]; // changed from CHAR char szMidiZXXExt[128*32]; // changed from CHAR
} MODMIDICFG, *LPMODMIDICFG; } FORCE_PACKED MODMIDICFG, *LPMODMIDICFG;
#pragma pack() #pragma pack()

View file

@ -72,7 +72,7 @@ struct PCXHeader
BYTE padding[54]; BYTE padding[54];
}; } FORCE_PACKED;
#pragma pack() #pragma pack()
//========================================================================== //==========================================================================

View file

@ -13,7 +13,7 @@ struct FZipEndOfCentralDirectory
DWORD DirectorySize; DWORD DirectorySize;
DWORD DirectoryOffset; DWORD DirectoryOffset;
WORD ZipCommentLength; WORD ZipCommentLength;
}; } FORCE_PACKED;
// FZipFileInfo // FZipFileInfo
struct FZipCentralDirectoryInfo struct FZipCentralDirectoryInfo
@ -36,7 +36,7 @@ struct FZipCentralDirectoryInfo
DWORD ExternalAttributes; DWORD ExternalAttributes;
DWORD LocalHeaderOffset; DWORD LocalHeaderOffset;
// file name and other variable length info follows // file name and other variable length info follows
}; } FORCE_PACKED;
// FZipLocalHeader // FZipLocalHeader
struct FZipLocalFileHeader struct FZipLocalFileHeader
@ -53,7 +53,7 @@ struct FZipLocalFileHeader
WORD NameLength; WORD NameLength;
WORD ExtraLength; WORD ExtraLength;
// file name and other variable length info follows // file name and other variable length info follows
}; } FORCE_PACKED;
#pragma pack() #pragma pack()

View file

@ -60,6 +60,17 @@
#define __cdecl #define __cdecl
#endif #endif
#ifdef __GNUC__
// With versions of GCC newer than 4.2, it appears it was determined that the
// cost of an unaligned pointer on PPC was high enough to add padding to the
// end of packed structs. For whatever reason __packed__ and pragma pack are
// handled differently in this regard. Note that this only needs to be applied
// to types which are used in arrays.
#define FORCE_PACKED __attribute__((__packed__))
#else
#define FORCE_PACKED
#endif
#ifndef __BIG_ENDIAN__ #ifndef __BIG_ENDIAN__
#define MAKE_ID(a,b,c,d) ((a)|((b)<<8)|((c)<<16)|((d)<<24)) #define MAKE_ID(a,b,c,d) ((a)|((b)<<8)|((c)<<16)|((d)<<24))
#define LittleShort(x) (x) #define LittleShort(x) (x)
@ -150,7 +161,7 @@ typedef struct
UINT32 UncompressedSize; // 22 UINT32 UncompressedSize; // 22
WORD NameLength; // 26 WORD NameLength; // 26
WORD ExtraLength; // 28 WORD ExtraLength; // 28
} LocalFileHeader; } FORCE_PACKED LocalFileHeader;
typedef struct typedef struct
{ {
@ -171,7 +182,7 @@ typedef struct
WORD InternalAttributes; WORD InternalAttributes;
UINT32 ExternalAttributes; UINT32 ExternalAttributes;
UINT32 LocalHeaderOffset; UINT32 LocalHeaderOffset;
} CentralDirectoryEntry; } FORCE_PACKED CentralDirectoryEntry;
typedef struct typedef struct
{ {
@ -183,7 +194,7 @@ typedef struct
UINT32 DirectorySize; UINT32 DirectorySize;
UINT32 DirectoryOffset; UINT32 DirectoryOffset;
WORD ZipCommentLength; WORD ZipCommentLength;
} EndOfCentralDirectory; } FORCE_PACKED EndOfCentralDirectory;
//#pragma pack(pop) //#pragma pack(pop)
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------