diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2012-05-19 09:32:50 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2012-05-19 09:32:50 +0000 |
commit | c80c1ce9510e2840d036d6a5e9b035a659701c41 (patch) | |
tree | 52608a68d00e823d6d2ae72fe69bd81af3a8b1c6 /gcc | |
parent | 2a2aa0391efaad653fba352187d6c51de479f40b (diff) | |
download | gcc-c80c1ce9510e2840d036d6a5e9b035a659701c41.zip gcc-c80c1ce9510e2840d036d6a5e9b035a659701c41.tar.gz gcc-c80c1ce9510e2840d036d6a5e9b035a659701c41.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/gcc-interface/Makefile.in | 4 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 77 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/misc.c | 8 |
3 files changed, 80 insertions, 9 deletions
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in index c1d9284..21c2471 100644 --- a/gcc/ada/gcc-interface/Makefile.in +++ b/gcc/ada/gcc-interface/Makefile.in @@ -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 diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index bb36269..05c9b1a 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 @@ -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 diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index f2002f5..6d77dc8 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -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; } |