function Hash (F : File_Name_Type) return Header_Num is
begin
- return Header_Num (Int (F) rem Header_Num'Range_Length);
+ return Header_Num (Int (F) mod Header_Num'Range_Length);
end Hash;
---------------------------
-- scope__name__line_column__locations
--
-- * The String is converted into a Name_Id
- -- * The Name_Id is used as the hash
+ --
+ -- * The absolute value of the Name_Id is used as the hash
Append (Buffer, IS_Rec.Scope);
Append (Buffer, "__");
end if;
IS_Nam := Name_Find (Buffer);
- return Bucket_Range_Type (IS_Nam);
+ return Bucket_Range_Type (abs IS_Nam);
end Hash;
--------------------
-- assertions this lock has no effect.
Reporting_Proc : Report_Proc := null;
- -- Record argument to last call to Set_Reporting_Proc
+ -- Set_Reporting_Proc sets this. Set_Reporting_Proc must be called only
+ -- once.
Rewriting_Proc : Rewrite_Proc := null;
-- This soft link captures the procedure invoked during a node rewrite
procedure Node_Debug_Output (Op : String; N : Node_Id);
-- Called by nnd; writes Op followed by information about N
- procedure Print_Statistics;
- pragma Export (Ada, Print_Statistics);
- -- Print various statistics on the tables maintained by the package
-
-----------------------------
-- Local Objects and Types --
-----------------------------
- Node_Count : Nat;
- -- Count allocated nodes for Num_Nodes function
+ Comes_From_Source_Default : Boolean := False;
use Unchecked_Access;
-- We are allowed to see these from within our own body
-- Note: eventually, this should be a field in the Node directly, but
-- for now we do not want to disturb the efficiency of a power of 2
- -- for the node size
+ -- for the node size. ????We are planning to get rid of power-of-2.
package Orig_Nodes is new Table.Table (
Table_Component_Type => Node_Id,
Table_Increment => 200,
Table_Name => "Paren_Counts");
+ procedure Set_Paren_Count_Of_Copy (Target, Source : Node_Id);
+ pragma Inline (Set_Paren_Count_Of_Copy);
+ -- Called when copying a node. Makes sure the Paren_Count of the copy is
+ -- correct.
+
-----------------------
-- Local Subprograms --
-----------------------
- function Allocate_Initialize_Node
- (Src : Node_Id;
- With_Extension : Boolean) return Node_Id;
- -- Allocate a new node or node extension. If Src is not empty, the
- -- information for the newly-allocated node is copied from it.
+ function Allocate_New_Node return Node_Id;
+ pragma Inline (Allocate_New_Node);
+ -- Allocate a new node or first part of a node extension. Initialize the
+ -- Nodes.Table entry, Flags, Orig_Nodes, and List tables.
procedure Fix_Parents (Ref_Node, Fix_Node : Node_Id);
-- Fix up parent pointers for the syntactic children of Fix_Node after a
-- Mark arbitrary node or entity N as Ghost when it is created within a
-- Ghost region.
- ------------------------------
- -- Allocate_Initialize_Node --
- ------------------------------
+ procedure Report (Target, Source : Node_Id);
+ pragma Inline (Report);
+ -- Invoke the reporting procedure if available
- function Allocate_Initialize_Node
- (Src : Node_Id;
- With_Extension : Boolean) return Node_Id
- is
- New_Id : Node_Id;
+ -----------------------
+ -- Allocate_New_Node --
+ -----------------------
+ function Allocate_New_Node return Node_Id is
+ New_Id : Node_Id;
begin
- if Present (Src)
- and then not Has_Extension (Src)
- and then With_Extension
- and then Src = Nodes.Last
- then
- New_Id := Src;
-
- -- We are allocating a new node, or extending a node other than
- -- Nodes.Last.
-
- else
- if Present (Src) then
- Nodes.Append (Nodes.Table (Src));
- Flags.Append (Flags.Table (Src));
- else
- Nodes.Append (Default_Node);
- Flags.Append (Default_Flags);
- end if;
-
- New_Id := Nodes.Last;
- Orig_Nodes.Append (New_Id);
- Node_Count := Node_Count + 1;
- end if;
-
- -- Clear Check_Actuals to False
-
- Set_Check_Actuals (New_Id, False);
-
- -- Specifically copy Paren_Count to deal with creating new table entry
- -- if the parentheses count is at the maximum possible value already.
-
- if Present (Src) and then Nkind (Src) in N_Subexpr then
- Set_Paren_Count (New_Id, Paren_Count (Src));
- end if;
-
- -- Set extension nodes if required
-
- if With_Extension then
- if Present (Src) and then Has_Extension (Src) then
- for J in 1 .. Num_Extension_Nodes loop
- Nodes.Append (Nodes.Table (Src + J));
- Flags.Append (Flags.Table (Src + J));
- end loop;
- else
- for J in 1 .. Num_Extension_Nodes loop
- Nodes.Append (Default_Node_Extension);
- Flags.Append (Default_Flags);
- end loop;
- end if;
- end if;
-
- Orig_Nodes.Set_Last (Nodes.Last);
+ Nodes.Append (Default_Node);
+ New_Id := Nodes.Last;
+ Flags.Append (Default_Flags);
+ Orig_Nodes.Append (New_Id);
+ Nodes.Table (Nodes.Last).Comes_From_Source :=
+ Comes_From_Source_Default;
Allocate_List_Tables (Nodes.Last);
-
- -- Invoke the reporting procedure (if available)
-
- if Reporting_Proc /= null then
- Reporting_Proc.all (Target => New_Id, Source => Src);
- end if;
+ Report (Target => New_Id, Source => Empty);
return New_Id;
- end Allocate_Initialize_Node;
+ end Allocate_New_Node;
--------------
-- Analyzed --
Flags.Table (Destination) := Flags.Table (Source);
- -- Specifically set Paren_Count to make sure auxiliary table entry
- -- gets correctly made if the parentheses count is at the max value.
-
- if Nkind (Destination) in N_Subexpr then
- Set_Paren_Count (Destination, Paren_Count (Source));
- end if;
+ Set_Paren_Count_Of_Copy (Target => Destination, Source => Source);
-- Deal with copying extension nodes if present. No need to copy flags
-- table entries, since they are always zero for extending components.
-- Extend_Node --
-----------------
- function Extend_Node (Node : Node_Id) return Entity_Id is
- Result : Entity_Id;
+ function Extend_Node (Source : Node_Id) return Entity_Id is
+ pragma Assert (Present (Source));
+ pragma Assert (not Has_Extension (Source));
+ New_Id : Entity_Id;
procedure Debug_Extend_Node;
pragma Inline (Debug_Extend_Node);
- -- Debug routine for debug flag N
+ -- Debug routine for -gnatdn
-----------------------
-- Debug_Extend_Node --
begin
if Debug_Flag_N then
Write_Str ("Extend node ");
- Write_Int (Int (Node));
+ Write_Int (Int (Source));
- if Result = Node then
+ if New_Id = Source then
Write_Str (" in place");
else
Write_Str (" copied to ");
- Write_Int (Int (Result));
+ Write_Int (Int (New_Id));
end if;
-- Write_Eol;
-- Start of processing for Extend_Node
begin
- pragma Assert (not (Has_Extension (Node)));
+ -- Optimize the case where Source happens to be the last node; in that
+ -- case, we don't need to move it.
+
+ if Source = Nodes.Last then
+ New_Id := Source;
+ else
+ Nodes.Append (Nodes.Table (Source));
+ Flags.Append (Flags.Table (Source));
+ New_Id := Nodes.Last;
+ Orig_Nodes.Append (New_Id);
+ end if;
+
+ Set_Check_Actuals (New_Id, False);
+
+ -- Set extension nodes
+
+ for J in 1 .. Num_Extension_Nodes loop
+ Nodes.Append (Default_Node_Extension);
+ Flags.Append (Default_Flags);
+ end loop;
+
+ Orig_Nodes.Set_Last (Nodes.Last);
+ Allocate_List_Tables (Nodes.Last);
+ Report (Target => New_Id, Source => Source);
- Result := Allocate_Initialize_Node (Node, With_Extension => True);
pragma Debug (Debug_Extend_Node);
- return Result;
+ return New_Id;
end Extend_Node;
-----------------
-----------------
procedure Fix_Parents (Ref_Node, Fix_Node : Node_Id) is
+ pragma Assert (Nkind (Ref_Node) = Nkind (Fix_Node));
+
procedure Fix_Parent (Field : Union_Id);
-- Fix up one parent pointer. Field is checked to see if it points to
-- a node, list, or element list that has a parent that points to
function Get_Comes_From_Source_Default return Boolean is
begin
- return Default_Node.Comes_From_Source;
+ return Comes_From_Source_Default;
end Get_Comes_From_Source_Default;
-----------------
pragma Warnings (Off, Dummy);
begin
- Node_Count := 0;
Atree_Private_Part.Nodes.Init;
Atree_Private_Part.Flags.Init;
Orig_Nodes.Init;
-- We used to Release the tables, as in the comments below, but that is
-- a waste of time. We're only wasting virtual memory here, and the
-- release calls copy large amounts of data.
+ -- ???Get rid of Release?
- -- Nodes.Release;
- Nodes.Locked := True;
-- Flags.Release;
Flags.Locked := True;
-- Orig_Nodes.Release;
--------------
function New_Copy (Source : Node_Id) return Node_Id is
- New_Id : Node_Id := Source;
-
+ New_Id : Node_Id;
begin
- if Source > Empty_Or_Error then
- New_Id := Allocate_Initialize_Node (Source, Has_Extension (Source));
+ if Source <= Empty_Or_Error then
+ return Source;
+ end if;
- Nodes.Table (New_Id).In_List := False;
- Nodes.Table (New_Id).Link := Empty_List_Or_Node;
+ Nodes.Append (Nodes.Table (Source));
+ Flags.Append (Flags.Table (Source));
+ New_Id := Nodes.Last;
+ Orig_Nodes.Append (New_Id);
+ Set_Check_Actuals (New_Id, False);
+ Set_Paren_Count_Of_Copy (Target => New_Id, Source => Source);
- -- If the original is marked as a rewrite insertion, then unmark the
- -- copy, since we inserted the original, not the copy.
+ -- Set extension nodes if required
- Nodes.Table (New_Id).Rewrite_Ins := False;
- pragma Debug (New_Node_Debugging_Output (New_Id));
+ if Has_Extension (Source) then
+ for J in 1 .. Num_Extension_Nodes loop
+ Nodes.Append (Nodes.Table (Source + J));
+ Flags.Append (Flags.Table (Source + J));
+ end loop;
+ Orig_Nodes.Set_Last (Nodes.Last);
+ else
+ pragma Assert (Orig_Nodes.Table (Orig_Nodes.Last) = Nodes.Last);
+ end if;
- -- Clear Is_Overloaded since we cannot have semantic interpretations
- -- of this new node.
+ Allocate_List_Tables (Nodes.Last);
+ Report (Target => New_Id, Source => Source);
- if Nkind (Source) in N_Subexpr then
- Set_Is_Overloaded (New_Id, False);
- end if;
+ Nodes.Table (New_Id).In_List := False;
+ Nodes.Table (New_Id).Link := Empty_List_Or_Node;
- -- Always clear Has_Aspects, the caller must take care of copying
- -- aspects if this is required for the particular situation.
+ -- If the original is marked as a rewrite insertion, then unmark the
+ -- copy, since we inserted the original, not the copy.
- Set_Has_Aspects (New_Id, False);
+ Nodes.Table (New_Id).Rewrite_Ins := False;
+ pragma Debug (New_Node_Debugging_Output (New_Id));
- -- Mark the copy as Ghost depending on the current Ghost region
+ -- Clear Is_Overloaded since we cannot have semantic interpretations
+ -- of this new node.
- Mark_New_Ghost_Node (New_Id);
+ if Nkind (Source) in N_Subexpr then
+ Set_Is_Overloaded (New_Id, False);
end if;
+ -- Always clear Has_Aspects, the caller must take care of copying
+ -- aspects if this is required for the particular situation.
+
+ Set_Has_Aspects (New_Id, False);
+
+ -- Mark the copy as Ghost depending on the current Ghost region
+
+ Mark_New_Ghost_Node (New_Id);
+
+ pragma Assert (New_Id /= Source);
return New_Id;
end New_Copy;
(New_Node_Kind : Node_Kind;
New_Sloc : Source_Ptr) return Entity_Id
is
- Ent : Entity_Id;
-
- begin
pragma Assert (New_Node_Kind in N_Entity);
+ New_Id : constant Entity_Id := Allocate_New_Node;
+ begin
+ -- Set extension nodes
- Ent := Allocate_Initialize_Node (Empty, With_Extension => True);
+ for J in 1 .. Num_Extension_Nodes loop
+ Nodes.Append (Default_Node_Extension);
+ Flags.Append (Default_Flags);
+ end loop;
+
+ Orig_Nodes.Set_Last (Nodes.Last);
-- If this is a node with a real location and we are generating
-- source nodes, then reset Current_Error_Node. This is useful
-- if we bomb during parsing to get a error location for the bomb.
- if Default_Node.Comes_From_Source and then New_Sloc > No_Location then
- Current_Error_Node := Ent;
+ if New_Sloc > No_Location and then Comes_From_Source_Default then
+ Current_Error_Node := New_Id;
end if;
- Nodes.Table (Ent).Nkind := New_Node_Kind;
- Nodes.Table (Ent).Sloc := New_Sloc;
- pragma Debug (New_Node_Debugging_Output (Ent));
+ Nodes.Table (New_Id).Nkind := New_Node_Kind;
+ Nodes.Table (New_Id).Sloc := New_Sloc;
+ pragma Debug (New_Node_Debugging_Output (New_Id));
-- Mark the new entity as Ghost depending on the current Ghost region
- Mark_New_Ghost_Node (Ent);
+ Mark_New_Ghost_Node (New_Id);
- return Ent;
+ return New_Id;
end New_Entity;
--------------
(New_Node_Kind : Node_Kind;
New_Sloc : Source_Ptr) return Node_Id
is
- Nod : Node_Id;
-
- begin
pragma Assert (New_Node_Kind not in N_Entity);
-
- Nod := Allocate_Initialize_Node (Empty, With_Extension => False);
- Nodes.Table (Nod).Nkind := New_Node_Kind;
- Nodes.Table (Nod).Sloc := New_Sloc;
- pragma Debug (New_Node_Debugging_Output (Nod));
+ New_Id : constant Node_Id := Allocate_New_Node;
+ pragma Assert (Orig_Nodes.Table (Orig_Nodes.Last) = Nodes.Last);
+ begin
+ Nodes.Table (New_Id).Nkind := New_Node_Kind;
+ Nodes.Table (New_Id).Sloc := New_Sloc;
+ pragma Debug (New_Node_Debugging_Output (New_Id));
-- If this is a node with a real location and we are generating source
-- nodes, then reset Current_Error_Node. This is useful if we bomb
-- during parsing to get an error location for the bomb.
- if Default_Node.Comes_From_Source and then New_Sloc > No_Location then
- Current_Error_Node := Nod;
+ if Comes_From_Source_Default and then New_Sloc > No_Location then
+ Current_Error_Node := New_Id;
end if;
-- Mark the new node as Ghost depending on the current Ghost region
- Mark_New_Ghost_Node (Nod);
+ Mark_New_Ghost_Node (New_Id);
- return Nod;
+ return New_Id;
end New_Node;
-------------------------
return Nodes.Table (First_Node_Id)'Address;
end Nodes_Address;
- ---------------
- -- Num_Nodes --
- ---------------
+ -----------------------------------
+ -- Approx_Num_Nodes_And_Entities --
+ -----------------------------------
- function Num_Nodes return Nat is
+ function Approx_Num_Nodes_And_Entities return Nat is
begin
- return Node_Count;
- end Num_Nodes;
+ -- This is an overestimate, because entities take up more space, but
+ -- that really doesn't matter; it's not worth subtracting out the
+ -- "extra".
+
+ return Nat (Nodes.Last - First_Node_Id);
+ end Approx_Num_Nodes_And_Entities;
-------------------
-- Original_Node --
end if;
end Replace;
+ ------------
+ -- Report --
+ ------------
+
+ procedure Report (Target, Source : Node_Id) is
+ begin
+ if Reporting_Proc /= null then
+ Reporting_Proc.all (Target, Source);
+ end if;
+ end Report;
+
-------------
-- Rewrite --
-------------
procedure Set_Comes_From_Source_Default (Default : Boolean) is
begin
- Default_Node.Comes_From_Source := Default;
+ Comes_From_Source_Default := Default;
end Set_Comes_From_Source_Default;
---------------
Nodes.Table (N).Pflag1 := True;
Nodes.Table (N).Pflag2 := True;
+ -- Search for existing table entry
+
for J in Paren_Counts.First .. Paren_Counts.Last loop
if N = Paren_Counts.Table (J).Nod then
Paren_Counts.Table (J).Count := Val;
end if;
end loop;
+ -- No existing table entry; make a new one
+
Paren_Counts.Append ((Nod => N, Count => Val));
end if;
end Set_Paren_Count;
+ -----------------------------
+ -- Set_Paren_Count_Of_Copy --
+ -----------------------------
+
+ procedure Set_Paren_Count_Of_Copy (Target, Source : Node_Id) is
+ begin
+ -- We already copied the two Pflags. We need to update the Paren_Counts
+ -- table only if greater than 2.
+
+ if Nkind (Source) in N_Subexpr
+ and then Paren_Count (Source) > 2
+ then
+ Set_Paren_Count (Target, Paren_Count (Source));
+ end if;
+
+ pragma Assert (Paren_Count (Target) = Paren_Count (Source));
+ end Set_Paren_Count_Of_Copy;
+
----------------
-- Set_Parent --
----------------
procedure Unlock is
begin
- Nodes.Locked := False;
Flags.Locked := False;
Orig_Nodes.Locked := False;
end Unlock;
-- Currently entities are composed of 7 sequentially allocated 32-byte
-- nodes, considered as a single record. The following definition gives
- -- the number of extension nodes.
+ -- the number of extension nodes. ????We plan to change this.
Num_Extension_Nodes : Node_Id := 6;
-- This value is increased by one if debug flag -gnatd.N is set. This is
-- 2.01 for the nodes/entities ratio and a 2% increase in compilation time
-- on average for the GCC-based compiler at -O0 on a 32-bit x86 host.
+ procedure Print_Statistics;
+ pragma Export (Ada, Print_Statistics);
+ -- Print various statistics on the tables maintained by the package
+
----------------------------------------
-- Definitions of Fields in Tree Node --
----------------------------------------
function Flags_Address return System.Address;
-- Return address of Flags table (used in Back_End for Gigi call)
- function Num_Nodes return Nat;
- -- Total number of nodes allocated, where an entity counts as a single
- -- node. This count is incremented every time a node or entity is
- -- allocated, and decremented every time a node or entity is deleted.
- -- This value is used by Xref and by Treepr to allocate hash tables of
- -- suitable size for hashing Node_Id values.
+ function Approx_Num_Nodes_And_Entities return Nat;
+ -- This is an approximation to the number of nodes and entities allocated,
+ -- used to determine sizes of hash tables.
-----------------------
-- Use of Empty Node --
-- place, and then for subsequent modifications as required.
procedure Initialize;
- -- Called at the start of compilation to initialize the allocation of
- -- the node and list tables and make the standard entries for Empty,
- -- Error and Error_List.
+ -- Called at the start of compilation to initialize the allocation of the
+ -- node and list tables and make the entries for Empty and Error.
procedure Lock;
-- Called before the back end is invoked to lock the nodes table
-- semantic chains: Homonym and Next_Entity: the corresponding links must
-- be adjusted by the caller, according to context.
- function Extend_Node (Node : Node_Id) return Entity_Id;
+ function Extend_Node (Source : Node_Id) return Entity_Id;
-- This function returns a copy of its input node with an extension added.
-- The fields of the extension are set to Empty. Due to the way extensions
-- are handled (as four consecutive array elements), it may be necessary
-- Field6-11 Holds Field36-Field41
end case;
- end record;
+ end record; -- Node_Record
+ pragma Suppress_Initialization (Node_Record); -- see package Nodes below
pragma Pack (Node_Record);
for Node_Record'Size use 8 * 32;
-- Default value used to initialize default nodes. Note that some of the
-- fields get overwritten, and in particular, Nkind always gets reset.
- Default_Node : Node_Record := (
+ Default_Node : constant Node_Record := (
Is_Extension => False,
Pflag1 => False,
Pflag2 => False,
Rewrite_Ins => False,
Analyzed => False,
Comes_From_Source => False,
- -- modified by Set_Comes_From_Source_Default
Error_Posted => False,
Flag4 => False,
Nkind => N_Unused_At_Start,
- Sloc => No_Location,
+ Sloc => 0,
Link => Empty_List_Or_Node,
Field1 => Empty_List_Or_Node,
Field2 => Empty_List_Or_Node,
Field11 => Empty_List_Or_Node,
Field12 => Empty_List_Or_Node);
- -- The following defines the extendable array used for the nodes table
- -- Nodes with extensions use six consecutive entries in the array
-
- package Nodes is new Table.Table (
- Table_Component_Type => Node_Record,
- Table_Index_Type => Node_Id'Base,
- Table_Low_Bound => First_Node_Id,
- Table_Initial => Alloc.Nodes_Initial,
- Table_Increment => Alloc.Nodes_Increment,
- Release_Threshold => Alloc.Nodes_Release_Threshold,
- Table_Name => "Nodes");
+ -- The following defines the extendable array used for the nodes table.
+ -- Nodes with extensions use multiple consecutive entries in the array
+ -- (see Num_Extension_Nodes).
+
+ package Nodes is new Table.Table
+ (Table_Component_Type => Node_Record,
+ Table_Index_Type => Node_Id'Base,
+ Table_Low_Bound => First_Node_Id,
+ Table_Initial => Alloc.Nodes_Initial,
+ Table_Increment => Alloc.Nodes_Increment,
+ Release_Threshold => Alloc.Nodes_Release_Threshold,
+ Table_Name => "Nodes");
-- The following is a parallel table to Nodes, which provides 8 more
-- bits of space that logically belong to the corresponding node. This
begin
pragma Assert (Present (Nam));
- return Bucket_Range_Type (Nam);
+ return Bucket_Range_Type (abs Nam);
end Hash_File_Name;
---------------------
-- d.y Disable implicit pragma Elaborate_All on task bodies
-- d.z Restore previous support for frontend handling of Inline_Always
- -- d.A
+ -- d.A Print Atree statistics
-- d.B Generate a bug box on abort_statement
-- d.C Generate concatenation call, do not generate inline code
-- d.D Disable errors on use of overriding keyword in Ada 95 mode
-- handling of Inline_Always by the front end on such targets. For the
-- targets that do not use the GCC back end, this switch is ignored.
+ -- d.A Print Atree statistics
+
-- d.B Generate a bug box when we see an abort_statement, even though
-- there is no bug. Useful for testing Comperr.Compiler_Abort: write
-- some code containing an abort_statement, and compile it with
limitations:
* Starting the program's execution in the debugger will cause it to
- stop at the start of the ``main`` function instead of the main subprogram.
- This can be worked around by manually inserting a breakpoint on that
+ stop at the start of the ``main`` function instead of the main subprogram.
+ This can be worked around by manually inserting a breakpoint on that
subprogram and resuming the program's execution until reaching that breakpoint.
* Programs using GNAT.Compiler_Version will not link.
-- --
------------------------------------------------------------------------------
-pragma Style_Checks (All_Checks);
--- Turn off subprogram ordering, not used for this unit
-
with Atree; use Atree;
with Elists; use Elists;
with Namet; use Namet;
function Hash (F : Name_Id) return Hash_Index is
begin
- return Hash_Index (Natural (F) mod Positive (Hash_Index'Last + 1));
+ return Hash_Index (Integer (F) mod Positive (Hash_Index'Last + 1));
end Hash;
--------------------------
function Hash (F : File_Name_Type) return Header_Num is
begin
- return Header_Num (Int (F) rem Header_Num'Range_Length);
+ return Header_Num (Int (F) mod Header_Num'Range_Length);
end Hash;
function Hash (F : Unit_Name_Type) return Header_Num is
begin
- return Header_Num (Int (F) rem Header_Num'Range_Length);
+ return Header_Num (Int (F) mod Header_Num'Range_Length);
end Hash;
----------------
function SFN_Hash (F : Unit_Name_Type) return SFN_Header_Num is
begin
- return SFN_Header_Num (Int (F) rem SFN_Header_Num'Range_Length);
+ return SFN_Header_Num (Int (F) mod SFN_Header_Num'Range_Length);
end SFN_Hash;
begin
-- Initialize all packages. For the most part, these initialization
-- calls can be made in any order. Exceptions are as follows:
- -- Lib.Initialize need to be called before Scan_Compiler_Arguments,
+ -- Lib.Initialize needs to be called before Scan_Compiler_Arguments,
-- because it initializes a table filled by Scan_Compiler_Arguments.
+ -- Atree.Initialize needs to be called after Scan_Compiler_Arguments,
+ -- because the value specified by the -gnaten switch is used by
+ -- Atree.Initialize.
+
Osint.Initialize;
Fmap.Reset_Tables;
Lib.Initialize;
end;
<<End_Of_Program>>
- null;
+
+ if Debug_Flag_Dot_AA then
+ Atree.Print_Statistics;
+ end if;
-- The outer exception handler handles an unrecoverable error
return Id in Name_Entries.First .. Name_Entries.Last;
end Is_Valid_Name;
+ ------------------
+ -- Last_Name_Id --
+ ------------------
+
+ function Last_Name_Id return Name_Id is
+ begin
+ return Name_Id (Int (First_Name_Id) + Name_Entries_Count - 1);
+ end Last_Name_Id;
+
--------------------
-- Length_Of_Name --
--------------------
function Name_Entries_Count return Nat;
-- Return current number of entries in the names table
+ function Last_Name_Id return Name_Id;
+ -- Return the last Name_Id in the table. This information is valid until
+ -- new names have been added.
+
--------------------------
-- Obsolete Subprograms --
--------------------------
----------------
procedure Initialize is
- E : constant List_Id := Error_List;
-
begin
Lists.Init;
Next_Node.Init;
-- Allocate Error_List list header
Lists.Increment_Last;
- Set_Parent (E, Empty);
- Set_First (E, Empty);
- Set_Last (E, Empty);
+ Set_Parent (Error_List, Empty);
+ Set_First (Error_List, Empty);
+ Set_Last (Error_List, Empty);
end Initialize;
------------------
-- "if Present (Statements)" as opposed to "if Statements /= No_List".
procedure Allocate_List_Tables (N : Node_Or_Entity_Id);
+ pragma Inline (Allocate_List_Tables);
-- Called when nodes table is expanded to include node N. This call
-- makes sure that list structures internal to Nlists are adjusted
-- appropriately to reflect this increase in the size of the nodes table.
-- If a pragma No_Tagged_Streams is active for the current scope, this
-- points to the corresponding pragma.
+ Nodes_Size_In_Meg : Nat := 0;
+ -- GNAT
+ -- Amount of memory to allocate for all nodes, in units of 2**20 bytes.
+ -- Set by the -gnaten switch; 0 means -gnaten was not given, and a default
+ -- value should be used.
+
Normalize_Scalars : Boolean := False;
-- GNAT, GNATBIND
-- Set True if a pragma Normalize_Scalars applies to the current unit.
function File_Hash (F : File_Name_Type) return File_Hash_Num is
begin
- return File_Hash_Num (Int (F) rem File_Hash_Num'Range_Length);
+ return File_Hash_Num (Int (F) mod File_Hash_Num'Range_Length);
end File_Hash;
-----------------
declare
E : Entity_Id;
Ematch : Entity_Id := Empty;
-
- Last_Name_Id : constant Name_Id :=
- Name_Id (Nat (First_Name_Id) +
- Name_Entries_Count - 1);
-
begin
for Nam in First_Name_Id .. Last_Name_Id loop
E := Get_Name_Entity_Id (Nam);
-- --
------------------------------------------------------------------------------
-pragma Style_Checks (All_Checks);
--- No subprogram ordering check, due to logical grouping
-
with Atree; use Atree;
package body Sinfo is
new String'(Switch_Chars (Ptr .. Max));
return;
+ -- -gnaten (memory to allocate for nodes)
+
+ when 'n' =>
+ Ptr := Ptr + 1;
+ Scan_Pos
+ (Switch_Chars, Max, Ptr, Nodes_Size_In_Meg, C);
+
-- -gnateO= (object path file)
-- This is an internal switch
----------------
procedure Print_Init is
+ Max_Hash_Entries : constant Nat :=
+ Approx_Num_Nodes_And_Entities + Num_Lists + Num_Elists;
begin
Printing_Descendants := True;
Write_Eol;
-- the maximum possible number of entries, so that the hash table
-- cannot get significantly overloaded.
- Hash_Table_Len := (150 * (Num_Nodes + Num_Lists + Num_Elists)) / 100;
+ Hash_Table_Len := (150 * Max_Hash_Entries) / 100;
Hash_Table := new Hash_Table_Type (0 .. Hash_Table_Len - 1);
for J in Hash_Table'Range loop
-- These types are represented as integer indices into various tables.
-- However, they should be treated as private, except in a few documented
- -- cases. In particular it is never appropriate to perform arithmetic
- -- operations using these types.
+ -- cases. In particular it is usually inappropriate to perform arithmetic
+ -- operations using these types. One exception is in computing hash
+ -- functions of these types.
-- In most contexts, the strongly typed interface determines which of these
-- types is present. However, there are some situations (involving untyped
-- traversals of the tree), where it is convenient to be easily able to
-- distinguish these values. The underlying representation in all cases is
-- an integer type Union_Id, and we ensure that the range of the various
- -- possible values for each of the above types is disjoint so that this
- -- distinction is possible.
+ -- possible values for each of the above types is disjoint (except that
+ -- List_Id and Node_Id overlap at Empty) so that this distinction is
+ -- possible.
-- Note: it is also helpful for debugging purposes to make these ranges
-- distinct. If a bug leads to misidentification of a value, then it will
-- typically result in an out of range value and a Constraint_Error.
+ -- The range of Node_Id is most of the nonnegative integers. The other
+ -- ranges are negative. Uint has a very large range, because a substantial
+ -- part of this range is used to store direct values; see Uintp for
+ -- details. The other types have 100 million values, which should be
+ -- plenty.
+
type Union_Id is new Int;
-- The type in the tree for a union of possible ID values
- List_Low_Bound : constant := -100_000_000;
+ -- Following are the Low and High bounds of the various ranges.
+
+ List_Low_Bound : constant := -099_999_999;
-- The List_Id values are subscripts into an array of list headers which
- -- has List_Low_Bound as its lower bound. This value is chosen so that all
- -- List_Id values are negative, and the value zero is in the range of both
- -- List_Id and Node_Id values (see further description below).
+ -- has List_Low_Bound as its lower bound.
List_High_Bound : constant := 0;
- -- Maximum List_Id subscript value. This allows up to 100 million list Id
- -- values, which is in practice infinite, and there is no need to check the
- -- range. The range overlaps the node range by one element (with value
- -- zero), which is used both for the Empty node, and for indicating no
- -- list. The fact that the same value is used is convenient because it
- -- means that the default value of Empty applies to both nodes and lists,
- -- and also is more efficient to test for.
+ -- Maximum List_Id subscript value. The ranges of List_Id and Node_Id
+ -- overlap by one element (with value zero), which is used both for the
+ -- Empty node, and for No_List. The fact that the same value is used is
+ -- convenient because it means that the default value of Empty applies to
+ -- both nodes and lists, and also is more efficient to test for.
Node_Low_Bound : constant := 0;
-- The tree Id values start at zero, because we use zero for Empty (to
- -- allow a zero test for Empty). Actual tree node subscripts start at 0
- -- since Empty is a legitimate node value.
+ -- allow a zero test for Empty).
- Node_High_Bound : constant := 099_999_999;
- -- Maximum number of nodes that can be allocated is 100 million, which
- -- is in practice infinite, and there is no need to check the range.
+ Node_High_Bound : constant :=
+ (if Standard'Address_Size = 32 then 299_999_999 else 1_999_999_999);
- Elist_Low_Bound : constant := 100_000_000;
+ Elist_Low_Bound : constant := -199_999_999;
-- The Elist_Id values are subscripts into an array of elist headers which
-- has Elist_Low_Bound as its lower bound.
- Elist_High_Bound : constant := 199_999_999;
- -- Maximum Elist_Id subscript value. This allows up to 100 million Elists,
- -- which is in practice infinite and there is no need to check the range.
+ Elist_High_Bound : constant := -100_000_000;
- Elmt_Low_Bound : constant := 200_000_000;
+ Elmt_Low_Bound : constant := -299_999_999;
-- Low bound of element Id values. The use of these values is internal to
-- the Elists package, but the definition of the range is included here
-- since it must be disjoint from other Id values. The Elmt_Id values are
-- subscripts into an array of list elements which has this as lower bound.
- Elmt_High_Bound : constant := 299_999_999;
- -- Upper bound of Elmt_Id values. This allows up to 100 million element
- -- list members, which is in practice infinite (no range check needed).
+ Elmt_High_Bound : constant := -200_000_000;
- Names_Low_Bound : constant := 300_000_000;
- -- Low bound for name Id values
+ Names_Low_Bound : constant := -399_999_999;
- Names_High_Bound : constant := 399_999_999;
- -- Maximum number of names that can be allocated is 100 million, which is
- -- in practice infinite and there is no need to check the range.
+ Names_High_Bound : constant := -300_000_000;
- Strings_Low_Bound : constant := 400_000_000;
- -- Low bound for string Id values
+ Strings_Low_Bound : constant := -499_999_999;
- Strings_High_Bound : constant := 499_999_999;
- -- Maximum number of strings that can be allocated is 100 million, which
- -- is in practice infinite and there is no need to check the range.
+ Strings_High_Bound : constant := -400_000_000;
- Ureal_Low_Bound : constant := 500_000_000;
- -- Low bound for Ureal values
+ Ureal_Low_Bound : constant := -599_999_999;
- Ureal_High_Bound : constant := 599_999_999;
- -- Maximum number of Ureal values stored is 100_000_000 which is in
- -- practice infinite so that no check is required.
+ Ureal_High_Bound : constant := -500_000_000;
- Uint_Low_Bound : constant := 600_000_000;
+ Uint_Low_Bound : constant := -2_100_000_000;
-- Low bound for Uint values
- Uint_Table_Start : constant := 2_000_000_000;
+ Uint_Table_Start : constant := -699_999_999;
-- Location where table entries for universal integers start (see
-- Uintp spec for details of the representation of Uint values).
- Uint_High_Bound : constant := 2_099_999_999;
- -- The range of Uint values is very large, since a substantial part
- -- of this range is used to store direct values, see Uintp for details.
+ Uint_High_Bound : constant := -600_000_000;
-- The following subtype definitions are used to provide convenient names
-- for membership tests on Int values to see what data type range they
/* Range definitions for Tree Data: */
-#define List_Low_Bound -100000000
+#define List_Low_Bound -99999999
#define List_High_Bound 0
#define Node_Low_Bound 0
-#define Node_High_Bound 99999999
+#define Node_High_Bound 1999999999
+/* Above is the correct value of Node_High_Bound for 64-bit machines. It is
+ wrong for 32-bit machines, but that doesn't matter. */
-#define Elist_Low_Bound 100000000
-#define Elist_High_Bound 199999999
+#define Elist_Low_Bound -199999999
+#define Elist_High_Bound -100000000
-#define Elmt_Low_Bound 200000000
-#define Elmt_High_Bound 299999999
+#define Elmt_Low_Bound -299999999
+#define Elmt_High_Bound -200000000
-#define Names_Low_Bound 300000000
-#define Names_High_Bound 399999999
+#define Names_Low_Bound -399999999
+#define Names_High_Bound -300000000
-#define Strings_Low_Bound 400000000
-#define Strings_High_Bound 499999999
+#define Strings_Low_Bound -499999999
+#define Strings_High_Bound -400000000
-#define Ureal_Low_Bound 500000000
-#define Ureal_High_Bound 599999999
+#define Ureal_Low_Bound -599999999
+#define Ureal_High_Bound -500000000
-#define Uint_Low_Bound 600000000
-#define Uint_Table_Start 2000000000
-#define Uint_High_Bound 2099999999
+#define Uint_Low_Bound -2100000000
+#define Uint_Table_Start -699999999
+#define Uint_High_Bound -600000000
SUBTYPE (List_Range, Int, List_Low_Bound, List_High_Bound)
SUBTYPE (Node_Range, Int, Node_Low_Bound, Node_High_Bound)