blob: cec5b94b6fc9c24d94894be541c87a648a537db5 [file] [log] [blame]
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- G E N _ I L . U T I L S --
-- --
-- B o d y --
-- --
-- Copyright (C) 2020-2022, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING3. If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
package body Gen_IL.Internals is
---------
-- Nil --
---------
procedure Nil (T : Node_Or_Entity_Type) is
begin
null;
end Nil;
--------------------
-- Node_Or_Entity --
--------------------
function Node_Or_Entity (Root : Root_Type) return String is
begin
if Root = Node_Kind then
return "Node";
else
return "Entity";
end if;
end Node_Or_Entity;
------------------------------
-- Num_Concrete_Descendants --
------------------------------
function Num_Concrete_Descendants
(T : Node_Or_Entity_Type) return Natural is
begin
return Concrete_Type'Pos (Type_Table (T).Last) -
Concrete_Type'Pos (Type_Table (T).First) + 1;
end Num_Concrete_Descendants;
function First_Abstract (Root : Root_Type) return Abstract_Type is
(case Root is
when Node_Kind => Abstract_Node'First,
when others => Abstract_Entity'First); -- Entity_Kind
function Last_Abstract (Root : Root_Type) return Abstract_Type is
(case Root is
when Node_Kind => Abstract_Node'Last,
when others => Abstract_Entity'Last); -- Entity_Kind
function First_Concrete (Root : Root_Type) return Concrete_Type is
(case Root is
when Node_Kind => Concrete_Node'First,
when others => Concrete_Entity'First); -- Entity_Kind
function Last_Concrete (Root : Root_Type) return Concrete_Type is
(case Root is
when Node_Kind => Concrete_Node'Last,
when others => Concrete_Entity'Last); -- Entity_Kind
function First_Field (Root : Root_Type) return Field_Enum is
(case Root is
when Node_Kind => Node_Field'First,
when others => Entity_Field'First); -- Entity_Kind
function Last_Field (Root : Root_Type) return Field_Enum is
(case Root is
when Node_Kind => Node_Field'Last,
when others => Entity_Field'Last); -- Entity_Kind
-----------------------
-- Verify_Type_Table --
-----------------------
procedure Verify_Type_Table is
begin
for T in Node_Or_Entity_Type loop
if Type_Table (T) /= null then
if not Type_Table (T).Is_Union then
case T is
when Concrete_Node | Concrete_Entity =>
pragma Assert (Type_Table (T).First = T);
pragma Assert (Type_Table (T).Last = T);
when Abstract_Node | Abstract_Entity =>
pragma Assert
(Type_Table (T).First < Type_Table (T).Last);
when Type_Boundaries =>
null;
end case;
end if;
end if;
end loop;
end Verify_Type_Table;
--------------
-- Id_Image --
--------------
function Id_Image (T : Type_Enum) return String is
begin
case T is
when Flag =>
return "Boolean";
when Node_Kind =>
return "Node_Id";
when Entity_Kind =>
return "Entity_Id";
when Node_Kind_Type =>
return "Node_Kind";
when Entity_Kind_Type =>
return "Entity_Kind";
when others =>
return Image (T) & "_Id";
end case;
end Id_Image;
----------------------
-- Get_Set_Id_Image --
----------------------
function Get_Set_Id_Image (T : Type_Enum) return String is
begin
case T is
when Node_Kind =>
return "Node_Id";
when Entity_Kind =>
return "Entity_Id";
when Node_Kind_Type =>
return "Node_Kind";
when Entity_Kind_Type =>
return "Entity_Kind";
when others =>
return Image (T);
end case;
end Get_Set_Id_Image;
-----------
-- Image --
-----------
function Image (T : Opt_Type_Enum) return String is
begin
case T is
-- We special case the following; otherwise the compiler will give
-- "wrong case" warnings in compiler code.
when N_Pop_xxx_Label =>
return "N_Pop_xxx_Label";
when N_Push_Pop_xxx_Label =>
return "N_Push_Pop_xxx_Label";
when N_Push_xxx_Label =>
return "N_Push_xxx_Label";
when N_Raise_xxx_Error =>
return "N_Raise_xxx_Error";
when N_SCIL_Node =>
return "N_SCIL_Node";
when N_SCIL_Dispatch_Table_Tag_Init =>
return "N_SCIL_Dispatch_Table_Tag_Init";
when N_SCIL_Dispatching_Call =>
return "N_SCIL_Dispatching_Call";
when N_SCIL_Membership_Test =>
return "N_SCIL_Membership_Test";
when others =>
return Capitalize (T'Img);
end case;
end Image;
------------------
-- Image_Sans_N --
------------------
function Image_Sans_N (T : Opt_Type_Enum) return String is
Im : constant String := Image (T);
pragma Assert (Im (1 .. 2) = "N_");
begin
return Im (3 .. Im'Last);
end Image_Sans_N;
-------------------------
-- Put_Types_With_Bars --
-------------------------
procedure Put_Types_With_Bars (S : in out Sink; U : Type_Vector) is
First_Time : Boolean := True;
begin
Increase_Indent (S, 3);
for T of U loop
if First_Time then
First_Time := False;
else
Put (S, LF & "| ");
end if;
Put (S, Image (T));
end loop;
Decrease_Indent (S, 3);
end Put_Types_With_Bars;
----------------------------
-- Put_Type_Ids_With_Bars --
----------------------------
procedure Put_Type_Ids_With_Bars (S : in out Sink; U : Type_Vector) is
First_Time : Boolean := True;
begin
Increase_Indent (S, 3);
for T of U loop
if First_Time then
First_Time := False;
else
Put (S, LF & "| ");
end if;
Put (S, Id_Image (T));
end loop;
Decrease_Indent (S, 3);
end Put_Type_Ids_With_Bars;
-----------
-- Image --
-----------
function Image (F : Opt_Field_Enum) return String is
begin
case F is
-- Special cases for the same reason as in the above Image
-- function for Opt_Type_Enum.
when Alloc_For_BIP_Return =>
return "Alloc_For_BIP_Return";
when Assignment_OK =>
return "Assignment_OK";
when Backwards_OK =>
return "Backwards_OK";
when BIP_Initialization_Call =>
return "BIP_Initialization_Call";
when Body_Needed_For_SAL =>
return "Body_Needed_For_SAL";
when Conversion_OK =>
return "Conversion_OK";
when CR_Discriminant =>
return "CR_Discriminant";
when DTC_Entity =>
return "DTC_Entity";
when DT_Entry_Count =>
return "DT_Entry_Count";
when DT_Offset_To_Top_Func =>
return "DT_Offset_To_Top_Func";
when DT_Position =>
return "DT_Position";
when Forwards_OK =>
return "Forwards_OK";
when Has_Inherited_DIC =>
return "Has_Inherited_DIC";
when Has_Own_DIC =>
return "Has_Own_DIC";
when Has_RACW =>
return "Has_RACW";
when Has_SP_Choice =>
return "Has_SP_Choice";
when Ignore_SPARK_Mode_Pragmas =>
return "Ignore_SPARK_Mode_Pragmas";
when Is_Constr_Subt_For_UN_Aliased =>
return "Is_Constr_Subt_For_UN_Aliased";
when Is_CPP_Class =>
return "Is_CPP_Class";
when Is_CUDA_Kernel =>
return "Is_CUDA_Kernel";
when Is_DIC_Procedure =>
return "Is_DIC_Procedure";
when Is_Discrim_SO_Function =>
return "Is_Discrim_SO_Function";
when Is_Elaboration_Checks_OK_Id =>
return "Is_Elaboration_Checks_OK_Id";
when Is_Elaboration_Checks_OK_Node =>
return "Is_Elaboration_Checks_OK_Node";
when Is_Elaboration_Warnings_OK_Id =>
return "Is_Elaboration_Warnings_OK_Id";
when Is_Elaboration_Warnings_OK_Node =>
return "Is_Elaboration_Warnings_OK_Node";
when Is_Known_Guaranteed_ABE =>
return "Is_Known_Guaranteed_ABE";
when Is_RACW_Stub_Type =>
return "Is_RACW_Stub_Type";
when Is_SPARK_Mode_On_Node =>
return "Is_SPARK_Mode_On_Node";
when Local_Raise_Not_OK =>
return "Local_Raise_Not_OK";
when LSP_Subprogram =>
return "LSP_Subprogram";
when OK_To_Rename =>
return "OK_To_Rename";
when Referenced_As_LHS =>
return "Referenced_As_LHS";
when RM_Size =>
return "RM_Size";
when SCIL_Controlling_Tag =>
return "SCIL_Controlling_Tag";
when SCIL_Entity =>
return "SCIL_Entity";
when SCIL_Tag_Value =>
return "SCIL_Tag_Value";
when SCIL_Target_Prim =>
return "SCIL_Target_Prim";
when Shift_Count_OK =>
return "Shift_Count_OK";
when SPARK_Aux_Pragma =>
return "SPARK_Aux_Pragma";
when SPARK_Aux_Pragma_Inherited =>
return "SPARK_Aux_Pragma_Inherited";
when SPARK_Pragma =>
return "SPARK_Pragma";
when SPARK_Pragma_Inherited =>
return "SPARK_Pragma_Inherited";
when Split_PPC =>
return "Split_PPC";
when SSO_Set_High_By_Default =>
return "SSO_Set_High_By_Default";
when SSO_Set_Low_By_Default =>
return "SSO_Set_Low_By_Default";
when TSS_Elist =>
return "TSS_Elist";
when others =>
return Capitalize (F'Img);
end case;
end Image;
function Image (Default : Field_Default_Value) return String is
(Capitalize (Default'Img));
-----------------
-- Value_Image --
-----------------
function Value_Image (Default : Field_Default_Value) return String is
begin
if Default = No_Default then
return Image (Default);
else
-- Strip off the prefix
declare
Im : constant String := Image (Default);
Prefix : constant String := "Default_";
begin
pragma Assert (Im (1 .. Prefix'Length) = Prefix);
return Im (Prefix'Length + 1 .. Im'Last);
end;
end if;
end Value_Image;
-------------------
-- Iterate_Types --
-------------------
procedure Iterate_Types
(Root : Node_Or_Entity_Type;
Pre, Post : not null access procedure (T : Node_Or_Entity_Type) :=
Nil'Access)
is
procedure Recursive (T : Node_Or_Entity_Type);
-- Recursive walk
procedure Recursive (T : Node_Or_Entity_Type) is
begin
Pre (T);
for Child of Type_Table (T).Children loop
Recursive (Child);
end loop;
Post (T);
end Recursive;
begin
Recursive (Root);
end Iterate_Types;
-------------------
-- Is_Descendant --
-------------------
function Is_Descendant (Ancestor, Descendant : Node_Or_Entity_Type)
return Boolean is
begin
if Ancestor = Descendant then
return True;
elsif Descendant in Root_Type then
return False;
else
return Is_Descendant (Ancestor, Type_Table (Descendant).Parent);
end if;
end Is_Descendant;
------------------------
-- Put_Type_Hierarchy --
------------------------
procedure Put_Type_Hierarchy (S : in out Sink; Root : Root_Type) is
Level : Natural := 0;
function Indentation return String is ((1 .. 3 * Level => ' '));
-- Indentation string of space characters. We can't use the Indent
-- primitive, because we want this indentation after the "--".
procedure Pre (T : Node_Or_Entity_Type);
procedure Post (T : Node_Or_Entity_Type);
-- Pre and Post actions passed to Iterate_Types
procedure Pre (T : Node_Or_Entity_Type) is
begin
Put (S, "-- " & Indentation & Image (T) & LF);
Level := Level + 1;
end Pre;
procedure Post (T : Node_Or_Entity_Type) is
begin
Level := Level - 1;
-- Put out an "end" line only if there are many descendants, for
-- an arbitrary definition of "many".
if Num_Concrete_Descendants (T) > 10 then
Put (S, "-- " & Indentation & "end " & Image (T) & LF);
end if;
end Post;
N_Or_E : constant String :=
(case Root is
when Node_Kind => "nodes",
when others => "entities"); -- Entity_Kind
-- Start of processing for Put_Type_Hierarchy
begin
Put (S, "-- Type hierarchy for " & N_Or_E & LF);
Put (S, "--" & LF);
Iterate_Types (Root, Pre'Access, Post'Access);
Put (S, "--" & LF);
Put (S, "-- End type hierarchy for " & N_Or_E & LF & LF);
end Put_Type_Hierarchy;
end Gen_IL.Internals;