mirror of git://gcc.gnu.org/git/gcc.git
decl.c (Has_Thiscall_Convention): New macro.
* 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. * gcc-interface/misc.c (gnat_handle_option): Fix formatting. * gcc-interface/Makefile.in: Likewise. From-SVN: r187676
This commit is contained in:
parent
2a2aa0391e
commit
c80c1ce951
|
@ -50,19 +50,23 @@
|
||||||
#include "ada-tree.h"
|
#include "ada-tree.h"
|
||||||
#include "gigi.h"
|
#include "gigi.h"
|
||||||
|
|
||||||
/* Convention_Stdcall should be processed in a specific way on 32 bits
|
/* "stdcall" and "thiscall" conventions should be processed in a specific way
|
||||||
Windows targets only. The macro below is a helper to avoid having to
|
on 32-bit x86/Windows only. The macros below are helpers to avoid having
|
||||||
check for a Windows specific attribute throughout this unit. */
|
to check for a Windows specific attribute throughout this unit. */
|
||||||
|
|
||||||
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
||||||
#ifdef TARGET_64BIT
|
#ifdef TARGET_64BIT
|
||||||
#define Has_Stdcall_Convention(E) \
|
#define Has_Stdcall_Convention(E) \
|
||||||
(!TARGET_64BIT && Convention (E) == Convention_Stdcall)
|
(!TARGET_64BIT && Convention (E) == Convention_Stdcall)
|
||||||
|
#define Has_Thiscall_Convention(E) \
|
||||||
|
(!TARGET_64BIT && gnat_first_param_is_class (E))
|
||||||
#else
|
#else
|
||||||
#define Has_Stdcall_Convention(E) (Convention (E) == Convention_Stdcall)
|
#define Has_Stdcall_Convention(E) (Convention (E) == Convention_Stdcall)
|
||||||
|
#define Has_Thiscall_Convention(E) (gnat_first_param_is_class (E))
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define Has_Stdcall_Convention(E) 0
|
#define Has_Stdcall_Convention(E) 0
|
||||||
|
#define Has_Thiscall_Convention(E) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Stack realignment is necessary for functions with foreign conventions when
|
/* Stack realignment is necessary for functions with foreign conventions when
|
||||||
|
@ -126,6 +130,7 @@ DEF_VEC_ALLOC_O(variant_desc,heap);
|
||||||
static GTY ((if_marked ("tree_int_map_marked_p"),
|
static GTY ((if_marked ("tree_int_map_marked_p"),
|
||||||
param_is (struct tree_int_map))) htab_t annotate_value_cache;
|
param_is (struct tree_int_map))) htab_t annotate_value_cache;
|
||||||
|
|
||||||
|
static bool gnat_first_param_is_class (Entity_Id) ATTRIBUTE_UNUSED;
|
||||||
static bool allocatable_size_p (tree, bool);
|
static bool allocatable_size_p (tree, bool);
|
||||||
static void prepend_one_attribute_to (struct attrib **,
|
static void prepend_one_attribute_to (struct attrib **,
|
||||||
enum attr_type, tree, tree, Node_Id);
|
enum attr_type, tree, tree, Node_Id);
|
||||||
|
@ -4403,6 +4408,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|
||||||
(&attr_list, ATTR_MACHINE_ATTRIBUTE,
|
(&attr_list, ATTR_MACHINE_ATTRIBUTE,
|
||||||
get_identifier ("stdcall"), NULL_TREE,
|
get_identifier ("stdcall"), NULL_TREE,
|
||||||
gnat_entity);
|
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
|
/* If we should request stack realignment for a foreign convention
|
||||||
subprogram, do so. Note that this applies to task entry points in
|
subprogram, do so. Note that this applies to task entry points in
|
||||||
|
@ -5266,6 +5276,10 @@ get_minimal_subprog_decl (Entity_Id gnat_entity)
|
||||||
prepend_one_attribute_to (&attr_list, ATTR_MACHINE_ATTRIBUTE,
|
prepend_one_attribute_to (&attr_list, ATTR_MACHINE_ATTRIBUTE,
|
||||||
get_identifier ("stdcall"), NULL_TREE,
|
get_identifier ("stdcall"), NULL_TREE,
|
||||||
gnat_entity);
|
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)
|
if (No (Interface_Name (gnat_entity)) && gnu_ext_name == gnu_entity_name)
|
||||||
gnu_ext_name = NULL_TREE;
|
gnu_ext_name = NULL_TREE;
|
||||||
|
@ -5275,6 +5289,63 @@ get_minimal_subprog_decl (Entity_Id gnat_entity)
|
||||||
false, true, true, true, attr_list, gnat_entity);
|
false, true, true, true, attr_list, gnat_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
/* Finalize the processing of From_With_Type incomplete types. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue