aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2005-01-03 16:35:16 +0100
committerArnaud Charlet <charlet@gcc.gnu.org>2005-01-03 16:35:16 +0100
commitc5e12904bcca3866f419bb91365dbdfb052b8782 (patch)
tree53590e1867ac15c4a766621c129b8b6971ad96f6
parentddda9d0f19611a053a759c415cc2f835c1051f22 (diff)
downloadgcc-c5e12904bcca3866f419bb91365dbdfb052b8782.zip
gcc-c5e12904bcca3866f419bb91365dbdfb052b8782.tar.gz
gcc-c5e12904bcca3866f419bb91365dbdfb052b8782.tar.bz2
decl.c (compatible_signatures_p): New function.
* decl.c (compatible_signatures_p): New function. The intended purpose is to check if two function signatures for a call-site and a callee are compatible enough for the call to be valid. The underlying purpose is to check if a call to a mapped builtin is using the right interface. The current code actually does not check antyhing - this a placeholder for future refinements. (gnat_to_gnu_entity) <E_Subprogram_Call>: Add preliminary bits to handle builtin calls for convention Intrinsic. * gigi.h (builtin_decl_for): Declare (new function). * utils.c (gnat_install_builtins): Install the target specific builtins. (builtin_decl_for): New function, provide a dummy body for now. From-SVN: r92833
-rw-r--r--gcc/ada/decl.c75
-rw-r--r--gcc/ada/gigi.h5
-rw-r--r--gcc/ada/utils.c14
3 files changed, 91 insertions, 3 deletions
diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c
index d11b11a..710d0f1 100644
--- a/gcc/ada/decl.c
+++ b/gcc/ada/decl.c
@@ -101,7 +101,8 @@ static void set_rm_size (Uint, tree, Entity_Id);
static tree make_type_from_size (tree, tree, bool);
static unsigned int validate_alignment (Uint, Entity_Id, unsigned int);
static void check_ok_for_atomic (tree, Entity_Id, bool);
-
+static int compatible_signatures_p (tree ftype1, tree ftype2);
+
/* Given GNAT_ENTITY, an entity in the incoming GNAT tree, return a
GCC type corresponding to that entity. GNAT_ENTITY is assumed to
refer to an Ada type. */
@@ -3242,6 +3243,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
corresponding to that field. This list will be saved in the
TYPE_CI_CO_LIST field of the FUNCTION_TYPE node we create. */
tree gnu_return_list = NULL_TREE;
+ /* If an import pragma asks to map this subprogram to a GCC builtin,
+ this is the builtin DECL node. */
+ tree gnu_builtin_decl = NULL_TREE;
Entity_Id gnat_param;
bool inline_flag = Is_Inlined (gnat_entity);
bool public_flag = Is_Public (gnat_entity);
@@ -3283,6 +3287,20 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
break;
}
+ /* If this subprogram is expectedly bound to a GCC builtin, fetch the
+ corresponding DECL node.
+
+ We still want the parameter associations to take place because the
+ proper generation of calls depends on it (a GNAT parameter without
+ a corresponding GCC tree has a very specific meaning), so we don't
+ just break here. */
+ if (Convention (gnat_entity) == Convention_Intrinsic)
+ gnu_builtin_decl = builtin_decl_for (gnu_ext_name);
+
+ /* ??? What if we don't find the builtin node above ? warn ? err ?
+ In the current state we neither warn nor err, and calls will just
+ be handled as for regular subprograms. */
+
if (kind == E_Function || kind == E_Subprogram_Type)
gnu_return_type = gnat_to_gnu_type (Etype (gnat_entity));
@@ -3378,9 +3396,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
bool copy_in_copy_out_flag = false;
bool req_by_copy = false, req_by_ref = false;
- /* See if a Mechanism was supplied that forced this
+ /* Builtins are expanded inline and there is no real call sequence
+ involved. so the type expected by the underlying expander is
+ always the type of each argument "as is". */
+ if (gnu_builtin_decl)
+ req_by_copy = 1;
+
+ /* Otherwise, see if a Mechanism was supplied that forced this
parameter to be passed one way or another. */
- if (Is_Valued_Procedure (gnat_entity) && parmnum == 0)
+ else if (Is_Valued_Procedure (gnat_entity) && parmnum == 0)
req_by_copy = true;
else if (Mechanism (gnat_param) == Default)
;
@@ -3638,6 +3662,23 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
Sloc_to_locus (Sloc (gnat_entity), &input_location);
+ /* If we have a builtin decl for that function, check the signatures
+ compatibilities. If the signatures are compatible, use the builtin
+ decl. If they are not, we expect the checker predicate to have
+ posted the appropriate errors, and just continue with what we have
+ so far. */
+ if (gnu_builtin_decl)
+ {
+ tree gnu_builtin_type = TREE_TYPE (gnu_builtin_decl);
+
+ if (compatible_signatures_p (gnu_type, gnu_builtin_type))
+ {
+ gnu_decl = gnu_builtin_decl;
+ gnu_type = gnu_builtin_type;
+ break;
+ }
+ }
+
/* If there was no specified Interface_Name and the external and
internal names of the subprogram are the same, only use the
internal name to allow disambiguation of nested subprograms. */
@@ -6210,6 +6251,34 @@ check_ok_for_atomic (tree object, Entity_Id gnat_entity, bool comp_p)
gnat_error_point, gnat_entity);
}
+/* Check if FTYPE1 and FTYPE2, two potentially different function type nodes,
+ have compatible signatures so that a call using one type may be safely
+ issued if the actual target function type is the other. Return 1 if it is
+ the case, 0 otherwise, and post errors on the incompatibilities.
+
+ This is used when an Ada subprogram is mapped onto a GCC builtin, to ensure
+ that calls to the subprogram will have arguments suitable for the later
+ underlying builtin expansion. */
+
+static int
+compatible_signatures_p (tree ftype1, tree ftype2)
+{
+ /* As of now, we only perform very trivial tests and consider it's the
+ programmer's responsability to ensure the type correctness in the Ada
+ declaration, as in the regular Import cases.
+
+ Mismatches typically result in either error messages from the builtin
+ expander, internal compiler errors, or in a real call sequence. This
+ should be refined to issue diagnostics helping error detection and
+ correction. */
+
+ /* Almost fake test, ensuring a use of each argument. */
+ if (ftype1 == ftype2)
+ return 1;
+
+ return 1;
+}
+
/* Given a type T, a FIELD_DECL F, and a replacement value R, return a new type
with all size expressions that contain F updated by replacing F with R.
This is identical to GCC's substitute_in_type except that it knows about
diff --git a/gcc/ada/gigi.h b/gcc/ada/gigi.h
index 20784c1..bb03912 100644
--- a/gcc/ada/gigi.h
+++ b/gcc/ada/gigi.h
@@ -687,6 +687,11 @@ extern bool gnat_mark_addressable (tree);
extern tree builtin_function (const char *, tree, int, enum built_in_class,
const char *, tree);
+/* Search the chain of currently reachable declarations for a builtin
+ FUNCTION_DECL node corresponding to function NAME (an IDENTIFIER_NODE).
+ Return the first node found, if any, or NULL_TREE otherwise. */
+extern tree builtin_decl_for (tree);
+
/* This function is called by the front end to enumerate all the supported
modes for the machine. We pass a function which is called back with
the following integer parameters:
diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c
index 7be9d97..b92fe4b 100644
--- a/gcc/ada/utils.c
+++ b/gcc/ada/utils.c
@@ -509,6 +509,9 @@ gnat_install_builtins ()
ftype = build_function_type (ptr_void_type_node, tmp);
gnat_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
"alloca", false);
+
+ /* Target specific builtins, such as the AltiVec family on ppc. */
+ targetm.init_builtins ();
}
/* Create the predefined scalar types such as `integer_type_node' needed
@@ -3305,6 +3308,17 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
return expr;
}
+
+/* Search the chain of currently reachable declarations for a builtin
+ FUNCTION_DECL node corresponding to function NAME (an IDENTIFIER_NODE).
+ Return the first node found, if any, or NULL_TREE otherwise. */
+tree
+builtin_decl_for (tree name __attribute__ ((unused)))
+{
+ /* ??? not clear yet how to implement this function in tree-ssa, so
+ return NULL_TREE for now */
+ return NULL_TREE;
+}
#include "gt-ada-utils.h"
#include "gtype-ada.h"