Patchwork [Ada] Static aggregates of a limited type

login
register
mail settings
Submitter Arnaud Charlet
Date Oct. 8, 2010, 10:32 a.m.
Message ID <20101008103224.GA10650@adacore.com>
Download mbox | patch
Permalink /patch/67161/
State New
Headers show

Comments

Arnaud Charlet - Oct. 8, 2010, 10:32 a.m.
This patch optimizes the handling of aggregates with static components, and
allows more complex nested aggregates to be handled by the backend without any
elaboration code. This applies in particular to aggregates of a limited type,
which previously were always expanded into assignments.

The following must compile quietly:

---
pragma Restrictions (No_Elaboration_Code);
package Elab is
   pragma Preelaborate;

   procedure Test;
   function Probe (X : Integer) return Boolean;
end Elab;
---
pragma Restrictions (No_Elaboration_Code);
with Fair_Locks;

package body Elab is

   use Fair_Locks;

   Lock : Fair_Lock := (Spinning => (others => False));

   Complex : Tagged_Lock := (Contents => (others => False));

   procedure Test is
   begin
      if not Lock.Spinning (3) then
         Lock.Spinning (2) := True;
      end if;
   end Test;

   function Probe (X : Integer) return Boolean is
   begin
      return Lock.Spinning (X);
   end Probe;
end Elab;
---
package Fair_Locks is
   pragma Preelaborate;

   type Spinning_Array is array (1 .. 16) of Boolean;

   type Fair_Lock is limited record
      Spinning : Spinning_Array := (others => False);
   end record;

   type Tagged_Lock is tagged limited record
      Contents : Spinning_Array := (others => False);
   end record;

end Fair_Locks;

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

2010-10-08  Ed Schonberg  <schonberg@adacore.com>

	* sem_aggr.adb (Resolve_Array_Aggregate): If the expression in an
	others choice is a literal analyze it now to enable later optimizations.
	* exp_aggr.adb (Expand_Record_Aggregate): An aggregate with static size
	and components can be handled by the backend even if it is of a limited
	type.

Patch

Index: sem_aggr.adb
===================================================================
--- sem_aggr.adb	(revision 165106)
+++ sem_aggr.adb	(working copy)
@@ -1795,6 +1795,19 @@  package body Sem_Aggr is
                      Expander_Mode_Save_And_Set (False);
                      Full_Analysis := False;
                      Analyze (Expr);
+
+                     --  If the expression is a literal, propagate this info
+                     --  to the expression in the association, to enable some
+                     --  optimizations downstream.
+
+                     if Is_Entity_Name (Expr)
+                       and then Present (Entity (Expr))
+                       and then Ekind (Entity (Expr)) = E_Enumeration_Literal
+                     then
+                        Analyze_And_Resolve
+                          (Expression (Assoc), Component_Typ);
+                     end if;
+
                      Full_Analysis := Save_Analysis;
                      Expander_Mode_Restore;
 
Index: exp_aggr.adb
===================================================================
--- exp_aggr.adb	(revision 165104)
+++ exp_aggr.adb	(working copy)
@@ -3773,6 +3773,13 @@  package body Exp_Aggr is
                then
                   null;
 
+               elsif Is_Entity_Name (Expression (Expr))
+                 and then Present (Entity (Expression (Expr)))
+                 and then Ekind (Entity (Expression (Expr))) =
+                   E_Enumeration_Literal
+               then
+                  null;
+
                elsif Nkind (Expression (Expr)) /= N_Aggregate
                  or else not Compile_Time_Known_Aggregate (Expression (Expr))
                  or else Expansion_Delayed (Expression (Expr))
@@ -5491,6 +5498,14 @@  package body Exp_Aggr is
 
          C := First (Comps);
          while Present (C) loop
+
+            --  If the component has box initialization, expansion is needed
+            --  and component is not ready for backend.
+
+            if Box_Present (C) then
+               return True;
+            end if;
+
             if Nkind (Expression (C)) = N_Qualified_Expression then
                Expr_Q := Expression (Expression (C));
             else
@@ -5576,13 +5591,32 @@  package body Exp_Aggr is
       end if;
 
       --  Ada 2005 (AI-318-2): We need to convert to assignments if components
-      --  are build-in-place function calls. This test could be more specific,
-      --  but doing it for all inherently limited aggregates seems harmless.
-      --  The assignments will turn into build-in-place function calls (see
-      --  Make_Build_In_Place_Call_In_Assignment).
+      --  are build-in-place function calls. The assignments will each turn
+      --  into a build-in-place function call.  If components are all static,
+      --  we can pass the aggregate to the backend regardless of limitedness.
+
+      --  Extension aggregates, aggregates in extended return statements, and
+      --  aggregates for C++ imported types must be expanded.
 
       if Ada_Version >= Ada_05 and then Is_Inherently_Limited_Type (Typ) then
-         Convert_To_Assignments (N, Typ);
+         if Nkind (Parent (N)) /= N_Object_Declaration then
+            Convert_To_Assignments (N, Typ);
+
+         elsif Nkind (N) = N_Extension_Aggregate
+           or else Convention (Typ) = Convention_CPP
+         then
+            Convert_To_Assignments (N, Typ);
+
+         elsif not Size_Known_At_Compile_Time (Typ)
+           or else Component_Not_OK_For_Backend
+           or else not Static_Components
+         then
+            Convert_To_Assignments (N, Typ);
+
+         else
+            Set_Compile_Time_Known_Aggregate (N);
+            Set_Expansion_Delayed (N, False);
+         end if;
 
       --  Gigi doesn't handle properly temporaries of variable size
       --  so we generate it in the front-end