From: Arnaud Charlet Date: Mon, 3 Jan 2005 15:35:16 +0000 (+0100) Subject: decl.c (compatible_signatures_p): New function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c5e12904bcca3866f419bb91365dbdfb052b8782;p=gcc.git 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) : 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 --- diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c index d11b11af8e4..710d0f1a4f0 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 20784c1b5d2..bb03912a637 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 7be9d975479..b92fe4bd7c6 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"