]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[Ada] Extend No_Dependence restriction to code generation
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 28 Jun 2022 17:03:00 +0000 (19:03 +0200)
committerPierre-Marie de Rodat <derodat@adacore.com>
Wed, 13 Jul 2022 10:01:22 +0000 (10:01 +0000)
This reports violations for 4 units from gigi.

gcc/ada/

* gcc-interface/trans.cc (gigi): Report a violation of No_Dependence
on System.Stack_Checking if Stack_Check_Probes_On_Target is not set
and -fstack-check is specified.
(build_binary_op_trapv): Report violatiosn of No_Dependence on both
System.Arith_64 and System.Arith_128.
(add_decl_expr): If an initialized variable, report a violation of
No_Dependence on System.Memory_Copy for large aggregate types.
(gnat_to_gnu) <N_Op_Eq>: Report a violation
of No_Dependence on System.Memory_Compare for large aggregate types.
<N_Assignment_Statement>! Report a violation of No_Dependence on
System.Memory_Set, System.Memory_Move or else System.Memory_Copy for
large aggregate types.
* gcc-interface/utils2.cc (maybe_wrap_malloc): Report a violation of
No_Dependence on System.Memory.
(maybe_wrap_free): Add GNAT_NODE parameter and report a violation of
No_Dependence on System.Memory.
(build_call_alloc_dealloc): Adjust call to maybe_wrap_free.

gcc/ada/gcc-interface/trans.cc
gcc/ada/gcc-interface/utils2.cc

index 5eff4df5954085d49835c9984d527767d5a7b522..9d7fd2b2377feb31b673633db0c65f290e4b23fe 100644 (file)
@@ -364,7 +364,12 @@ gigi (Node_Id gnat_root,
 
   /* Enable GNAT stack checking method if needed */
   if (!Stack_Check_Probes_On_Target)
-    set_stack_check_libfunc ("__gnat_stack_check");
+    {
+      set_stack_check_libfunc ("__gnat_stack_check");
+      if (flag_stack_check != NO_STACK_CHECK)
+       Check_Restriction_No_Dependence_On_System (Name_Stack_Checking,
+                                                  gnat_root);
+    }
 
   /* Retrieve alignment settings.  */
   double_float_alignment = get_target_double_float_alignment ();
@@ -6933,9 +6938,18 @@ gnat_to_gnu (Node_Id gnat_node)
              = convert (TREE_TYPE (gnu_rhs), TYPE_SIZE (gnu_type));
          }
 
+       /* If this is a comparison between (potentially) large aggregates, then
+          declare the dependence on the memcmp routine.  */
+       else if ((kind == N_Op_Eq || kind == N_Op_Ne)
+                && AGGREGATE_TYPE_P (TREE_TYPE (gnu_lhs))
+                && (!TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (gnu_lhs)))
+                    || compare_tree_int (TYPE_SIZE (TREE_TYPE (gnu_lhs)),
+                                         2 * BITS_PER_WORD) > 0))
+         Check_Restriction_No_Dependence_On_System (Name_Memory_Compare,
+                                                    gnat_node);
+
        /* Pending generic support for efficient vector logical operations in
-          GCC, convert vectors to their representative array type view and
-          fallthrough.  */
+          GCC, convert vectors to their representative array type view.  */
        gnu_lhs = maybe_vector_array (gnu_lhs);
        gnu_rhs = maybe_vector_array (gnu_rhs);
 
@@ -7254,6 +7268,8 @@ gnat_to_gnu (Node_Id gnat_node)
                  value = int_const_binop (BIT_AND_EXPR, value, mask);
                }
              gnu_result = build_call_expr (t, 3, dest, value, size);
+             Check_Restriction_No_Dependence_On_System (Name_Memory_Set,
+                                                        gnat_node);
            }
 
          /* Otherwise build a regular assignment.  */
@@ -7278,7 +7294,18 @@ gnat_to_gnu (Node_Id gnat_node)
              tree from_ptr = build_fold_addr_expr (from);
              tree t = builtin_decl_explicit (BUILT_IN_MEMMOVE);
              gnu_result = build_call_expr (t, 3, to_ptr, from_ptr, size);
+             Check_Restriction_No_Dependence_On_System (Name_Memory_Move,
+                                                        gnat_node);
           }
+
+         /* If this is an assignment between (potentially) large aggregates,
+            then declare the dependence on the memcpy routine.  */
+         else if (AGGREGATE_TYPE_P (TREE_TYPE (gnu_lhs))
+                  && (!TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (gnu_lhs)))
+                      || compare_tree_int (TYPE_SIZE (TREE_TYPE (gnu_lhs)),
+                                           2 * BITS_PER_WORD) > 0))
+           Check_Restriction_No_Dependence_On_System (Name_Memory_Copy,
+                                                      gnat_node);
        }
       break;
 
@@ -8437,27 +8464,37 @@ add_decl_expr (tree gnu_decl, Node_Id gnat_node)
       && !TYPE_FAT_POINTER_P (type))
     MARK_VISITED (TYPE_ADA_SIZE (type));
 
