From patchwork Sun Apr 10 07:01:29 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai Tietz X-Patchwork-Id: 90498 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 A2A561007D1 for ; Sun, 10 Apr 2011 17:53:35 +1000 (EST) Received: (qmail 30142 invoked by alias); 10 Apr 2011 07:53:31 -0000 Received: (qmail 30125 invoked by uid 22791); 10 Apr 2011 07:53:28 -0000 X-SWARE-Spam-Status: No, hits=-0.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RFC_ABUSE_POST, SPF_NEUTRAL, TW_FN X-Spam-Check-By: sourceware.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (140.186.70.92) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 10 Apr 2011 07:53:23 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q8orR-0001YI-CJ for gcc-patches@gcc.gnu.org; Sun, 10 Apr 2011 03:15:07 -0400 Received: from mail-qy0-f175.google.com ([209.85.216.175]:57434) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q8orR-0001Xp-6X for gcc-patches@gcc.gnu.org; Sun, 10 Apr 2011 03:15:05 -0400 Received: by qyk35 with SMTP id 35so694407qyk.20 for ; Sun, 10 Apr 2011 00:11:30 -0700 (PDT) MIME-Version: 1.0 Received: by 10.224.211.200 with SMTP id gp8mr3261810qab.76.1302418889919; Sun, 10 Apr 2011 00:01:29 -0700 (PDT) Received: by 10.229.97.206 with HTTP; Sun, 10 Apr 2011 00:01:29 -0700 (PDT) In-Reply-To: References: <4D9F79B0.5010900@redhat.com> Date: Sun, 10 Apr 2011 09:01:29 +0200 Message-ID: Subject: Re: [patch i386]: Cleanup calling convention handling in i386.c and fix PR target/9601 and PR target/11772 From: Kai Tietz To: Richard Henderson Cc: GCC Patches X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.216.175 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 I had introduced an const issue by recent patch. Attached patch fixes that. Kai Index: gcc/gcc/config/i386/i386-protos.h =================================================================== --- gcc.orig/gcc/config/i386/i386-protos.h 2011-04-08 16:00:16.264411500 +0200 +++ gcc/gcc/config/i386/i386-protos.h 2011-04-09 12:38:15.360805300 +0200 @@ -191,6 +191,8 @@ extern tree ix86_handle_shared_attribute extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *); extern int x86_field_alignment (tree, int); extern tree ix86_valid_target_attribute_tree (tree); +extern unsigned int ix86_get_callcvt (const_tree); + #endif extern rtx ix86_tls_get_addr (void); Index: gcc/gcc/config/i386/i386.c =================================================================== --- gcc.orig/gcc/config/i386/i386.c 2011-04-08 16:00:16.272411500 +0200 +++ gcc/gcc/config/i386/i386.c 2011-04-09 19:31:13.991227800 +0200 @@ -5312,7 +5312,7 @@ ix86_handle_cconv_attribute (tree *node, return NULL_TREE; } - /* Can combine regparm with all attributes but fastcall. */ + /* Can combine regparm with all attributes but fastcall, and thiscall. */ if (is_attribute_p ("regparm", name)) { tree cst; @@ -5436,38 +5436,54 @@ ix86_handle_cconv_attribute (tree *node, return NULL_TREE; } -/* This function checks if the method-function has default __thiscall - calling-convention for 32-bit msabi. - It returns true if TYPE is of kind METHOD_TYPE, no stdarg function, - and the MS_ABI 32-bit is used. Otherwise it returns false. */ +/* This function determines from TYPE the calling-convention. */ -static bool -ix86_is_msabi_thiscall (const_tree type) +unsigned int +ix86_get_callcvt (const_tree type) { - if (TARGET_64BIT || ix86_function_type_abi (type) != MS_ABI - || TREE_CODE (type) != METHOD_TYPE || stdarg_p (type)) - return false; - /* Check for different calling-conventions. */ - if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (type)) - || lookup_attribute ("stdcall", TYPE_ATTRIBUTES (type)) - || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)) - || lookup_attribute ("regparm", TYPE_ATTRIBUTES (type)) - || lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type))) - return false; - return true; -} + unsigned int ret = 0; + bool is_stdarg; + tree attrs; -/* This function checks if the thiscall attribute is set for the TYPE, - or if it is an method-type with default thiscall convention. - It returns true if function match, otherwise false is returned. */ + if (TARGET_64BIT) + return IX86_CALLCVT_CDECL; -static bool -ix86_is_type_thiscall (const_tree type) -{ - if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type)) - || ix86_is_msabi_thiscall (type)) - return true; - return false; + attrs = TYPE_ATTRIBUTES (type); + if (attrs != NULL_TREE) + { + if (lookup_attribute ("cdecl", attrs)) + ret |= IX86_CALLCVT_CDECL; + else if (lookup_attribute ("stdcall", attrs)) + ret |= IX86_CALLCVT_STDCALL; + else if (lookup_attribute ("fastcall", attrs)) + ret |= IX86_CALLCVT_FASTCALL; + else if (lookup_attribute ("thiscall", attrs)) + ret |= IX86_CALLCVT_THISCALL; + + /* Regparam isn't allowed for thiscall and fastcall. */ + if ((ret & (IX86_CALLCVT_THISCALL | IX86_CALLCVT_FASTCALL)) == 0) + { + if (lookup_attribute ("regparm", attrs)) + ret |= IX86_CALLCVT_REGPARM; + if (lookup_attribute ("sseregparm", attrs)) + ret |= IX86_CALLCVT_SSEREGPARM; + } + + if (IX86_BASE_CALLCVT(ret) != 0) + return ret; + } + + is_stdarg = stdarg_p (type); + if (TARGET_RTD && !is_stdarg) + return IX86_CALLCVT_STDCALL | ret; + + if (ret != 0 + || is_stdarg + || TREE_CODE (type) != METHOD_TYPE + || ix86_function_type_abi (type) != MS_ABI) + return IX86_CALLCVT_CDECL | ret; + + return IX86_CALLCVT_THISCALL; } /* Return 0 if the attributes for two types are incompatible, 1 if they @@ -5477,43 +5493,18 @@ ix86_is_type_thiscall (const_tree type) static int ix86_comp_type_attributes (const_tree type1, const_tree type2) { - /* Check for mismatch of non-default calling convention. */ - bool is_thiscall = ix86_is_msabi_thiscall (type1); - const char *const rtdstr = TARGET_RTD ? (is_thiscall ? "thiscall" : "cdecl") : "stdcall"; + unsigned int ccvt1, ccvt2; if (TREE_CODE (type1) != FUNCTION_TYPE && TREE_CODE (type1) != METHOD_TYPE) return 1; - /* Check for mismatched fastcall/regparm types. */ - if ((!lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type1)) - != !lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type2))) - || (ix86_function_regparm (type1, NULL) - != ix86_function_regparm (type2, NULL))) - return 0; - - /* Check for mismatched sseregparm types. */ - if (!lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type1)) - != !lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type2))) + ccvt1 = ix86_get_callcvt (type1); + ccvt2 = ix86_get_callcvt (type2); + if (ccvt1 != ccvt2) return 0; - - /* Check for mismatched thiscall types. */ - if (is_thiscall && !TARGET_RTD) - { - if (!lookup_attribute ("cdecl", TYPE_ATTRIBUTES (type1)) - != !lookup_attribute ("cdecl", TYPE_ATTRIBUTES (type2))) - return 0; - } - else if (!is_thiscall || TARGET_RTD) - { - if (!lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type1)) - != !lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type2))) - return 0; - } - - /* Check for mismatched return types (cdecl vs stdcall). */ - if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1)) - != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2))) + if (ix86_function_regparm (type1, NULL) + != ix86_function_regparm (type2, NULL)) return 0; return 1; @@ -5528,23 +5519,26 @@ ix86_function_regparm (const_tree type, { tree attr; int regparm; + unsigned int ccvt; if (TARGET_64BIT) return (ix86_function_type_abi (type) == SYSV_ABI ? X86_64_REGPARM_MAX : X86_64_MS_REGPARM_MAX); - + ccvt = ix86_get_callcvt (type); regparm = ix86_regparm; - attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type)); - if (attr) + + if ((ccvt & IX86_CALLCVT_REGPARM) != 0) { - regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))); - return regparm; + attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type)); + if (attr) + { + regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))); + return regparm; + } } - - if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type))) + else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0) return 2; - - if (ix86_is_type_thiscall (type)) + else if ((ccvt & IX86_CALLCVT_THISCALL) != 0) return 1; /* Use register calling convention for local functions when possible. */ @@ -5695,27 +5689,18 @@ ix86_keep_aggregate_return_pointer (tree static int ix86_return_pops_args (tree fundecl, tree funtype, int size) { - int rtd; + unsigned int ccvt; /* None of the 64-bit ABIs pop arguments. */ if (TARGET_64BIT) return 0; - rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE); + ccvt = ix86_get_callcvt (funtype); - /* Cdecl functions override -mrtd, and never pop the stack. */ - if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) - { - /* Stdcall and fastcall functions will pop the stack if not - variable args. */ - if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)) - || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)) - || ix86_is_type_thiscall (funtype)) - rtd = 1; - - if (rtd && ! stdarg_p (funtype)) - return size; - } + if ((ccvt & (IX86_CALLCVT_STDCALL | IX86_CALLCVT_FASTCALL + | IX86_CALLCVT_THISCALL)) != 0 + && ! stdarg_p (funtype)) + return size; /* Lose any fake structure return argument if it is passed on the stack. */ if (aggregate_value_p (TREE_TYPE (funtype), fundecl) @@ -5818,7 +5803,7 @@ ix86_reg_parm_stack_space (const_tree fn enum calling_abi ix86_function_type_abi (const_tree fntype) { - if (fntype != NULL) + if (fntype != NULL_TREE && TYPE_ATTRIBUTES (fntype) != NULL_TREE) { enum calling_abi abi = ix86_abi; if (abi == SYSV_ABI) @@ -6048,12 +6033,13 @@ init_cumulative_args (CUMULATIVE_ARGS *c else look for regparm information. */ if (fntype) { - if (ix86_is_type_thiscall (fntype)) + unsigned int ccvt = ix86_get_callcvt (fntype); + if ((ccvt & IX86_CALLCVT_THISCALL) != 0) { cum->nregs = 1; cum->fastcall = 1; /* Same first register as in fastcall. */ } - else if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype))) + else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0) { cum->nregs = 2; cum->fastcall = 1; @@ -9839,13 +9825,13 @@ find_drap_reg (void) /* Reuse static chain register if it isn't used for parameter passing. */ - if (ix86_function_regparm (TREE_TYPE (decl), decl) <= 2 - && !lookup_attribute ("fastcall", - TYPE_ATTRIBUTES (TREE_TYPE (decl))) - && !ix86_is_type_thiscall (TREE_TYPE (decl))) - return CX_REG; - else - return DI_REG; + if (ix86_function_regparm (TREE_TYPE (decl), decl) <= 2) + { + unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl)); + if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) == 0) + return CX_REG; + } + return DI_REG; } } @@ -23282,20 +23268,19 @@ ix86_static_chain (const_tree fndecl, bo else { tree fntype; + unsigned int ccvt; + /* By default in 32-bit mode we use ECX to pass the static chain. */ regno = CX_REG; fntype = TREE_TYPE (fndecl); - if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype))) + ccvt = ix86_get_callcvt (fntype); + if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0) { /* Fastcall functions use ecx/edx for arguments, which leaves - us with EAX for the static chain. */ - regno = AX_REG; - } - else if (ix86_is_type_thiscall (fntype)) - { - /* Thiscall functions use ecx for arguments, which leaves - us with EAX for the static chain. */ + us with EAX for the static chain. + Thiscall functions use ecx for arguments, which also + leaves us with EAX for the static chain. */ regno = AX_REG; } else if (ix86_function_regparm (fntype, fndecl) == 3) @@ -29846,10 +29831,11 @@ x86_this_parameter (tree function) if (nregs > 0 && !stdarg_p (type)) { int regno; + unsigned int ccvt = ix86_get_callcvt (type); - if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type))) + if ((ccvt & IX86_CALLCVT_FASTCALL) != 0) regno = aggr ? DX_REG : CX_REG; - else if (ix86_is_type_thiscall (type)) + else if ((ccvt & IX86_CALLCVT_THISCALL) != 0) { regno = CX_REG; if (aggr) @@ -29966,9 +29952,8 @@ x86_output_mi_thunk (FILE *file, else { int tmp_regno = CX_REG; - if (lookup_attribute ("fastcall", - TYPE_ATTRIBUTES (TREE_TYPE (function))) - || ix86_is_type_thiscall (TREE_TYPE (function))) + unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (function)); + if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0) tmp_regno = AX_REG; tmp = gen_rtx_REG (SImode, tmp_regno); } Index: gcc/gcc/config/i386/i386.h =================================================================== --- gcc.orig/gcc/config/i386/i386.h 2011-04-08 16:00:16.274411500 +0200 +++ gcc/gcc/config/i386/i386.h 2011-04-09 12:38:15.444810100 +0200 @@ -2368,6 +2368,18 @@ extern void debug_dispatch_window (int); ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_BMI) +/* Flags returned by ix86_get_callcvt (). */ +#define IX86_CALLCVT_CDECL 0x1 +#define IX86_CALLCVT_STDCALL 0x2 +#define IX86_CALLCVT_FASTCALL 0x4 +#define IX86_CALLCVT_THISCALL 0x8 +#define IX86_CALLCVT_REGPARM 0x10 +#define IX86_CALLCVT_SSEREGPARM 0x20 + +#define IX86_BASE_CALLCVT(FLAGS) \ + ((FLAGS) & (IX86_CALLCVT_CDECL | IX86_CALLCVT_STDCALL \ + | IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) + /* Local variables: version-control: t Index: gcc/gcc/config/i386/netware.c =================================================================== --- gcc.orig/gcc/config/i386/netware.c 2011-04-08 16:00:16.279411500 +0200 +++ gcc/gcc/config/i386/netware.c 2011-04-09 12:46:52.578388500 +0200 @@ -148,12 +148,20 @@ i386_nlm_maybe_mangle_decl_assembler_nam { tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); tree new_id; + unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl)); - if (lookup_attribute ("stdcall", type_attributes)) - new_id = gen_stdcall_or_fastcall_decoration (decl, id, '_'); - else if (lookup_attribute ("fastcall", type_attributes)) + if ((ccvt & IX86_CALLCVT_STDCALL) != 0) + { + if (TARGET_RTD) + /* If we are using -mrtd emit undecorated symbol and let linker + do the proper resolving. */ + return NULL_TREE; + new_id = gen_stdcall_or_fastcall_decoration (decl, id, '_'); + } + else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0) new_id = gen_stdcall_or_fastcall_decoration (decl, id, FASTCALL_PREFIX); - else if ((new_id = lookup_attribute ("regparm", type_attributes))) + else if ((cvt & IX86_CALLCVT_REGPARM) != 0 + && (new_id = lookup_attribute ("regparm", type_attributes))) new_id = gen_regparm_prefix (decl, id, TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (new_id)))); else Index: gcc/gcc/config/i386/winnt.c =================================================================== --- gcc.orig/gcc/config/i386/winnt.c 2011-04-08 16:00:16.328411500 +0200 +++ gcc/gcc/config/i386/winnt.c 2011-04-09 12:48:32.982131200 +0200 @@ -170,7 +170,7 @@ gen_stdcall_or_fastcall_suffix (tree dec HOST_WIDE_INT total = 0; const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl)); char *new_str, *p; - tree type = TREE_TYPE (decl); + tree type = TREE_TYPE (DECL_ORIGIN (decl)); tree arg; function_args_iterator args_iter; @@ -202,7 +202,8 @@ gen_stdcall_or_fastcall_suffix (tree dec / parm_boundary_bytes * parm_boundary_bytes); total += parm_size; } - } + } + /* Assume max of 8 base 10 digits in the suffix. */ p = new_str = XALLOCAVEC (char, 1 + strlen (old_str) + 1 + 8 + 1); if (fastcall) @@ -222,10 +223,16 @@ i386_pe_maybe_mangle_decl_assembler_name if (TREE_CODE (decl) == FUNCTION_DECL) { - tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); - if (lookup_attribute ("stdcall", type_attributes)) - new_id = gen_stdcall_or_fastcall_suffix (decl, id, false); - else if (lookup_attribute ("fastcall", type_attributes)) + unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl)); + if ((ccvt & IX86_CALLCVT_STDCALL) != 0) + { + if (TARGET_RTD) + /* If we are using -mrtd emit undecorated symbol and let linker + do the proper resolving. */ + return NULL_TREE; + new_id = gen_stdcall_or_fastcall_suffix (decl, id, false); + } + else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0) new_id = gen_stdcall_or_fastcall_suffix (decl, id, true); }