summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-19 09:34:06 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-19 09:34:06 +0000
commit54b6d55e2a681d419e01391f88c7fa81e111ad35 (patch)
tree06b9e25509fedd2c6a3eceb26b5663720ec58535
parent4cff7dce115e891c0c4672c788a5aa033e1152f9 (diff)
downloadgcc-54b6d55e2a681d419e01391f88c7fa81e111ad35.tar.gz
2012-05-19 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (Has_Thiscall_Convention): New macro. (gnat_to_gnu_entity) <E_Subprogram_Type>: Test it to set the thiscall calling convention (get_minimal_subprog_decl): Likewise. (gnat_first_param_is_class): New predicate. Backport from mainline 2012-05-15 Javier Miranda <miranda@adacore.com> * exp_ch3.adb (Build_Offset_To_Top): Modify the expansion of the offset_to_top functions to ensure that their profile is conformant with the profile specified in Ada.Tags. No change in functionality. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@187677 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ada/ChangeLog16
-rw-r--r--gcc/ada/exp_ch3.adb26
-rw-r--r--gcc/ada/gcc-interface/decl.c77
3 files changed, 111 insertions, 8 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 293ee33a71a..abc566858a3 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,19 @@
+2012-05-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (Has_Thiscall_Convention): New macro.
+ (gnat_to_gnu_entity) <E_Subprogram_Type>: Test it to set the thiscall
+ calling convention
+ (get_minimal_subprog_decl): Likewise.
+ (gnat_first_param_is_class): New predicate.
+
+ Backport from mainline
+ 2012-05-15 Javier Miranda <miranda@adacore.com>
+
+ * exp_ch3.adb (Build_Offset_To_Top): Modify the
+ expansion of the offset_to_top functions to ensure that their
+ profile is conformant with the profile specified in Ada.Tags. No
+ change in functionality.
+
2012-05-18 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity) <object>: For an object at
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index d1865038361..0feaaf30f6d 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -1883,9 +1883,10 @@ package body Exp_Ch3 is
procedure Build_Offset_To_Top_Function (Iface_Comp : Entity_Id);
-- Generate:
- -- function Fxx (O : in Rec_Typ) return Storage_Offset is
+ -- function Fxx (O : Address) return Storage_Offset is
+ -- type Acc is access all <Typ>;
-- begin
- -- return O.Iface_Comp'Position;
+ -- return Acc!(O).Iface_Comp'Position;
-- end Fxx;
----------------------------------
@@ -1896,6 +1897,7 @@ package body Exp_Ch3 is
Body_Node : Node_Id;
Func_Id : Entity_Id;
Spec_Node : Node_Id;
+ Acc_Type : Entity_Id;
begin
Func_Id := Make_Temporary (Loc, 'F');
@@ -1912,7 +1914,7 @@ package body Exp_Ch3 is
Make_Defining_Identifier (Loc, Name_uO),
In_Present => True,
Parameter_Type =>
- New_Reference_To (Rec_Type, Loc))));
+ New_Reference_To (RTE (RE_Address), Loc))));
Set_Result_Definition (Spec_Node,
New_Reference_To (RTE (RE_Storage_Offset), Loc));
@@ -1924,7 +1926,19 @@ package body Exp_Ch3 is
Body_Node := New_Node (N_Subprogram_Body, Loc);
Set_Specification (Body_Node, Spec_Node);
- Set_Declarations (Body_Node, New_List);
+
+ Acc_Type := Make_Temporary (Loc, 'T');
+ Set_Declarations (Body_Node, New_List (
+ Make_Full_Type_Declaration (Loc,
+ Defining_Identifier => Acc_Type,
+ Type_Definition =>
+ Make_Access_To_Object_Definition (Loc,
+ All_Present => True,
+ Null_Exclusion_Present => False,
+ Constant_Present => False,
+ Subtype_Indication =>
+ New_Reference_To (Rec_Type, Loc)))));
+
Set_Handled_Statement_Sequence (Body_Node,
Make_Handled_Sequence_Of_Statements (Loc,
Statements => New_List (
@@ -1933,7 +1947,9 @@ package body Exp_Ch3 is
Make_Attribute_Reference (Loc,
Prefix =>
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uO),
+ Prefix =>
+ Unchecked_Convert_To (Acc_Type,
+ Make_Identifier (Loc, Name_uO)),
Selector_Name =>
New_Reference_To (Iface_Comp, Loc)),
Attribute_Name => Name_Position)))));
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 122fdd397ed..1fae317f99c 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -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 && gnat_first_param_is_class (E))
#else
#define Has_Stdcall_Convention(E) (Convention (E) == Convention_Stdcall)
+#define Has_Thiscall_Convention(E) (gnat_first_param_is_class (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
@@ -140,6 +144,7 @@ enum alias_set_op
static void relate_alias_sets (tree, tree, enum alias_set_op);
+static bool gnat_first_param_is_class (Entity_Id) ATTRIBUTE_UNUSED;
static bool allocatable_size_p (tree, bool);
static void prepend_one_attribute_to (struct attrib **,
enum attr_type, tree, tree, Node_Id);
@@ -4410,6 +4415,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
(&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
@@ -5290,6 +5300,10 @@ get_minimal_subprog_decl (Entity_Id gnat_entity)
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;
@@ -5338,6 +5352,63 @@ rest_of_type_decl_compilation_no_defer (tree decl)
}
}
+/* Return whether the E_Subprogram_Type/E_Function/E_Procedure GNAT_ENTITY has
+ a first parameter with a class or equivalent type.
+
+ 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
+ the one set for C++ methods (functions with METHOD_TYPE) by the back-end.
+ Now in Ada primitive operations are regular subprograms (e.g. you can have
+ common pointers to both) so we cannot compute an equivalent of METHOD_TYPE
+ and so we set the calling convention in an uniform way. */
+
+static bool
+gnat_first_param_is_class (Entity_Id gnat_entity)
+{
+ Entity_Id gnat_param = First_Formal_With_Extras (gnat_entity);
+ Entity_Id gnat_type;
+ Node_Id node;
+
+ if (No (gnat_param))
+ return false;
+
+ gnat_type = Underlying_Type (Etype (gnat_param));
+
+ /* This is the main case. Note that we must return the same value for
+ regular tagged types and CW types since dispatching calls have a CW
+ type on the caller side and a tagged type on the callee side. */
+ if (Is_Tagged_Type (gnat_type))
+ 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_CPP_Class (gnat_type))
+ return True;
+
+ /* The language-level "protected" calling convention doesn't distinguish
+ tagged protected types from non-tagged protected types (e.g. you can
+ have common pointers to both) so we must use a single low-level calling
+ convention for it. Since tagged protected types can be derived from
+ simple limited interfaces, we need to pick the calling convention of
+ the latters. */
+ if (Is_Protected_Record_Type (gnat_type))
+ return True;
+
+ /* If this is the special E_Subprogram_Type built for the declaration of
+ an access to protected subprogram type, the first parameter will have
+ type Address, but we must return true to be consistent with above. */
+ if (Is_Itype (gnat_entity)
+ && Present (node = Associated_Node_For_Itype (gnat_entity))
+ && Nkind (node) == N_Full_Type_Declaration
+ && Ekind (Defining_Identifier (node)) == E_Access_Subprogram_Type
+ && Present (node = Original_Access_Type (Defining_Identifier (node)))
+ && (Ekind (node) == E_Access_Protected_Subprogram_Type
+ || Ekind (node) == E_Anonymous_Access_Protected_Subprogram_Type))
+ return True;
+
+ return False;
+}
+
/* Finalize the processing of From_With_Type incomplete types. */
void