Skip to content

Commit

Permalink
Support compiling on mingw (no exception handling)
Browse files Browse the repository at this point in the history
  • Loading branch information
qmfrederik authored and davidchisnall committed Dec 31, 2023
1 parent 4d9d930 commit a61309b
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 41 deletions.
14 changes: 7 additions & 7 deletions CMakeLists.txt
Expand Up @@ -114,12 +114,12 @@ set(libBlocksRuntime_COMPATIBILITY_HDRS
set(libobjc_CXX_SRCS
selector_table.cc
)
# Windows does not use DWARF EH
if (WIN32)
# Windows does not use DWARF EH, except when using the GNU ABI (MinGW)
if (WIN32 AND NOT MINGW)
list(APPEND libobjc_CXX_SRCS eh_win32_msvc.cc)
else ()
list(APPEND libobjc_C_SRCS eh_personality.c)
endif (WIN32)
endif (WIN32 AND NOT MINGW)

find_package(tsl-robin-map)

Expand All @@ -132,7 +132,7 @@ if (NOT tls-robin-map_FOUND)
FetchContent_MakeAvailable(robinmap)
endif()

if (WIN32)
if (WIN32 AND NOT MINGW)
set(OLD_ABI_COMPAT_DEFAULT false)
else()
set(OLD_ABI_COMPAT_DEFAULT true)
Expand Down Expand Up @@ -189,7 +189,7 @@ if(WIN32)
endif()


if (MSVC)
if (WIN32 AND NOT MINGW)
set(ASSEMBLER ${CMAKE_ASM_COMPILER} CACHE STRING "Assembler to use with Visual Studio (must be gcc / clang!)")
message(STATUS "Using custom build commands to work around CMake bugs")
message(STATUS "ASM compiler: ${ASSEMBLER}")
Expand All @@ -210,7 +210,7 @@ endif()



if (WIN32)
if (WIN32 AND NOT MINGW)
message(STATUS "Using MSVC-compatible exception model")
else ()
separate_arguments(EH_PERSONALITY_FLAGS NATIVE_COMMAND ${CMAKE_CXX_FLAGS})
Expand All @@ -234,7 +234,7 @@ target_sources(objc PRIVATE ${libobjc_CXX_SRCS})
include(FindThreads)
target_link_libraries(objc Threads::Threads)
# Link against ntdll.dll for RtlRaiseException
if (WIN32)
if (WIN32 AND NOT MINGW)
target_link_libraries(objc ntdll.dll)
endif()

Expand Down
6 changes: 6 additions & 0 deletions common.S
Expand Up @@ -10,3 +10,9 @@
#define TYPE_DIRECTIVE(symbol, symboltype)
#endif

#if defined(_MSC_VER) && defined(__i386__)
#define STRINGIFY(a) #a
#define EXPORT_SYMBOL(symbol) .ascii " " STRINGIFY(/EXPORT:_##symbol)
#else
#define EXPORT_SYMBOL(symbol) .ascii " /EXPORT:" #symbol
#endif
18 changes: 11 additions & 7 deletions eh_personality.c
Expand Up @@ -550,25 +550,29 @@ static inline _Unwind_Reason_Code internal_objc_personality(int version,
}
}

_Unwind_SetIP(context, (unsigned long)action.landing_pad);
_Unwind_SetIP(context, (uintptr_t)action.landing_pad);
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
(unsigned long)(isNew ? exceptionObject : object));
(uintptr_t)(isNew ? exceptionObject : object));
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1), selector);

DEBUG_LOG("Installing context, selector %d\n", (int)selector);
get_thread_data()->cxxCaughtException = NO;
return _URC_INSTALL_CONTEXT;
}

OBJC_PUBLIC
BEGIN_PERSONALITY_FUNCTION(__gnu_objc_personality_v0)
return internal_objc_personality(version, actions, exceptionClass,
exceptionObject, context, NO);
}

OBJC_PUBLIC
BEGIN_PERSONALITY_FUNCTION(__gnustep_objc_personality_v0)
return internal_objc_personality(version, actions, exceptionClass,
exceptionObject, context, YES);
}

