2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-03-25 10:40:56 +08:00

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
This commit is contained in:
Arnaud Charlet 2005-01-03 16:35:16 +01:00
parent ddda9d0f19
commit c5e12904bc
3 changed files with 91 additions and 3 deletions

@ -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

@ -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:

@ -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"