OSDN Git Service

* decl.c (compatible_signatures_p): New function. The intended purpose
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 3 Jan 2005 15:35:16 +0000 (15:35 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 3 Jan 2005 15:35:16 +0000 (15:35 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@92833 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/decl.c
gcc/ada/gigi.h
gcc/ada/utils.c

index d11b11a..710d0f1 100644 (file)
@@ -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);
-\f
+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);
 }
 \f
+/* 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;
+}
+\f
 /* 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
index 20784c1..bb03912 100644 (file)
@@ -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:
index 7be9d97..b92fe4b 100644 (file)
@@ -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;
 }
+\f
+/* 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"