Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -130,15 +130,17 @@ # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif # endif -# elif defined(_WIN32) && defined(__i386__) +# elif defined(_WIN32) +# if defined(__x86_64__) || defined(__i386__) # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR # if __OBJFW_RUNTIME_ABI__ >= 800 # define OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET # endif +# endif # endif #endif #if __has_feature(objc_arc) # define OF_RETURNS_RETAINED __attribute__((ns_returns_retained)) ADDED src/forwarding/forwarding-amd64-win64.S Index: src/forwarding/forwarding-amd64-win64.S ================================================================== --- src/forwarding/forwarding-amd64-win64.S +++ src/forwarding/forwarding-amd64-win64.S @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +.globl of_forward +.globl of_forward_stret + +.section .text +of_forward: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0x90, %rsp /* 16-byte alignment */ + movq %rax, -0x28(%rbp) + movq %rcx, -0x30(%rbp) + movq %rdx, -0x38(%rbp) + movq %r8, -0x40(%rbp) + movq %r9, -0x48(%rbp) + movdqa %xmm0, -0x60(%rbp) + movdqa %xmm1, -0x70(%rbp) + movdqa %xmm2, -0x80(%rbp) + movdqa %xmm3, -0x90(%rbp) + + call object_getClass + + movq %rax, %rcx + leaq sel_forwardingTargetForSelector_(%rip), %rdx + call class_respondsToSelector + + testq %rax, %rax + jz 0f + + movq -0x30(%rbp), %rcx + leaq sel_forwardingTargetForSelector_(%rip), %rdx + call objc_msg_lookup + + movq -0x30(%rbp), %rcx + leaq sel_forwardingTargetForSelector_(%rip), %rdx + movq -0x38(%rbp), %r8 + call *%rax + + testq %rax, %rax + jz 0f + cmpq -0x30(%rbp), %rax + je 0f + + movq %rax, -0x30(%rbp) + + movq %rax, %rcx + movq -0x38(%rbp), %rdx + call objc_msg_lookup + movq %rax, %r11 + + /* Restore all arguments */ + movdqa -0x90(%rbp), %xmm3 + movdqa -0x80(%rbp), %xmm2 + movdqa -0x70(%rbp), %xmm1 + movdqa -0x60(%rbp), %xmm0 + movq -0x48(%rbp), %r9 + movq -0x40(%rbp), %r8 + movq -0x38(%rbp), %rdx + movq -0x30(%rbp), %rcx + movq -0x28(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmpq *%r11 + +0: + movq -0x30(%rbp), %rcx + movq -0x38(%rbp), %rdx + + movq %rbp, %rsp + popq %rbp + + jmp of_method_not_found + +of_forward_stret: + pushq %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0x90, %rsp /* 16-byte alignment */ + movq %rax, -0x28(%rbp) + movq %rcx, -0x30(%rbp) + movq %rdx, -0x38(%rbp) + movq %r8, -0x40(%rbp) + movq %r9, -0x48(%rbp) + movdqa %xmm0, -0x60(%rbp) + movdqa %xmm1, -0x70(%rbp) + movdqa %xmm2, -0x80(%rbp) + movdqa %xmm3, -0x90(%rbp) + + movq %rdx, %rcx + call object_getClass + + movq %rax, %rcx + leaq sel_forwardingTargetForSelector_(%rip), %rdx + call class_respondsToSelector + + testq %rax, %rax + jz 0f + + movq -0x38(%rbp), %rcx + leaq sel_forwardingTargetForSelector_(%rip), %rdx + call objc_msg_lookup + + movq -0x38(%rbp), %rcx + leaq sel_forwardingTargetForSelector_(%rip), %rdx + movq -0x40(%rbp), %r8 + call *%rax + + testq %rax, %rax + jz 0f + cmpq -0x38(%rbp), %rax + je 0f + + movq %rax, -0x38(%rbp) + + movq %rax, %rcx + movq -0x40(%rbp), %rdx + call objc_msg_lookup_stret@PLT + movq %rax, %r11 + + /* Restore all arguments */ + movdqa -0x90(%rbp), %xmm3 + movdqa -0x80(%rbp), %xmm2 + movdqa -0x70(%rbp), %xmm1 + movdqa -0x60(%rbp), %xmm0 + movq -0x48(%rbp), %r9 + movq -0x40(%rbp), %r8 + movq -0x38(%rbp), %rdx + movq -0x30(%rbp), %rcx + movq -0x28(%rbp), %rax + + movq %rbp, %rsp + popq %rbp + + jmpq *%r11 + +0: + movq -0x30(%rbp), %rcx + movq -0x38(%rbp), %rdx + movq -0x40(%rbp), %r8 + + movq %rbp, %rsp + popq %rbp + + jmp of_method_not_found_stret + +init: + leaq module(%rip), %rcx + jmp __objc_exec_class + +.section .ctors, "aw" + .quad init + +.section .rodata +str_forwardingTargetForSelector_: + .asciz "forwardingTargetForSelector:" + +.section .data +sel_forwardingTargetForSelector_: + .quad str_forwardingTargetForSelector_, 0 + .quad 0, 0 +symtab: + .long 0, 0 + .quad sel_forwardingTargetForSelector_ + .short 0, 0 + .long 0 + .quad 0 +module: + .long 8, 32 + .quad 0, symtab Index: src/forwarding/forwarding.S ================================================================== --- src/forwarding/forwarding.S +++ src/forwarding/forwarding.S @@ -40,9 +40,13 @@ # include "forwarding-ppc-elf.S" # elif (defined(_MIPS_SIM) && _MIPS_SIM == _ABIO32) || \ (defined(__mips_eabi) && _MIPS_SZPTR == 32) # include "forwarding-mips-elf.S" # endif -# elif defined(_WIN32) && defined(__i386__) -# include "forwarding-x86-win32.S" +# elif defined(_WIN32) +# if defined(__x86_64__) +# include "forwarding-amd64-win64.S" +# elif defined(__i386__) +# include "forwarding-x86-win32.S" +# endif # endif #endif Index: tests/ForwardingTests.m ================================================================== --- tests/ForwardingTests.m +++ tests/ForwardingTests.m @@ -208,12 +208,18 @@ : -1 : 1.25 : 2.75] == 0x12345678) TEST(@"-[forwardingTargetForSelector:] variable arguments", [([t forwardingTargetVarArgTest: FMT, ARGS]) isEqual: RESULT]) + /* + * Don't try fpret on Win64 if we don't have stret forwarding, as + * long double is handled as a struct there. + */ +# if !defined(_WIN64) || defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET) TEST(@"-[forwardingTargetForSelector:] fp return", [t forwardingTargetFPRetTest] == 12345678.00006103515625) +# endif # ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET TEST(@"-[forwardingTargetForSelector:] struct return", !memcmp([t forwardingTargetStRetTest].s, "abcdefghijklmnopqrstuvwxyz", 27)) # endif