From patchwork Wed Jan 25 10:40:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai Tietz X-Patchwork-Id: 137727 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 4A4EEB6F68 for ; Wed, 25 Jan 2012 21:41:01 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1328092862; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received:Date:Message-ID:Subject:From:To: Cc:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=Vlr1FsC ybJicCTzH1nFeG6dkI40=; b=rZgROCU6nGE9w3+HCUKjk/EJmn0mwlwyDr5H0+A d+l44dtrpMWEZYULNlnpePZpzqwy8in9IfC5V1mUQQaWqvaScUGSkT71onkqHVS7 Q2kMLT1sGES9vQWjx/Na1ekBO7Xg3nbiFQaSgTCOTbtmhuPw9qZI/IM3sFgJXApF JuzE= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:MIME-Version:Received:Received:Date:Message-ID:Subject:From:To:Cc:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=xeWh/ZUyVZ61eE2ofNPLe8o1mWTa3kgRhUscuUcP4rxwnhivGUQ3Ok8Fmzdcxu aWRZIilymLH+Ej6R4xfJhWwRqXqVKRvRGCy2LY9Wmlxwwv+ngyCLEj/qa5KGbggi hdnCR4UgnN3kGtU7eaMzZxVHHizq/X69QBviJDl1tSAS4=; Received: (qmail 6044 invoked by alias); 25 Jan 2012 10:40:57 -0000 Received: (qmail 6034 invoked by uid 22791); 25 Jan 2012 10:40:56 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_BF, TW_JN, TW_OV X-Spam-Check-By: sourceware.org Received: from mail-tul01m020-f175.google.com (HELO mail-tul01m020-f175.google.com) (209.85.214.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 25 Jan 2012 10:40:42 +0000 Received: by obbuo9 with SMTP id uo9so6088091obb.20 for ; Wed, 25 Jan 2012 02:40:41 -0800 (PST) MIME-Version: 1.0 Received: by 10.182.5.198 with SMTP id u6mr15284819obu.14.1327488041523; Wed, 25 Jan 2012 02:40:41 -0800 (PST) Received: by 10.182.60.232 with HTTP; Wed, 25 Jan 2012 02:40:41 -0800 (PST) Date: Wed, 25 Jan 2012 11:40:41 +0100 Message-ID: Subject: [patch libffi]: Add support for fastcall/thiscall to x86 variant of libffi for PR 51500 From: Kai Tietz To: GCC Patches Cc: Andrew Haley X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello, this patch adds required support for thiscall/fastcall calling-convention of x86 Windows. It is a prerequisit for fixing PR libgcj/51500 for 32-bit Windows. The default-calling-convention for C++ none-static and none-variadic class-members is changed by 4.7 to thiscall as described by vendors ABI defintion. 2012-01-25 Kai Tietz * src/libffi/src/x86/ffi.c (ffi_call_win32): Add new argument to prototype for specify calling-convention. (ffi_call): Add support for stdcall/thiscall convention. (ffi_raw_call): Likewise. * src/x86/ffitarget.h (ffi_abi): Add FFI_THISCALL and FFI_FASTCALL. * src/x86/win32.S (_ffi_call_win32): Add support for fastcall/thiscall calling-convention calls. Tested for i686-w64-mingw32 and i686-pc-cygwin. Ok for apply? Regards, Kai ChangeLog 2012-01-25 Kai Tietz * src/libffi/src/x86/ffi.c (ffi_call_win32): Add new argument to prototype for specify calling-convention. (ffi_call): Add support for stdcall/thiscall convention. (ffi_raw_call): Likewise. * src/x86/ffitarget.h (ffi_abi): Add FFI_THISCALL and FFI_FASTCALL. * src/x86/win32.S (_ffi_call_win32): Add support for fastcall/thiscall calling-convention calls. Index: gcc/libffi/src/x86/ffi.c =================================================================== --- gcc.orig/libffi/src/x86/ffi.c +++ gcc/libffi/src/x86/ffi.c @@ -252,7 +252,7 @@ ffi_call_win64(void (*)(char *, extended #elif defined(X86_WIN32) extern void ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); + unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); #else extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); @@ -316,8 +316,23 @@ void ffi_call(ffi_cif *cif, void (*fn)(v #elif defined(X86_WIN32) case FFI_SYSV: case FFI_STDCALL: - ffi_call_win32(ffi_prep_args, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); + case FFI_THISCALL: + case FFI_FASTCALL: + { + unsigned int abi = cif->abi; + size_t sz = 0; + unsigned int i; + + for (i=0; i < cif->nargs && sz < 8;i++) + sz += (cif->arg_types[i]->size + 3) & ~3; + if (sz <= 4 && cif->nargs <= 1 + && abi == FFI_FASTCALL) + abi = FFI_THISCALL; + if (!sz && cif->nargs == 0 && abi == FFI_THISCALL) + abi = FFI_STDCALL; + ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags, + ecif.rvalue, fn); + } break; #else case FFI_SYSV: @@ -644,8 +659,22 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(vo #ifdef X86_WIN32 case FFI_SYSV: case FFI_STDCALL: - ffi_call_win32(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); + case FFI_THISCALL: + case FFI_FASTCALL: + { + unsigned int abi = cif->abi; + size_t sz = 0; + unsigned int i; + + for (i=0; i < cif->nargs && sz < 8;i++) + sz += (cif->arg_types[i]->size + 3) & ~3; + if (sz <= 4 && cif->nargs < 2 && abi == FFI_FASTCALL) + abi = FFI_THISCALL; + if (!sz && cif->nargs == 0 && abi == FFI_THISCALL) + abi = FFI_STDCALL; + ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags, + ecif.rvalue, fn); + } break; #else case FFI_SYSV: Index: gcc/libffi/src/x86/ffitarget.h =================================================================== --- gcc.orig/libffi/src/x86/ffitarget.h +++ gcc/libffi/src/x86/ffitarget.h @@ -64,6 +64,8 @@ typedef enum ffi_abi { #ifdef X86_WIN32 FFI_SYSV, FFI_STDCALL, + FFI_THISCALL, + FFI_FASTCALL, /* TODO: Add fastcall support for the sake of completeness */ FFI_DEFAULT_ABI = FFI_SYSV, #endif Index: gcc/libffi/src/x86/win32.S =================================================================== --- gcc.orig/libffi/src/x86/win32.S +++ gcc/libffi/src/x86/win32.S @@ -45,6 +45,7 @@ _TEXT SEGMENT ffi_call_win32 PROC NEAR, ffi_prep_args : NEAR PTR DWORD, ecif : NEAR PTR DWORD, + cif_abi : DWORD, cif_bytes : DWORD, cif_flags : DWORD, rvalue : NEAR PTR DWORD, @@ -64,6 +65,19 @@ ffi_call_win32 PROC NEAR, ;; Return stack to previous state and call the function add esp, 8 + ;; Handle thiscall and fastcall + cmp cif_abi, 3 ;; FFI_THISCALL + jz do_thiscall + cmp cif_abi, 4 ;; FFI_FASTCALL + jnz do_stdcall + mov ecx, DWORD PTR [esp] + mov edx, DWORD PTR [esp+4] + add esp, 8 + jmp do_stdcall +do_thiscall: + mov ecx, DWORD PTR [esp] + add esp, 4 +do_stdcall: call fn ;; cdecl: we restore esp in the epilogue, so there's no need to @@ -405,7 +419,7 @@ _ffi_call_win32: movl %esp,%ebp .LCFI1: # Make room for all of the new args. - movl 16(%ebp),%ecx + movl 20(%ebp),%ecx subl %ecx,%esp movl %esp,%eax @@ -417,19 +431,34 @@ _ffi_call_win32: # Return stack to previous state and call the function addl $8,%esp - + + # Handle fastcall and thiscall + cmpl $3, 16(%ebp) # FFI_THISCALL + jz .do_thiscall + cmpl $4, 16(%ebp) # FFI_FASTCALL + jnz .do_fncall + movl (%esp), %ecx + movl 4(%esp), %edx + addl $8, %esp + jmp .do_fncall +.do_thiscall: + movl (%esp), %ecx + addl $4, %esp + +.do_fncall: + # FIXME: Align the stack to a 128-bit boundary to avoid # potential performance hits. - call *28(%ebp) + call *32(%ebp) # stdcall functions pop arguments off the stack themselves # Load %ecx with the return type code - movl 20(%ebp),%ecx + movl 24(%ebp),%ecx # If the return value pointer is NULL, assume no return value. - cmpl $0,24(%ebp) + cmpl $0,28(%ebp) jne 0f # Even if there is no space for the return value, we are @@ -488,50 +517,50 @@ _ffi_call_win32: .Lretint: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movl %eax,0(%ecx) jmp .Lepilogue .Lretfloat: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx fstps (%ecx) jmp .Lepilogue .Lretdouble: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx fstpl (%ecx) jmp .Lepilogue .Lretlongdouble: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx fstpt (%ecx) jmp .Lepilogue .Lretint64: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movl %eax,0(%ecx) movl %edx,4(%ecx) jmp .Lepilogue .Lretstruct1b: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movb %al,0(%ecx) jmp .Lepilogue .Lretstruct2b: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movw %ax,0(%ecx) jmp .Lepilogue .Lretstruct4b: # Load %ecx with the pointer to storage for the return value - movl 24(%ebp),%ecx + movl 28(%ebp),%ecx movl %eax,0(%ecx) jmp .Lepilogue