OBJC_PUBLIC
BEGIN_PERSONALITY_FUNCTION(__gnustep_objcxx_personality_v0)
#ifndef NO_OBJCXX
if (cxx_exception_class == 0)
Expand All @@ -584,11 +588,11 @@ BEGIN_PERSONALITY_FUNCTION(__gnustep_objcxx_personality_v0)
}
// We now have two copies of the _Unwind_Exception object (which stores
// state for the unwinder) in flight. Make sure that they're in sync.
COPY_EXCEPTION(ex->cxx_exception, exceptionObject)
COPY_EXCEPTION(ex->cxx_exception, exceptionObject);
exceptionObject = ex->cxx_exception;
exceptionClass = cxx_exception_class;
int ret = CALL_PERSONALITY_FUNCTION(__gxx_personality_v0);
COPY_EXCEPTION(exceptionObject, ex->cxx_exception)
COPY_EXCEPTION(exceptionObject, ex->cxx_exception);
if (ret == _URC_INSTALL_CONTEXT)
{
get_thread_data()->cxxCaughtException = YES;
Expand All @@ -599,7 +603,7 @@ BEGIN_PERSONALITY_FUNCTION(__gnustep_objcxx_personality_v0)
return CALL_PERSONALITY_FUNCTION(__gxx_personality_v0);
}

id objc_begin_catch(struct _Unwind_Exception *exceptionObject)
OBJC_PUBLIC id objc_begin_catch(struct _Unwind_Exception *exceptionObject)
{
struct thread_data *td = get_thread_data();
DEBUG_LOG("Beginning catch %p\n", exceptionObject);
Expand Down Expand Up @@ -671,7 +675,7 @@ id objc_begin_catch(struct _Unwind_Exception *exceptionObject)
return (id)((char*)exceptionObject + sizeof(struct _Unwind_Exception));
}

void objc_end_catch(void)
OBJC_PUBLIC void objc_end_catch(void)
{
struct thread_data *td = get_thread_data_fast();
// If this is a boxed foreign exception then the boxing class is
Expand Down Expand Up @@ -717,7 +721,7 @@ void objc_end_catch(void)
}
}

