mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-31 15:11:04 +08:00
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
@ -2148,7 +2148,7 @@ ifeq ($(strip $(filter-out darwin%,$(osys))),)
|
||||
s-taprop.adb<s-taprop-posix.adb \
|
||||
s-taspri.ads<s-taspri-posix.ads \
|
||||
s-tpopsp.adb<s-tpopsp-posix-foreign.adb
|
||||
|
||||
|
||||
ifeq ($(strip $(filter-out %86,$(arch))),)
|
||||
LIBGNAT_TARGET_PAIRS += \
|
||||
s-intman.adb<s-intman-susv3.adb \
|
||||
@ -2195,7 +2195,7 @@ ifeq ($(strip $(filter-out darwin%,$(osys))),)
|
||||
s-osprim.adb<s-osprim-posix.adb \
|
||||
a-numaux.ads<a-numaux-darwin.ads \
|
||||
a-numaux.adb<a-numaux-darwin.adb
|
||||
|
||||
|
||||
ifeq ($(strip $(MULTISUBDIR)),/ppc64)
|
||||
LIBGNAT_TARGET_PAIRS += \
|
||||
system.ads<system-darwin-ppc64.ads
|
||||
|
@ -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
|
||||
@ -126,6 +130,7 @@ DEF_VEC_ALLOC_O(variant_desc,heap);
|
||||
static GTY ((if_marked ("tree_int_map_marked_p"),
|
||||
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 void prepend_one_attribute_to (struct attrib **,
|
||||
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,
|
||||
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
|
||||
@ -5266,6 +5276,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;
|
||||
@ -5275,6 +5289,63 @@ get_minimal_subprog_decl (Entity_Id 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. */
|
||||
|
||||
void
|
||||
|
@ -153,10 +153,10 @@ gnat_handle_option (size_t scode, const char *arg ATTRIBUTE_UNUSED, int value,
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
Ada_handle_option_auto (&global_options, &global_options_set,
|
||||
scode, arg, value,
|
||||
gnat_option_lang_mask (), kind,
|
||||
loc, handlers, global_dc);
|
||||
Ada_handle_option_auto (&global_options, &global_options_set,
|
||||
scode, arg, value,
|
||||
gnat_option_lang_mask (), kind,
|
||||
loc, handlers, global_dc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user