aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/repinfo.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/repinfo.adb')
-rw-r--r--gcc/ada/repinfo.adb315
1 files changed, 235 insertions, 80 deletions
diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb
index cd4b664..1d616db 100644
--- a/gcc/ada/repinfo.adb
+++ b/gcc/ada/repinfo.adb
@@ -30,6 +30,7 @@ with Debug; use Debug;
with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
+with GNAT.Heap_Sort_G;
with Lib; use Lib;
with Namet; use Namet;
with Nlists; use Nlists;
@@ -77,20 +78,6 @@ package body Repinfo is
Op3 : Node_Ref_Or_Val;
end record;
- -- The following representation clause ensures that the above record
- -- has no holes. We do this so that when instances of this record are
- -- written, we do not write uninitialized values to the file.
-
- for Exp_Node use record
- Expr at 0 range 0 .. 31;
- Op1 at 4 range 0 .. 31;
- Op2 at 8 range 0 .. 31;
- Op3 at 12 range 0 .. 31;
- end record;
-
- for Exp_Node'Size use 16 * 8;
- -- This ensures that we did not leave out any fields
-
package Rep_Table is new Table.Table (
Table_Component_Type => Exp_Node,
Table_Index_Type => Nat,
@@ -427,9 +414,9 @@ package body Repinfo is
Write_Line (";");
end if;
- -- Alignment is not always set for task, protected, and class-wide
- -- types, or when doing semantic analysis only. Representation aspects
- -- are not computed for types in a generic unit.
+ -- Alignment is not always set for concurrent types, class-wide types,
+ -- cloned subtypes, or when doing semantic analysis only. Representation
+ -- aspects are not computed for types declared in a generic unit.
else
-- Add unknown alignment entry in JSON format to ensure the format is
@@ -440,11 +427,13 @@ package body Repinfo is
Write_Unknown_Val;
end if;
- pragma Assert
- (not Expander_Active or else
- Is_Concurrent_Type (Ent) or else
- Is_Class_Wide_Type (Ent) or else
- Sem_Util.In_Generic_Scope (Ent));
+ pragma Assert (not Expander_Active
+ or else Is_Concurrent_Type (Ent)
+ or else Is_Class_Wide_Type (Ent)
+ or else (Ekind (Ent) = E_Record_Subtype
+ and then Present (Cloned_Subtype (Ent))
+ and then Has_Delayed_Freeze (Cloned_Subtype (Ent)))
+ or else Sem_Util.In_Generic_Scope (Ent));
end if;
end List_Common_Type_Info;
@@ -544,11 +533,13 @@ package body Repinfo is
List_Type_Info (E);
end if;
- -- Note that formals are not annotated so we skip them here
+ -- Formals and renamings are not annotated, so we skip them
+ -- here.
elsif Ekind (E) in E_Constant
| E_Loop_Parameter
| E_Variable
+ and then Nkind (Parent (E)) /= N_Object_Renaming_Declaration
then
if List_Representation_Info >= 2 then
List_Object_Info (E);
@@ -870,8 +861,7 @@ package body Repinfo is
-- generic unit, or if the back end is not being run), don't try to
-- print them.
- pragma Assert (Known_Esize (Ent) = Known_Alignment (Ent));
- if not Known_Alignment (Ent) then
+ if not Known_Esize (Ent) or else not Known_Alignment (Ent) then
return;
end if;
@@ -896,6 +886,7 @@ package body Repinfo is
Write_Eol;
Write_Line ("}");
+
else
Write_Str ("for ");
List_Name (Ent);
@@ -1237,11 +1228,135 @@ package body Repinfo is
Starting_First_Bit : Uint := Uint_0;
Prefix : String := "")
is
- Comp : Entity_Id;
- First : Boolean := True;
+ function First_Comp_Or_Discr (Ent : Entity_Id) return Entity_Id;
+ -- Like First_Component_Or_Discriminant, but reorder the components
+ -- according to their bit offset if need be.
+
+ -------------------------
+ -- First_Comp_Or_Discr --
+ -------------------------
+
+ function First_Comp_Or_Discr (Ent : Entity_Id) return Entity_Id is
+
+ function Is_Placed_Before (C1, C2 : Entity_Id) return Boolean;
+ -- Return True if component C1 is placed before component C2
+
+ ----------------------
+ -- Is_Placed_Before --
+ ----------------------
+
+ function Is_Placed_Before (C1, C2 : Entity_Id) return Boolean is
+ begin
+ return Known_Static_Component_Bit_Offset (C1)
+ and then Known_Static_Component_Bit_Offset (C2)
+ and then
+ Component_Bit_Offset (C1) < Component_Bit_Offset (C2);
+ end Is_Placed_Before;
+
+ -- Local variables
+
+ Comp : Entity_Id;
+ N_Comp : Natural := 0;
+ Prev : Entity_Id;
+ Reorder : Boolean := False;
+
+ -- Start of processing for First_Comp_Or_Discr
+
+ begin
+ -- Reordering is needed only for -gnatRh
+
+ if not List_Representation_Info_Holes then
+ return First_Component_Or_Discriminant (Ent);
+ end if;
+
+ -- Count the number of components and whether reordering is needed
+
+ Comp := First_Component_Or_Discriminant (Ent);
+ Prev := Comp;
+
+ while Present (Comp) loop
+ N_Comp := N_Comp + 1;
+
+ if not Reorder then
+ Reorder := Is_Placed_Before (Comp, Prev);
+ end if;
+
+ Prev := Comp;
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
+
+ -- Reorder the components, if need be, by directly reshuffling the
+ -- list of entities between First_Entity and Last_Entity, which is
+ -- safe because we are invoked after compilation is finished.
+
+ if Reorder then
+ declare
+ Comps : array (Natural range 0 .. N_Comp) of Entity_Id;
+ -- Support array for the heapsort
+
+ function Lt (Op1, Op2 : Natural) return Boolean is
+ (Is_Placed_Before (Comps (Op1), Comps (Op2)));
+ -- Compare function for the heapsort
+
+ procedure Move (From : Natural; To : Natural);
+ pragma Inline (Move);
+ -- Move procedure for the heapsort
+
+ ----------
+ -- Move --
+ ----------
+
+ procedure Move (From : Natural; To : Natural) is
+ begin
+ Comps (To) := Comps (From);
+ end Move;
+
+ package HS is new GNAT.Heap_Sort_G (Lt => Lt, Move => Move);
+ -- The heapsort for record components
+
+ begin
+ -- Pack the components into the array
+
+ N_Comp := 0;
+ Comp := First_Component_Or_Discriminant (Ent);
+
+ while Present (Comp) loop
+ N_Comp := N_Comp + 1;
+ Comps (N_Comp) := Comp;
+
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
+
+ -- Sort the array
+
+ HS.Sort (N_Comp);
+
+ -- Unpack the component into the list of entities
+
+ Set_First_Entity (Ent, Comps (1));
+ Set_Prev_Entity (Comps (1), Empty);
+ for J in 1 .. N_Comp - 1 loop
+ Set_Next_Entity (Comps (J), Comps (J + 1));
+ Set_Prev_Entity (Comps (J + 1), Comps (J));
+ end loop;
+ Set_Next_Entity (Comps (N_Comp), Empty);
+ Set_Last_Entity (Ent, Comps (N_Comp));
+ end;
+ end if;
+
+ return First_Component_Or_Discriminant (Ent);
+ end First_Comp_Or_Discr;
+
+ -- Local variables
+
+ Bit_Offset : Uint := Uint_0;
+ Comp : Entity_Id;
+ First : Boolean := True;
+
+ -- Start of processing for List_Record_Layout
begin
- Comp := First_Component_Or_Discriminant (Ent);
+ Comp := First_Comp_Or_Discr (Ent);
while Present (Comp) loop
-- Skip a completely hidden discriminant or a discriminant in an
@@ -1251,69 +1366,98 @@ package body Repinfo is
and then (Is_Completely_Hidden (Comp)
or else Is_Unchecked_Union (Ent))
then
- goto Continue;
- end if;
+ null;
-- Skip _Parent component in extension (to avoid overlap)
- if Chars (Comp) = Name_uParent then
- goto Continue;
- end if;
+ elsif Chars (Comp) = Name_uParent then
+ null;
-- All other cases
- declare
- Ctyp : constant Entity_Id := Underlying_Type (Etype (Comp));
- Npos : constant Uint := Normalized_Position (Comp);
- Fbit : constant Uint := Normalized_First_Bit (Comp);
- Spos : Uint;
- Sbit : Uint;
+ else
+ declare
+ C : constant Entity_Id :=
+ (if Known_Normalized_Position (Comp)
+ then Comp
+ else Original_Record_Component (Comp));
+ -- The Parent_Subtype in an extension is not back-annotated
+ -- but its layout is the same as that of the parent type.
- begin
- Get_Decoded_Name_String (Chars (Comp));
- Set_Casing (Unit_Casing);
+ Ctyp : constant Entity_Id := Underlying_Type (Etype (C));
- -- If extended information is requested, recurse fully into
- -- record components, i.e. skip the outer level.
+ begin
+ Get_Decoded_Name_String (Chars (C));
+ Set_Casing (Unit_Casing);
- if List_Representation_Info_Extended
- and then Is_Record_Type (Ctyp)
- and then Known_Static_Normalized_Position (Comp)
- and then Known_Static_Normalized_First_Bit (Comp)
- then
- Spos := Starting_Position + Npos;
- Sbit := Starting_First_Bit + Fbit;
+ -- If extended information is requested, recurse fully into
+ -- record components, i.e. skip the outer level.
- if Sbit >= SSU then
- Spos := Spos + 1;
- Sbit := Sbit - SSU;
- end if;
+ if List_Representation_Info_Extended
+ and then Is_Record_Type (Ctyp)
+ and then Known_Static_Normalized_Position (C)
+ and then Known_Static_Normalized_First_Bit (C)
+ then
+ declare
+ Npos : constant Uint := Normalized_Position (C);
+ Fbit : constant Uint := Normalized_First_Bit (C);
+ Pref : constant String :=
+ Prefix & Name_Buffer (1 .. Name_Len) & ".";
- List_Record_Layout (Ctyp,
- Spos, Sbit, Prefix & Name_Buffer (1 .. Name_Len) & ".");
+ Spos : Uint;
+ Sbit : Uint;
- goto Continue;
- end if;
+ begin
+ Spos := Starting_Position + Npos;
+ Sbit := Starting_First_Bit + Fbit;
+
+ if Sbit >= SSU then
+ Spos := Spos + 1;
+ Sbit := Sbit - SSU;
+ end if;
+
+ List_Record_Layout (Ctyp, Spos, Sbit, Pref);
+ end;
- if List_Representation_Info_To_JSON then
- if First then
- Write_Eol;
- First := False;
else
- Write_Line (",");
- end if;
- end if;
+ if List_Representation_Info_To_JSON then
+ if First then
+ Write_Eol;
+ First := False;
+ else
+ Write_Line (",");
+ end if;
+ end if;
- -- The Parent_Subtype in an extension is not back-annotated
+ -- If information about holes is requested, update the
+ -- current bit offset and report any (static) gap.
- List_Component_Layout (
- (if Known_Normalized_Position (Comp)
- then Comp
- else Original_Record_Component (Comp)),
- Starting_Position, Starting_First_Bit, Prefix);
- end;
+ if List_Representation_Info_Holes
+ and then Known_Static_Component_Bit_Offset (C)
+ then
+ declare
+ Gap : constant Uint :=
+ Component_Bit_Offset (C) - Bit_Offset;
+ begin
+ if Gap > Uint_0 then
+ Write_Str (" -- ");
+ UI_Write (Gap, Decimal);
+ Write_Line (" bits unused --");
+ end if;
+
+ if Known_Static_Esize (C) then
+ Bit_Offset :=
+ Component_Bit_Offset (C) + Esize (C);
+ end if;
+ end;
+ end if;
+
+ List_Component_Layout
+ (C, Starting_Position, Starting_First_Bit, Prefix);
+ end if;
+ end;
+ end if;
- <<Continue>>
Next_Component_Or_Discriminant (Comp);
end loop;
end List_Record_Layout;
@@ -1624,6 +1768,17 @@ package body Repinfo is
end loop;
end List_Structural_Record_Layout;
+ -- Use the original record type giving the layout of components
+ -- to avoid repeated reordering when -gnatRh is specified.
+
+ Rec : constant Entity_Id :=
+ (if Ekind (Ent) = E_Record_Subtype
+ and then Present (Cloned_Subtype (Ent))
+ then (if Is_Private_Type (Cloned_Subtype (Ent))
+ then Full_View (Cloned_Subtype (Ent))
+ else Cloned_Subtype (Ent))
+ else Ent);
+
-- Start of processing for List_Record_Info
begin
@@ -1638,7 +1793,7 @@ package body Repinfo is
-- First find out max line length and max starting position
-- length, for the purpose of lining things up nicely.
- Compute_Max_Length (Ent);
+ Compute_Max_Length (Rec);
-- Then do actual output based on those values
@@ -1650,21 +1805,21 @@ package body Repinfo is
-- declared in the extended main source unit for the time being,
-- because otherwise declarations might not be processed at all.
- if Is_Base_Type (Ent) then
+ if Is_Base_Type (Rec) then
begin
- List_Structural_Record_Layout (Ent, Ent);
+ List_Structural_Record_Layout (Rec, Rec);
exception
when Incomplete_Layout
| Not_In_Extended_Main
=>
- List_Record_Layout (Ent);
+ List_Record_Layout (Rec);
when others =>
raise Program_Error;
end;
else
- List_Record_Layout (Ent);
+ List_Record_Layout (Rec);
end if;
Write_Eol;
@@ -1674,7 +1829,7 @@ package body Repinfo is
List_Name (Ent);
Write_Line (" use record");
- List_Record_Layout (Ent);
+ List_Record_Layout (Rec);
Write_Line ("end record;");
end if;