diff mbox series

[Ada] Initialize_Scalars optimization causes spurious runtime check failure

Message ID 20180523103003.GA9102@adacore.com
State New
Headers show
Series [Ada] Initialize_Scalars optimization causes spurious runtime check failure | expand

Commit Message

Pierre-Marie de Rodat May 23, 2018, 10:30 a.m. UTC
This patch suppresses the optimization of scalar arrays when pragma
Initialize_Scalars is in effect if the component type is subject to
predicates. Since the scalar array is initialized with invalid values,
these values may violate the predicate or a validity check within the
predicate.

------------
-- Source --
------------

--  gnat.adc

pragma Initialize_Scalars;

--  types.ads

with System; use System;

package Types is
   type Byte is mod System.Storage_Unit;

   subtype Inter_Byte is Byte;

   function Always_OK (B : Inter_Byte) return Boolean is (True);
   function Is_OK     (B : Inter_Byte) return Boolean is (Always_OK (B));

   subtype Final_Byte is Byte with Predicate => Is_OK (Final_Byte);

   type Bytes is array (1 .. 5) of Final_Byte;

   Obj : Bytes;
end Types;

--  main.adb

with Types; use Types;

procedure Main is begin null; end Main;

-----------------
-- Compilation --
-----------------

$ gnatmake -q -gnata -gnatVa main.adb
$ ./main

Tested on x86_64-pc-linux-gnu, committed on trunk

2018-05-23  Hristian Kirtchev  <kirtchev@adacore.com>

gcc/ada/

	* exp_ch3.adb (Default_Initialize_Object): Do not optimize scalar array
	initialization when the component type has predicates.
	* exp_ch4.adb (Expand_N_Allocator): Do not optimize scalar array
	allocation when the component type has predicates.
diff mbox series

Patch

--- gcc/ada/exp_ch3.adb
+++ gcc/ada/exp_ch3.adb
@@ -6069,29 +6069,43 @@  package body Exp_Ch3 is
                   null;
 
                --  Optimize the default initialization of an array object when
-               --  the following conditions are met:
-               --
-               --    * Pragma Initialize_Scalars or Normalize_Scalars is in
-               --      effect.
-               --
-               --    * The bounds of the array type are static and lack empty
-               --      ranges.
-               --
-               --    * The array type does not contain atomic components or is
-               --      treated as packed.
-               --
-               --    * The component is of a scalar type which requires simple
-               --      initialization.
-               --
+               --  pragma Initialize_Scalars or Normalize_Scalars is in effect.
                --  Construct an in-place initialization aggregate which may be
                --  convert into a fast memset by the backend.
 
                elsif Init_Or_Norm_Scalars
                  and then Is_Array_Type (Typ)
+
+                 --  The array must lack atomic components because they are
+                 --  treated as non-static, and as a result the backend will
+                 --  not initialize the memory in one go.
+
                  and then not Has_Atomic_Components (Typ)
+
+                 --  The array must not be packed because the invalid values
+                 --  in System.Scalar_Values are multiples of Storage_Unit.
+
                  and then not Is_Packed (Typ)
+
+                 --  The array must have static non-empty ranges, otherwise
+                 --  the backend cannot initialize the memory in one go.
+
                  and then Has_Static_Non_Empty_Array_Bounds (Typ)
+
+                 --  The optimization is only relevant for arrays of scalar
+                 --  types.
+
                  and then Is_Scalar_Type (Component_Type (Typ))
+
+                 --  Similar to regular array initialization using a type
+                 --  init proc, predicate checks are not performed because the
+                 --  initialization values are intentionally invalid, and may
+                 --  violate the predicate.
+
+                 and then not Has_Predicates (Component_Type (Typ))
+
+                 --  The component type must have a single initialization value
+
                  and then Simple_Initialization_OK (Component_Type (Typ))
                then
                   Set_No_Initialization (N, False);

--- gcc/ada/exp_ch4.adb
+++ gcc/ada/exp_ch4.adb
@@ -4618,28 +4618,42 @@  package body Exp_Ch4 is
                   Is_Allocate => True);
             end if;
 
-         --  Optimize the default allocation of an array object when the
-         --  following conditions are met:
-         --
-         --    * Pragma Initialize_Scalars or Normalize_Scalars is in effect
-         --
-         --    * The bounds of the array type are static and lack empty ranges
-         --
-         --    * The array type does not contain atomic components or is
-         --      treated as packed.
-         --
-         --    * The component is of a scalar type which requires simple
-         --      initialization.
-         --
-         --  Construct an in-place initialization aggregate which may be
-         --  convert into a fast memset by the backend.
+         --  Optimize the default allocation of an array object when pragma
+         --  Initialize_Scalars or Normalize_Scalars is in effect. Construct an
+         --  in-place initialization aggregate which may be convert into a fast
+         --  memset by the backend.
 
          elsif Init_Or_Norm_Scalars
            and then Is_Array_Type (T)
+
+           --  The array must lack atomic components because they are treated
+           --  as non-static, and as a result the backend will not initialize
+           --  the memory in one go.
+
            and then not Has_Atomic_Components (T)
+
+           --  The array must not be packed because the invalid values in
+           --  System.Scalar_Values are multiples of Storage_Unit.
+
            and then not Is_Packed (T)
+
+           --  The array must have static non-empty ranges, otherwise the
+           --  backend cannot initialize the memory in one go.
+
            and then Has_Static_Non_Empty_Array_Bounds (T)
+
+           --  The optimization is only relevant for arrays of scalar types
+
            and then Is_Scalar_Type (Component_Type (T))
+
+           --  Similar to regular array initialization using a type init proc,
+           --  predicate checks are not performed because the initialization
+           --  values are intentionally invalid, and may violate the predicate.
+
+           and then not Has_Predicates (Component_Type (T))
+
+           --  The component type must have a single initialization value
+
            and then Needs_Simple_Initialization
                       (Typ         => Component_Type (T),
                        Consider_IS => True)