-  /* If this is a variable and an initializer is attached to it, it must be
-     valid for the context.  Similar to init_const in create_var_decl.  */
-  if (TREE_CODE (gnu_decl) == VAR_DECL
-      && (gnu_init = DECL_INITIAL (gnu_decl))
-      && (!gnat_types_compatible_p (type, TREE_TYPE (gnu_init))
+  if (TREE_CODE (gnu_decl) == VAR_DECL && (gnu_init = DECL_INITIAL (gnu_decl)))
+    {
+      /* If this is a variable and an initializer is attached to it, it must be
+        valid for the context.  Similar to init_const in create_var_decl.  */
+      if (!gnat_types_compatible_p (type, TREE_TYPE (gnu_init))
          || (TREE_STATIC (gnu_decl)
              && !initializer_constant_valid_p (gnu_init,
-                                               TREE_TYPE (gnu_init)))))
-    {
-      DECL_INITIAL (gnu_decl) = NULL_TREE;
-      if (TREE_READONLY (gnu_decl))
+                                               TREE_TYPE (gnu_init))))
        {
-         TREE_READONLY (gnu_decl) = 0;
-         DECL_READONLY_ONCE_ELAB (gnu_decl) = 1;
-       }
+         DECL_INITIAL (gnu_decl) = NULL_TREE;
+         if (TREE_READONLY (gnu_decl))
+           {
+             TREE_READONLY (gnu_decl) = 0;
+             DECL_READONLY_ONCE_ELAB (gnu_decl) = 1;
+           }
+
+         /* Remove any padding so the assignment is done properly.  */
+         gnu_decl = maybe_padded_object (gnu_decl);
 
-      /* Remove any padding so the assignment is done properly.  */
-      gnu_decl = maybe_padded_object (gnu_decl);
+         gnu_stmt
+           = build_binary_op (INIT_EXPR, NULL_TREE, gnu_decl, gnu_init);
+         add_stmt_with_node (gnu_stmt, gnat_node);
+       }
 
-      gnu_stmt = build_binary_op (INIT_EXPR, NULL_TREE, gnu_decl, gnu_init);
-      add_stmt_with_node (gnu_stmt, gnat_node);
+      /* If this is the initialization of a (potentially) large aggregate, then
+        declare the dependence on the memcpy routine.  */
+      if (AGGREGATE_TYPE_P (type)
+         && (!TREE_CONSTANT (TYPE_SIZE (type))
+             || compare_tree_int (TYPE_SIZE (type), 2 * BITS_PER_WORD) > 0))
+       Check_Restriction_No_Dependence_On_System (Name_Memory_Copy,
+                                                  gnat_node);
     }
 }
 
@@ -9359,6 +9396,7 @@ build_binary_op_trapv (enum tree_code code, tree gnu_type, tree left,
       if (code == MULT_EXPR && precision == 64 && BITS_PER_WORD < 64)
        {
          tree int64 = gnat_type_for_size (64, 0);
+         Check_Restriction_No_Dependence_On_System (Name_Arith_64, gnat_node);
          return convert (gnu_type, build_call_n_expr (mulv64_decl, 2,
                                                       convert (int64, lhs),
                                                       convert (int64, rhs)));
@@ -9368,6 +9406,7 @@ build_binary_op_trapv (enum tree_code code, tree gnu_type, tree left,
       else if (code == MULT_EXPR && precision == 128 && BITS_PER_WORD < 128)
        {
          tree int128 = gnat_type_for_size (128, 0);
+         Check_Restriction_No_Dependence_On_System (Name_Arith_128, gnat_node);
          return convert (gnu_type, build_call_n_expr (mulv128_decl, 2,
                                                       convert (int128, lhs),
                                                       convert (int128, rhs)));
index 4dfe29dc7d9993485803687187b090e7c34d93a4..4c66a930d1d79002997e76d2e513f19b4ff4d48c 100644 (file)
@@ -2259,6 +2259,8 @@ maybe_wrap_malloc (tree data_size, tree data_type, Node_Id gnat_node)
 
   tree malloc_ptr = build_call_n_expr (malloc_decl, 1, size_to_malloc);
 
+  Check_Restriction_No_Dependence_On_System (Name_Memory, gnat_node);
+
   if (aligning_type)
     {
       /* Latch malloc's return value and get a pointer to the aligning field
@@ -2305,7 +2307,7 @@ maybe_wrap_malloc (tree data_size, tree data_type, Node_Id gnat_node)
    designated by DATA_PTR using the __gnat_free entry point.  */
 
 static inline tree
-maybe_wrap_free (tree data_ptr, tree data_type)
+maybe_wrap_free (tree data_ptr, tree data_type, Node_Id gnat_node)
 {
   /* In the regular alignment case, we pass the data pointer straight to free.
      In the superaligned case, we need to retrieve the initial allocator
@@ -2317,6 +2319,8 @@ maybe_wrap_free (tree data_ptr, tree data_type)
 
   tree free_ptr;
 
+  Check_Restriction_No_Dependence_On_System (Name_Memory, gnat_node);
+
   if (data_align > system_allocator_alignment)
     {
       /* DATA_FRONT_PTR (void *)
@@ -2363,7 +2367,7 @@ build_call_alloc_dealloc (tree gnu_obj, tree gnu_size, tree gnu_type,
   /* Otherwise, object to "free" or "malloc" with possible special processing
      for alignments stricter than what the default allocator honors.  */
   else if (gnu_obj)
-    return maybe_wrap_free (gnu_obj, gnu_type);
+    return maybe_wrap_free (gnu_obj, gnu_type, gnat_node);
   else
     {
       /* Assert that we no longer can be called with this special pool.  */