From patchwork Tue Jul 3 08:22:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 168733 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 7D7172C00C2 for ; Tue, 3 Jul 2012 18:30:14 +1000 (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=1341909014; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:From:To:Subject:Date:User-Agent:References:In-Reply-To: MIME-Version:Content-Type:Message-Id:Mailing-List:Precedence: List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=xvwNlVWaIbp+8A5KqKS1ML9sx/E=; b=fdDuz5BcES+1/sv yMrWK4ii1ZUD6oVU51SEKwH9JKyaoADhZRSE5NZbbQZ5z4amZ0M6m6or9YhhS7Z1 AGB5BxbveSOBB/9TmSuhRC6CzstNtjqQRkduMI672SxAIOMg2EwUO7hjfhgW4RLc xK99s+uEZr/18WZvs+2uCTUXtiHs= 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:Received:Received:From:To:Subject:Date:User-Agent:References:In-Reply-To:MIME-Version:Content-Type:Message-Id:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=aoKjA4fHeqgKtNzMceSoYF/QqRrGbyq+ah4z79obk1yuYIzNMBim0YcDy60vIG oQNrdcArby5kuZymdxXg4UlZa5PFs2Rx2N0Zf5/tZCZCUf2+Tglzhb+Vk996A0Ky lzoLOkM/ar4KSFmHfpyqYoI1bPen97YG8uqolxtMfLHcg=; Received: (qmail 3536 invoked by alias); 3 Jul 2012 08:30:01 -0000 Received: (qmail 3362 invoked by uid 22791); 3 Jul 2012 08:29:57 -0000 X-SWARE-Spam-Status: No, hits=-2.9 required=5.0 tests=AWL, BAYES_00, KHOP_THREADED X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (194.98.77.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 03 Jul 2012 08:29:35 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id D1B24290046 for ; Tue, 3 Jul 2012 10:29:39 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3ZG4vRkCyq4K for ; Tue, 3 Jul 2012 10:29:39 +0200 (CEST) Received: from [192.168.1.2] (bon31-6-88-161-99-133.fbx.proxad.net [88.161.99.133]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id 48F56290022 for ; Tue, 3 Jul 2012 10:29:39 +0200 (CEST) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: Re: [Ada] Use C++-compatible calling convention on x86/Windows Date: Tue, 3 Jul 2012 10:22:13 +0200 User-Agent: KMail/1.9.9 References: <201205191129.23652.ebotcazou@adacore.com> <201206131531.08159.ebotcazou@adacore.com> In-Reply-To: <201206131531.08159.ebotcazou@adacore.com> MIME-Version: 1.0 Message-Id: <201207031022.14019.ebotcazou@adacore.com> 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 > Now reverted, including on the 4.7 branch (this is only for x86/Windows). > We have decided to use another approach to deal with the problem as the > above one introduces backwards compatibily issues. This is the new approach, which doesn't require modifications to the source code and essentially replicates the separation between methods and non-methods that doesn't exist in Ada. Tested on i586-suse-linux, applied on mainline and 4.7 branch. 2012-07-03 Eric Botcazou * exp_disp.adb (Expand_Dispatching_Call): Propagate the convention on the designated subprogram type and also set Is_Dispatch_Table_Entity. (Expand_Interface_Thunk): Propagate the convention on the thunk. (Set_CPP_Constructors_Old): Set Is_Constructor and Convention_CPP on the internal view of the constructors. (Set_CPP_Constructors): Likewise. * sem_prag.adb (Analyze_Pragma) : Set the convention on the function. * gcc-interface/gigi.h (is_cplusplus_method): Declare. * gcc-interface/decl.c (Has_Thiscall_Convention): New macro. (gnat_to_gnu_entity) : Test it to set the `thiscall' calling convention (get_minimal_subprog_decl): Likewise. (is_cplusplus_method): New predicate. * gcc-interface/trans.c (Attribute_to_gnu) : Issue an error on access to C++ constructor or member function. Index: sem_prag.adb =================================================================== --- sem_prag.adb (revision 189034) +++ sem_prag.adb (working copy) @@ -7865,6 +7865,7 @@ package body Sem_Prag is Set_Has_Completion (Def_Id); Set_Is_Constructor (Def_Id); + Set_Convention (Def_Id, Convention_CPP); -- Imported C++ constructors are not dispatching primitives -- because in C++ they don't have a dispatch table slot. Index: exp_disp.adb =================================================================== --- exp_disp.adb (revision 189034) +++ exp_disp.adb (working copy) @@ -803,6 +803,11 @@ package body Exp_Disp is Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node); Set_Etype (Subp_Typ, Res_Typ); Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp)); + Set_Convention (Subp_Typ, Convention (Subp)); + + -- Notify gigi that the designated type is a dispatching primitive + + Set_Is_Dispatch_Table_Entity (Subp_Typ); -- Create a new list of parameters which is a copy of the old formal -- list including the creation of a new set of matching entities. @@ -1850,6 +1855,7 @@ package body Exp_Disp is Thunk_Id := Make_Temporary (Loc, 'T'); Set_Is_Thunk (Thunk_Id); + Set_Convention (Thunk_Id, Convention (Prim)); -- Procedure case @@ -8468,8 +8474,9 @@ package body Exp_Disp is Set_Init_Proc (Typ, Init); Set_Is_Imported (Init); + Set_Is_Constructor (Init); Set_Interface_Name (Init, Interface_Name (E)); - Set_Convention (Init, Convention_C); + Set_Convention (Init, Convention_CPP); Set_Is_Public (Init); Set_Has_Completion (Init); end if; @@ -8562,8 +8569,9 @@ package body Exp_Disp is Parameter_Specifications => Parms)); Set_Is_Imported (Constructor_Id); + Set_Is_Constructor (Constructor_Id); Set_Interface_Name (Constructor_Id, Interface_Name (E)); - Set_Convention (Constructor_Id, Convention_C); + Set_Convention (Constructor_Id, Convention_CPP); Set_Is_Public (Constructor_Id); Set_Has_Completion (Constructor_Id); Index: gcc-interface/decl.c =================================================================== --- gcc-interface/decl.c (revision 189034) +++ gcc-interface/decl.c (working copy) @@ -50,19 +50,23 @@ #include "ada-tree.h" #include "gigi.h" -/* Convention_Stdcall should be processed in a specific way on 32 bits - Windows targets only. The macro below is a helper to avoid having to - check for a Windows specific attribute throughout this unit. */ +/* "stdcall" and "thiscall" conventions should be processed in a specific way + on 32-bit x86/Windows only. The macros below are helpers to avoid having + to check for a Windows specific attribute throughout this unit. */ #if TARGET_DLLIMPORT_DECL_ATTRIBUTES #ifdef TARGET_64BIT #define Has_Stdcall_Convention(E) \ (!TARGET_64BIT && Convention (E) == Convention_Stdcall) +#define Has_Thiscall_Convention(E) \ + (!TARGET_64BIT && is_cplusplus_method (E)) #else #define Has_Stdcall_Convention(E) (Convention (E) == Convention_Stdcall) +#define Has_Thiscall_Convention(E) (is_cplusplus_method (E)) #endif #else #define Has_Stdcall_Convention(E) 0 +#define Has_Thiscall_Convention(E) 0 #endif /* Stack realignment is necessary for functions with foreign conventions when @@ -4413,6 +4417,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entit (&attr_list, ATTR_MACHINE_ATTRIBUTE, get_identifier ("stdcall"), NULL_TREE, gnat_entity); + else if (Has_Thiscall_Convention (gnat_entity)) + prepend_one_attribute_to + (&attr_list, ATTR_MACHINE_ATTRIBUTE, + get_identifier ("thiscall"), NULL_TREE, + gnat_entity); /* If we should request stack realignment for a foreign convention subprogram, do so. Note that this applies to task entry points in @@ -5276,6 +5285,10 @@ get_minimal_subprog_decl (Entity_Id gnat prepend_one_attribute_to (&attr_list, ATTR_MACHINE_ATTRIBUTE, get_identifier ("stdcall"), NULL_TREE, gnat_entity); + else if (Has_Thiscall_Convention (gnat_entity)) + prepend_one_attribute_to (&attr_list, ATTR_MACHINE_ATTRIBUTE, + get_identifier ("thiscall"), NULL_TREE, + gnat_entity); if (No (Interface_Name (gnat_entity)) && gnu_ext_name == gnu_entity_name) gnu_ext_name = NULL_TREE; @@ -5285,6 +5298,39 @@ get_minimal_subprog_decl (Entity_Id gnat false, true, true, true, attr_list, gnat_entity); } +/* Return whether the E_Subprogram_Type/E_Function/E_Procedure GNAT_ENTITY is + a C++ imported method or equivalent. + + We use the predicate on 32-bit x86/Windows to find out whether we need to + use the "thiscall" calling convention for GNAT_ENTITY. This convention is + used for C++ methods (functions with METHOD_TYPE) by the back-end. */ + +bool +is_cplusplus_method (Entity_Id gnat_entity) +{ + if (Convention (gnat_entity) != Convention_CPP) + return False; + + /* This is the main case: C++ method imported as a primitive operation. */ + if (Is_Dispatching_Operation (gnat_entity)) + return True; + + /* A thunk needs to be handled like its associated primitive operation. */ + if (Is_Subprogram (gnat_entity) && Is_Thunk (gnat_entity)) + return True; + + /* C++ classes with no virtual functions can be imported as limited + record types, but we need to return true for the constructors. */ + if (Is_Constructor (gnat_entity)) + return True; + + /* This is set on the E_Subprogram_Type built for a dispatching call. */ + if (Is_Dispatch_Table_Entity (gnat_entity)) + return True; + + return False; +} + /* Finalize the processing of From_With_Type incomplete types. */ void Index: gcc-interface/gigi.h =================================================================== --- gcc-interface/gigi.h (revision 189034) +++ gcc-interface/gigi.h (working copy) @@ -116,6 +116,10 @@ extern tree get_unpadded_type (Entity_Id alias is already present, in which case it is returned instead. */ extern tree get_minimal_subprog_decl (Entity_Id gnat_entity); +/* Return whether the E_Subprogram_Type/E_Function/E_Procedure GNAT_ENTITY is + a C++ imported method or equivalent. */ +extern bool is_cplusplus_method (Entity_Id gnat_entity); + /* Create a record type that contains a SIZE bytes long field of TYPE with a starting bit position so that it is aligned to ALIGN bits, and leaving at least ROOM bytes free before the field. BASE_ALIGN is the alignment the Index: gcc-interface/trans.c =================================================================== --- gcc-interface/trans.c (revision 189034) +++ gcc-interface/trans.c (working copy) @@ -1424,6 +1424,15 @@ Attribute_to_gnu (Node_Id gnat_node, tre TREE_NO_TRAMPOLINE (gnu_expr) = TREE_CONSTANT (gnu_expr) = 1; } + /* For 'Access, issue an error message if the prefix is a C++ method + since it can use a special calling convention on some platforms, + which cannot be propagated to the access type. */ + else if (attribute == Attr_Access + && Nkind (Prefix (gnat_node)) == N_Identifier + && is_cplusplus_method (Entity (Prefix (gnat_node)))) + post_error ("access to C++ constructor or member function not allowed", + gnat_node); + /* For other address attributes applied to a nested function, find an inner ADDR_EXPR and annotate it so that we can issue a useful warning with -Wtrampolines. */