@@ -61,21 +61,14 @@ # import "threading.h" #endif #if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR) extern id of_forward(id, SEL, ...); -# ifdef OF_APPLE_RUNTIME -/* - * Forwarding for methods returning structs only works with the Apple ABI, as - * with the GNU ABI, there is no way of knowing if a struct is returned and if - * so how. - * As forwardingTargetForSelector: only works for architectures for which - * assembly has been written anyway, it makes sense to switch to - * objc_msgSend(_{st,fp}ret) for those architectures to solve this problem. - */ extern struct stret of_forward_stret(id, SEL, ...); -# endif +#else +# define of_forward NULL +# define of_forward_stret NULL #endif struct pre_ivar { int32_t retainCount; struct pre_mem *firstMem, *lastMem; @@ -144,11 +137,11 @@ abort(); } #ifdef OF_OBJFW_RUNTIME static IMP -forward_handler(id obj, SEL sel) +common_forward_handler(id obj, SEL sel, IMP (*lookup)(id, SEL), IMP forward) { /* Try resolveClassMethod:/resolveInstanceMethod: */ if (class_isMetaClass(object_getClass(obj))) { if ([obj respondsToSelector: @selector(resolveClassMethod:)] && [obj resolveClassMethod: sel]) { @@ -158,11 +151,11 @@ "without adding the method!\n", class_getName(obj), sel_getName(sel)); abort(); } - return objc_msg_lookup(obj, sel); + return lookup(obj, sel); } } else { Class c = object_getClass(obj); if ([c respondsToSelector: @selector(resolveInstanceMethod:)] && @@ -174,27 +167,41 @@ class_getName(object_getClass(obj)), sel_getName(sel)); abort(); } - return objc_msg_lookup(obj, sel); + return lookup(obj, sel); } } #ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR if (class_respondsToSelector(object_getClass(obj), @selector(forwardingTargetForSelector:))) { id target = [obj forwardingTargetForSelector: sel]; if (target != nil && target != obj) - return (IMP)of_forward; + return forward; } #endif of_method_not_found(obj, sel); return NULL; } + +static IMP +forward_handler(id obj, SEL sel) +{ + return common_forward_handler(obj, sel, + objc_msg_lookup, (IMP)of_forward); +} + +static IMP +forward_handler_stret(id obj, SEL sel) +{ + return common_forward_handler(obj, sel, + objc_msg_lookup_stret, (IMP)of_forward_stret); +} #endif #ifndef HAVE_OBJC_ENUMERATIONMUTATION void objc_enumerationMutation(id object) @@ -273,11 +280,12 @@ objc_setUncaughtExceptionHandler(uncaught_exception_handler); #endif #if defined(OF_OBJFW_RUNTIME) objc_forward_handler = forward_handler; -#elif defined(OF_APPLE_RUNTIME) && !defined(__ppc64__) + objc_forward_handler_stret = forward_handler_stret; +#elif defined(OF_APPLE_RUNTIME) && defined(HAVE_FORWARDING_TARGET_FOR_SELECTOR) objc_setForwardHandler(of_forward, of_forward_stret); #endif #ifdef HAVE_OBJC_ENUMERATIONMUTATION objc_setEnumerationMutationHandler(enumeration_mutation_handler);