void objc_exception_rethrow(struct _Unwind_Exception *e)
OBJC_PUBLIC void objc_exception_rethrow(struct _Unwind_Exception *e)
{
struct thread_data *td = get_thread_data_fast();
// If this is an Objective-C exception, then
Expand Down
2 changes: 1 addition & 1 deletion objc/hooks.h
Expand Up @@ -47,7 +47,7 @@ OBJC_PUBLIC extern struct objc_slot *(*__objc_msg_forward3)(id, SEL) OBJC_DEPREC
*/
OBJC_PUBLIC extern IMP (*__objc_msg_forward2)(id, SEL);

#ifndef _WIN32
#ifndef _MSC_VER
/**
* Hook defined for handling unhandled exceptions. If the unwind library
* reaches the end of the stack without finding a handler then this hook is
Expand Down
10 changes: 5 additions & 5 deletions objc_msgSend.x86-32.S
Expand Up @@ -37,7 +37,7 @@
test %eax, %eax
jz 5f # Nil slot - invoke some kind of forwarding mechanism
mov SLOT_OFFSET(%eax), %ecx
#ifdef _WIN32
#ifdef _MSC_VER
call *CDECL(__guard_check_icall_fptr)
#endif
jmp *%ecx
Expand All @@ -62,7 +62,7 @@
add $12, %esp # restore the stack


#ifdef _WIN32
#ifdef _MSC_VER
mov %eax, %ecx
call *CDECL(__guard_check_icall_fptr)
jmp *%ecx
Expand Down Expand Up @@ -126,7 +126,7 @@ CDECL(objc_msgSend_stret):

#ifdef _WIN32
.section .drectve,"yn"
.ascii " /EXPORT:_objc_msgSend"
.ascii " /EXPORT:_objc_msgSend_stret"
.ascii " /EXPORT:_objc_msgSend_fpret"
EXPORT_SYMBOL(objc_msgSend)
EXPORT_SYMBOL(objc_msgSend_stret)
EXPORT_SYMBOL(objc_msgSend_fpret)
#endif
10 changes: 6 additions & 4 deletions objc_msgSend.x86-64.S
Expand Up @@ -193,7 +193,7 @@

12:
#endif // WITH_TRACING
#ifdef _WIN64
#ifdef _MSC_VER
mov %r10, %rax
jmp *__guard_dispatch_icall_fptr(%rip)
#else
Expand Down Expand Up @@ -295,9 +295,11 @@ TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), @function)
CDECL(objc_msgSend_stret):
MSGSEND objc_msgSend_stret, %rdx, %r8
.section .drectve,"yn"
.ascii " /EXPORT:objc_msgSend"
.ascii " /EXPORT:objc_msgSend_fpret"
.ascii " /EXPORT:objc_msgSend_stret"
EXPORT_SYMBOL(objc_msgSend)

EXPORT_SYMBOL(objc_msgSend_fpret)

EXPORT_SYMBOL(objc_msgSend_stret)
#else
.globl CDECL(objc_msgSend)
TYPE_DIRECTIVE(CDECL(objc_msgSend), @function)
Expand Down
6 changes: 3 additions & 3 deletions objcxx_eh.cc
Expand Up @@ -218,7 +218,7 @@ namespace gnustep
/**
* Superclass for the type info for Objective-C exceptions.
*/
struct __objc_type_info : std::type_info
struct OBJC_PUBLIC __objc_type_info : std::type_info
{
/**
* Constructor that sets the name.
Expand Down Expand Up @@ -266,7 +266,7 @@ namespace gnustep
/**
* Singleton type info for the `id` type.
*/
struct __objc_id_type_info : __objc_type_info
struct OBJC_PUBLIC __objc_id_type_info : __objc_type_info
{
/**
* The `id` type is mangled to `@id`, which is not a valid mangling
Expand All @@ -278,7 +278,7 @@ namespace gnustep
void **obj,
unsigned outer) const;
};
struct __objc_class_type_info : __objc_type_info
struct OBJC_PUBLIC __objc_class_type_info : __objc_type_info
{
virtual ~__objc_class_type_info();
virtual bool __do_catch(const type_info *thrownType,
Expand Down
41 changes: 27 additions & 14 deletions unwind-itanium.h
Expand Up @@ -79,22 +79,26 @@ struct _Unwind_Exception
{
uint64_t exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
#ifdef __SEH__
uintptr_t private_[6];
#else
uintptr_t private_1;
uintptr_t private_2;
#endif
} __attribute__((__aligned__));

extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *);
extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *,
_Unwind_Stop_Fn, void *);
extern void _Unwind_Resume (struct _Unwind_Exception *);
extern void _Unwind_DeleteException (struct _Unwind_Exception *);
extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int);
extern void _Unwind_SetGR (struct _Unwind_Context *, int, unsigned long);
extern unsigned long _Unwind_GetIP (struct _Unwind_Context *);
extern unsigned long _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
extern void _Unwind_SetIP (struct _Unwind_Context *, unsigned long);
extern unsigned long _Unwind_GetLanguageSpecificData (struct _Unwind_Context*);
extern unsigned long _Unwind_GetRegionStart (struct _Unwind_Context *);
extern uintptr_t _Unwind_GetGR (struct _Unwind_Context *, int);
extern void _Unwind_SetGR (struct _Unwind_Context *, int, uintptr_t);
extern uintptr_t _Unwind_GetIP (struct _Unwind_Context *);
extern uintptr_t _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
extern void _Unwind_SetIP (struct _Unwind_Context *, uintptr_t);
extern uintptr_t _Unwind_GetLanguageSpecificData (struct _Unwind_Context*);
extern uintptr_t _Unwind_GetRegionStart (struct _Unwind_Context *);

#ifdef _GNU_SOURCE

Expand All @@ -115,17 +119,17 @@ extern _Unwind_Reason_Code

/* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why
_Unwind_GetBSP() exists. */
extern unsigned long _Unwind_GetBSP (struct _Unwind_Context *);
extern uintptr_t _Unwind_GetBSP (struct _Unwind_Context *);

/* Return the "canonical frame address" for the given context.
This is used by NPTL... */
extern unsigned long _Unwind_GetCFA (struct _Unwind_Context *);
extern uintptr_t _Unwind_GetCFA (struct _Unwind_Context *);

/* Return the base-address for data references. */
extern unsigned long _Unwind_GetDataRelBase (struct _Unwind_Context *);
extern uintptr_t _Unwind_GetDataRelBase (struct _Unwind_Context *);

/* Return the base-address for text references. */
extern unsigned long _Unwind_GetTextRelBase (struct _Unwind_Context *);
extern uintptr_t _Unwind_GetTextRelBase (struct _Unwind_Context *);

/* Call _Unwind_Trace_Fn once for each stack-frame, without doing any
cleanup. The first frame for which the callback is invoked is the
Expand Down Expand Up @@ -164,12 +168,21 @@ _Unwind_Reason_Code name(int version,\

#define CALL_PERSONALITY_FUNCTION(name) name(version, actions, exceptionClass, exceptionObject, context)

#ifdef __SEH__
#define COPY_EXCEPTION(dst, src) \
do { \
memcpy((dst)->private_, (src)->private_, sizeof((src)->private_)); \
} while(0)
#else
#define COPY_EXCEPTION(dst, src) \
(dst)->private_1 = (src)->private_1; \
(dst)->private_2 = (src)->private_2;
do { \
(dst)->private_1 = (src)->private_1; \
(dst)->private_2 = (src)->private_2; \
} while(0)
#endif

#ifdef __cplusplus
}
#endif

#endif /* _UNWIND_H */
#endif /* _UNWIND_H */

1 comment on commit a61309b

@gcasa
Copy link
Member

@gcasa gcasa commented on a61309b Jan 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just have to say that this is awesome! Thanks guys! :)

Please sign in to comment.