From: Javier Miranda Date: Wed, 6 Jun 2007 10:20:45 +0000 (+0200) Subject: a-tags.ads, a-tags.adb (Tag_Size): This constant is now internal to the package. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d0dd5209d981a9705ea87c5e86211e8f0709bb7c;p=gcc.git a-tags.ads, a-tags.adb (Tag_Size): This constant is now internal to the package. 2007-04-20 Javier Miranda * a-tags.ads, a-tags.adb (Tag_Size): This constant is now internal to the package. (Object_Specific_Data_Array): This is now internal to the package. (Object_Specific_Data): This is now internal to the package. (Select_Specific_Data_Element): This is now internal to the package. (Select_Specific_Data_Array): This is now internal to the package. (Select_Specific_Data): This is now internal to the package. (Offset_To_Top_Function_Ptr): This is now public. (To_Offset_To_Top_Function_Ptr): Removed. (Storage_Offset_Ptr,To_Storage_Offset_Ptr): These declarations are now local to subprogram Offset_To_Top. (Predefined_DT): Removed. (Typeinfo_Ptr): Removed. (OSD): This function is now internal to this package. (SSD): This function is now internal to this package. (DT): New function that displaces the pointer to the table of primitives to get access to the enclosing wrapper record. (IW_Membership): Code cleanup. (Offset_To_Top): Code cleanup. (Predefined_DT): Removed. (Register_Interface_Tag): Removed. (Set_Interface_Table): Removed. (Set_Offset_Index): Removed. (Set_Offset_To_Top): Code cleanup. (Set_OSD): Removed. (Set_Signature): Removed. (Set_SSD): Removed. (Set_Tagged_Kind): Removed. (Typeinfo_Ptr): Removed. (TSD): Removed. (Displace): Add missing check on null actual. * exp_disp.ads, exp_disp.adb (Select_Expansion_Utilities): Removed. (Build_Common_Dispatching_Select_Statements): Moved to exp_atags. (Expand_Dispatching_Call): Update calls to Get_Prim_Op_Address because the interface requires a new parameter. (Make_Disp_Asynchronous_Select_Spec, Make_Disp_Conditional_Select_Spec, Make_Disp_Get_Prim_Op_Kind_Spec, Make_Disp_Timed_Select_Spec): Replace calls to subprograms Build_T, Build_S, etc. by the corresponding code. Done to remove package Select_Expansion_Utilities. (Make_DT): New implementation for statically allocated dispatch tables. (Make_Secondary_DT): Moved to the scope of Make_DT. (Register_Primitive): Code cleanup plus incoporate the use of the new function DT_Address_Attribute. (Expand_Interface_Thunk): The profile of this subprogram has been changed to return the Thunk_Id and the corresponding code. (Fill_DT_Entry): Removed. Its functionality is now provided by subprogram Register_Primitive. (Fill_Secondary_DT_Entry): Removed. Its functionality is now provided by subprogram Register_Primitive. (Register_Primitive): New subprogram that incorporates the previous functionalities of Fill_DT_Entry and Fill_Secondary_DT_Entry. (Build_Common_Dispatching_Select_Statements): Remove formal Typ. This was only required to call Make_DT_Access_Action, which is now removed. (Ada_Actions): Removed (Action_Is_Proc): Removed (Action_Nb_Arg): Removed Replace all the calls to Make_DT_Access_Action by direct calls to Make_Procedure_Call_Statement or Make_Function_Call. (Set_DTC_Entity_Value): New subprogram. (Set_All_DT_Position): Add call to new subprogram Set_DTC_Entity_Value. (Expand_Interface_Thunk): Add missing support for primitives that are functions with a controlling result (case in which there is no need to generate the thunk). * exp_atag.ads, exp_atag.adb (Build_DT): New subprogram that displaces the pointer to reference the base of the wrapper record. (Build_Typeinfo_Offset): Removed. (RTE_Tag_Node): Removed. (Build_Common_Dispatching_Select_Statements): Moved here from exp_disp (Build_Get_RC_Offset): Removed. (Build_Inherit_Predefined_Prims): Removed. (Build_Inherit_TSD: Removed. (Build_New_TSD): Removed. (Build_Set_External_Tag): Removed. (Build_Set_Predefined_Prim_Op_Address): Add documentation. (Build_Set_Prim_Op_Address): Add documentation. (Build_Set_TSD): Removed. * rtsfind.ads, rtsfind.adb (Load_Fail): If load fails and we are not in configurable run-time mode, then raise Unrecoverable_Error. (Text_IO_Kludge): Generate an error message if a run-time library is not available in a given run-time (ie. zfp run-time). (RTE_Record_Component): Add code to check that the component we search for is not found in two records in the given run-time package. (RE_DT_Offset_To_Top_Size, RE_DT_Predef_Prims_Size): Removed (RE_DT_Predef_Prims_Offset): New entity (RE_Static_Offset_To_Top): New entity (RE_HT_Link): New entity. (System_Address_Image): Addition of this run-time package. (RE_Address_Image): New entity. (RE_Abstract_Interface): Removed. (RE_Default_Prim_Op_Count): Removed. (RE_DT_Entry_Size): Removed. (RE_DT_Min_Prologue_Size): Removed. (RE_DT_Prologue_Size): Removed. (RE_Ifaces_Table_Ptr): Removed. (RE_Interface_Data_Ptr): Removed. (RE_Type_Specific_Data): Removed. (RE_Primary_DT): Removed. (RE_Register_Interface_Tag): Removed. (RE_Set_Offset_Index): Removed. (RE_Set_OSD): Removed. (RE_Set_SSD): Removed. (RE_Set_Signature): Removed. (RE_Set_Tagged_Kind): Removed. (RE_Address_Array): New entity. (RE_DT): New entity. (RE_Iface_Tag): New entity. (RE_Interfaces_Table): New entity. (RE_No_Dispatch_Table): New entity. (RE_NDT_Prims_Ptr): New entity. (RE_NDT_TSD): New entity. (RE_Num_Prims): New entity. (RE_Offset_To_Top_Function_Ptr): New entity. (RE_OSD_Table): New entity. (RE_OSD_Num_Prims): New entity. (RE_Predef_Prims): New entity (RE_Predef_Prims_Table_Ptr): New entity. (RE_Primary_DT): New entity. (RE_Signature): New entity. (RE_SSD): New entity. (RE_TSD): New entity. (RE_Type_Specific_Data): New entity. (RE_Tag_Kind): New entity. From-SVN: r125379 --- diff --git a/gcc/ada/a-tags.adb b/gcc/ada/a-tags.adb index 556265ac2fa..622087a08ad 100644 --- a/gcc/ada/a-tags.adb +++ b/gcc/ada/a-tags.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2006, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2007, 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- -- @@ -41,32 +41,40 @@ pragma Elaborate_All (System.HTable); package body Ada.Tags is - -- Object specific data types (see description in a-tags.ads) + ----------------------- + -- Local Subprograms -- + ----------------------- + + function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean; + -- Given the tag of an object and the tag associated to a type, return + -- true if Obj is in Typ'Class. - type Object_Specific_Data_Array is array (Positive range <>) of Positive; + function Get_External_Tag (T : Tag) return System.Address; + -- Returns address of a null terminated string containing the external name - type Object_Specific_Data (Nb_Prim : Positive) is record - OSD_Table : Object_Specific_Data_Array (1 .. Nb_Prim); - -- Table used in secondary DT to reference their counterpart in the - -- select specific data (in the TSD of the primary DT). This construct - -- is used in the handling of dispatching triggers in select statements. - -- Nb_Prim is the number of non-predefined primitive operations. - end record; + function Is_Primary_DT (T : Tag) return Boolean; + -- Given a tag returns True if it has the signature of a primary dispatch + -- table. This is Inline_Always since it is called from other Inline_ + -- Always subprograms where we want no out of line code to be generated. - -- Select specific data types + function Length (Str : Cstring_Ptr) return Natural; + -- Length of string represented by the given pointer (treating the string + -- as a C-style string, which is Nul terminated). - type Select_Specific_Data_Element is record - Index : Positive; - Kind : Prim_Op_Kind; - end record; + function OSD (T : Tag) return Object_Specific_Data_Ptr; + -- Ada 2005 (AI-251): Given a pointer T to a secondary dispatch table, + -- retrieve the address of the record containing the Object Specific + -- Data table. - type Select_Specific_Data_Array is - array (Positive range <>) of Select_Specific_Data_Element; + function SSD (T : Tag) return Select_Specific_Data_Ptr; + -- Ada 2005 (AI-251): Given a pointer T to a dispatch Table, retrieves the + -- address of the record containing the Select Specific Data in T's TSD. - type Select_Specific_Data (Nb_Prim : Positive) is record - SSD_Table : Select_Specific_Data_Array (1 .. Nb_Prim); - -- NOTE: Nb_Prim is the number of non-predefined primitive operations - end record; + pragma Inline_Always (CW_Membership); + pragma Inline_Always (Get_External_Tag); + pragma Inline_Always (Is_Primary_DT); + pragma Inline_Always (OSD); + pragma Inline_Always (SSD); --------------------------------------------- -- Unchecked Conversions for String Fields -- @@ -78,6 +86,17 @@ package body Ada.Tags is function To_Cstring_Ptr is new Unchecked_Conversion (System.Address, Cstring_Ptr); + -- Disable warnings on possible aliasing problem because we only use + -- use this function to convert tags found in the External_Tag of + -- locally defined tagged types. + + pragma Warnings (off); + + function To_Tag is + new Unchecked_Conversion (Integer_Address, Tag); + + pragma Warnings (on); + ------------------------------------------------ -- Unchecked Conversions for other components -- ------------------------------------------------ @@ -88,47 +107,93 @@ package body Ada.Tags is function To_Acc_Size is new Unchecked_Conversion (System.Address, Acc_Size); -- The profile of the implicitly defined _size primitive - type Offset_To_Top_Function_Ptr is - access function (This : System.Address) - return System.Storage_Elements.Storage_Offset; - -- Type definition used to call the function that is generated by the - -- expander in case of tagged types with discriminants that have secondary - -- dispatch tables. This function provides the Offset_To_Top value in this - -- specific case. + ------------------------------- + -- Inline_Always Subprograms -- + ------------------------------- - function To_Offset_To_Top_Function_Ptr is - new Unchecked_Conversion (System.Address, Offset_To_Top_Function_Ptr); + -- Inline_always subprograms must be placed before their first call to + -- avoid defeating the frontend inlining mechanism and thus ensure the + -- generation of their correct debug info. - type Storage_Offset_Ptr is access System.Storage_Elements.Storage_Offset; + ------------------- + -- CW_Membership -- + ------------------- - function To_Storage_Offset_Ptr is - new Unchecked_Conversion (System.Address, Storage_Offset_Ptr); + -- Canonical implementation of Classwide Membership corresponding to: - ----------------------- - -- Local Subprograms -- - ----------------------- + -- Obj in Typ'Class - function Is_Primary_DT (T : Tag) return Boolean; - pragma Inline_Always (Is_Primary_DT); - -- Given a tag returns True if it has the signature of a primary dispatch - -- table. This is Inline_Always since it is called from other Inline_ - -- Always subprograms where we want no out of line code to be generated. + -- Each dispatch table contains a reference to a table of ancestors (stored + -- in the first part of the Tags_Table) and a count of the level of + -- inheritance "Idepth". - function Length (Str : Cstring_Ptr) return Natural; - -- Length of string represented by the given pointer (treating the string - -- as a C-style string, which is Nul terminated). + -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are + -- contained in the dispatch table referenced by Obj'Tag . Knowing the + -- level of inheritance of both types, this can be computed in constant + -- time by the formula: + + -- TSD (Obj'tag).Tags_Table (TSD (Obj'tag).Idepth - TSD (Typ'tag).Idepth) + -- = Typ'tag + + function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean is + Obj_TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (Obj_Tag) - DT_Typeinfo_Ptr_Size); + Typ_TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (Typ_Tag) - DT_Typeinfo_Ptr_Size); + Obj_TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (Obj_TSD_Ptr.all); + Typ_TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (Typ_TSD_Ptr.all); + Pos : constant Integer := Obj_TSD.Idepth - Typ_TSD.Idepth; + begin + return Pos >= 0 and then Obj_TSD.Tags_Table (Pos) = Typ_Tag; + end CW_Membership; + + ---------------------- + -- Get_External_Tag -- + ---------------------- - function Predefined_DT (T : Tag) return Tag; - pragma Inline_Always (Predefined_DT); - -- Displace the Tag to reference the dispatch table containing the - -- predefined primitives. + function Get_External_Tag (T : Tag) return System.Address is + TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (TSD_Ptr.all); + begin + return To_Address (TSD.External_Tag); + end Get_External_Tag; - function Typeinfo_Ptr (T : Tag) return System.Address; - -- Returns the current value of the typeinfo_ptr component available in - -- the prologue of the dispatch table. + ------------------- + -- Is_Primary_DT -- + ------------------- - pragma Unreferenced (Typeinfo_Ptr); - -- These functions will be used for full compatibility with the C++ ABI + function Is_Primary_DT (T : Tag) return Boolean is + begin + return DT (T).Signature = Primary_DT; + end Is_Primary_DT; + + --------- + -- OSD -- + --------- + + function OSD (T : Tag) return Object_Specific_Data_Ptr is + OSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + begin + return To_Object_Specific_Data_Ptr (OSD_Ptr.all); + end OSD; + + --------- + -- SSD -- + --------- + + function SSD (T : Tag) return Select_Specific_Data_Ptr is + TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (TSD_Ptr.all); + begin + return TSD.SSD; + end SSD; ------------------------- -- External_Tag_HTable -- @@ -192,8 +257,12 @@ package body Ada.Tags is ----------------- function Get_HT_Link (T : Tag) return Tag is + TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (TSD_Ptr.all); begin - return TSD (T).HT_Link; + return TSD.HT_Link; end Get_HT_Link; ---------- @@ -213,39 +282,16 @@ package body Ada.Tags is ----------------- procedure Set_HT_Link (T : Tag; Next : Tag) is + TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (TSD_Ptr.all); begin - TSD (T).HT_Link := Next; + TSD.HT_Link := Next; end Set_HT_Link; end HTable_Subprograms; - ------------------- - -- CW_Membership -- - ------------------- - - -- Canonical implementation of Classwide Membership corresponding to: - - -- Obj in Typ'Class - - -- Each dispatch table contains a reference to a table of ancestors (stored - -- in the first part of the Tags_Table) and a count of the level of - -- inheritance "Idepth". - - -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are - -- contained in the dispatch table referenced by Obj'Tag . Knowing the - -- level of inheritance of both types, this can be computed in constant - -- time by the formula: - - -- TSD (Obj'tag).Tags_Table (TSD (Obj'tag).Idepth - TSD (Typ'tag).Idepth) - -- = Typ'tag - - function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean is - Pos : Integer; - begin - Pos := TSD (Obj_Tag).Idepth - TSD (Typ_Tag).Idepth; - return Pos >= 0 and then TSD (Obj_Tag).Tags_Table (Pos) = Typ_Tag; - end CW_Membership; - ------------------ -- Base_Address -- ------------------ @@ -265,14 +311,18 @@ package body Ada.Tags is is Iface_Table : Interface_Data_Ptr; Obj_Base : System.Address; - Obj_DT : Tag; - Obj_TSD : Type_Specific_Data_Ptr; + Obj_DT : Dispatch_Table_Ptr; + Obj_DT_Tag : Tag; begin - Obj_Base := This - Offset_To_Top (This); - Obj_DT := To_Tag_Ptr (Obj_Base).all; - Obj_TSD := TSD (Obj_DT); - Iface_Table := To_Interface_Data_Ptr (Obj_TSD.Ifaces_Table_Ptr); + if System."=" (This, System.Null_Address) then + return System.Null_Address; + end if; + + Obj_Base := Base_Address (This); + Obj_DT_Tag := To_Tag_Ptr (Obj_Base).all; + Obj_DT := DT (To_Tag_Ptr (Obj_Base).all); + Iface_Table := To_Type_Specific_Data_Ptr (Obj_DT.TSD).Interfaces_Table; if Iface_Table /= null then for Id in 1 .. Iface_Table.Nb_Ifaces loop @@ -288,14 +338,11 @@ package body Ada.Tags is -- to provide us with this value else - Obj_Base := - Obj_Base + - To_Offset_To_Top_Function_Ptr - (Iface_Table.Ifaces_Table (Id).Offset_To_Top_Func).all - (Obj_Base); + Obj_Base := Obj_Base + + Iface_Table.Ifaces_Table (Id).Offset_To_Top_Func.all + (Obj_Base); end if; - Obj_DT := To_Tag_Ptr (Obj_Base).all; return Obj_Base; end if; end loop; @@ -304,7 +351,7 @@ package body Ada.Tags is -- Check if T is an immediate ancestor. This is required to handle -- conversion of class-wide interfaces to tagged types. - if CW_Membership (Obj_DT, T) then + if CW_Membership (Obj_DT_Tag, T) then return Obj_Base; end if; @@ -313,6 +360,17 @@ package body Ada.Tags is raise Constraint_Error; end Displace; + -------- + -- DT -- + -------- + + function DT (T : Tag) return Dispatch_Table_Ptr is + Offset : constant SSE.Storage_Offset := + To_Dispatch_Table_Ptr (T).Prims_Ptr'Position; + begin + return To_Dispatch_Table_Ptr (To_Address (T) - Offset); + end DT; + ------------------- -- IW_Membership -- ------------------- @@ -329,20 +387,15 @@ package body Ada.Tags is function IW_Membership (This : System.Address; T : Tag) return Boolean is Iface_Table : Interface_Data_Ptr; - Last_Id : Natural; Obj_Base : System.Address; - Obj_DT : Tag; + Obj_DT : Dispatch_Table_Ptr; Obj_TSD : Type_Specific_Data_Ptr; begin - Obj_Base := This - Offset_To_Top (This); - Obj_DT := To_Tag_Ptr (Obj_Base).all; - Obj_TSD := TSD (Obj_DT); - Last_Id := Obj_TSD.Idepth; - - -- Look for the tag in the table of interfaces - - Iface_Table := To_Interface_Data_Ptr (Obj_TSD.Ifaces_Table_Ptr); + Obj_Base := Base_Address (This); + Obj_DT := DT (To_Tag_Ptr (Obj_Base).all); + Obj_TSD := To_Type_Specific_Data_Ptr (Obj_DT.TSD); + Iface_Table := Obj_TSD.Interfaces_Table; if Iface_Table /= null then for Id in 1 .. Iface_Table.Nb_Ifaces loop @@ -355,7 +408,7 @@ package body Ada.Tags is -- Look for the tag in the ancestor tags table. This is required for: -- Iface_CW in Typ'Class - for Id in 0 .. Last_Id loop + for Id in 0 .. Obj_TSD.Idepth loop if Obj_TSD.Tags_Table (Id) = T then return True; end if; @@ -384,14 +437,18 @@ package body Ada.Tags is ------------------- function Expanded_Name (T : Tag) return String is - Result : Cstring_Ptr; + Result : Cstring_Ptr; + TSD_Ptr : Addr_Ptr; + TSD : Type_Specific_Data_Ptr; begin if T = No_Tag then raise Tag_Error; end if; - Result := TSD (T).Expanded_Name; + TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all); + Result := TSD.Expanded_Name; return Result (1 .. Length (Result)); end Expanded_Name; @@ -400,14 +457,18 @@ package body Ada.Tags is ------------------ function External_Tag (T : Tag) return String is - Result : Cstring_Ptr; + Result : Cstring_Ptr; + TSD_Ptr : Addr_Ptr; + TSD : Type_Specific_Data_Ptr; begin if T = No_Tag then raise Tag_Error; end if; - Result := TSD (T).External_Tag; + TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all); + Result := TSD.External_Tag; return Result (1 .. Length (Result)); end External_Tag; @@ -420,15 +481,6 @@ package body Ada.Tags is return SSD (T).SSD_Table (Position).Index; end Get_Entry_Index; - ---------------------- - -- Get_External_Tag -- - ---------------------- - - function Get_External_Tag (T : Tag) return System.Address is - begin - return To_Address (TSD (T).External_Tag); - end Get_External_Tag; - ---------------------- -- Get_Prim_Op_Kind -- ---------------------- @@ -462,8 +514,12 @@ package body Ada.Tags is ------------------- function Get_RC_Offset (T : Tag) return SSE.Storage_Offset is + TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (TSD_Ptr.all); begin - return TSD (T).RC_Offset; + return TSD.RC_Offset; end Get_RC_Offset; --------------------- @@ -471,10 +527,8 @@ package body Ada.Tags is --------------------- function Get_Tagged_Kind (T : Tag) return Tagged_Kind is - Tagged_Kind_Ptr : constant System.Address := - To_Address (T) - K_Tagged_Kind; begin - return To_Tagged_Kind_Ptr (Tagged_Kind_Ptr).all; + return DT (T).Tag_Kind; end Get_Tagged_Kind; ----------------------------- @@ -482,11 +536,13 @@ package body Ada.Tags is ----------------------------- function Interface_Ancestor_Tags (T : Tag) return Tag_Array is - Iface_Table : Interface_Data_Ptr; + TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (TSD_Ptr.all); + Iface_Table : constant Interface_Data_Ptr := TSD.Interfaces_Table; begin - Iface_Table := To_Interface_Data_Ptr (TSD (T).Ifaces_Table_Ptr); - if Iface_Table = null then declare Table : Tag_Array (1 .. 0); @@ -510,17 +566,67 @@ package body Ada.Tags is -- Internal_Tag -- ------------------ + -- Internal tags have the following format: + -- "Internal tag at 16#ADDRESS#: " + + Internal_Tag_Header : constant String := "Internal tag at "; + Header_Separator : constant Character := '#'; + function Internal_Tag (External : String) return Tag is Ext_Copy : aliased String (External'First .. External'Last + 1); - Res : Tag; + Res : Tag := null; begin - -- Make a copy of the string representing the external tag with - -- a null at the end. + -- Handle locally defined tagged types + + if External'Length > Internal_Tag_Header'Length + and then + External (External'First .. + External'First + Internal_Tag_Header'Length - 1) + = Internal_Tag_Header + then + declare + Addr_First : constant Natural := + External'First + Internal_Tag_Header'Length; + Addr_Last : Natural; + Addr : Integer_Address; + + begin + -- Search the second separator (#) to identify the address + + Addr_Last := Addr_First; + + for J in 1 .. 2 loop + while Addr_Last <= External'Last + and then External (Addr_Last) /= Header_Separator + loop + Addr_Last := Addr_Last + 1; + end loop; + + -- Skip the first separator + + if J = 1 then + Addr_Last := Addr_Last + 1; + end if; + end loop; + + if Addr_Last <= External'Last then + Addr := + Integer_Address'Value (External (Addr_First .. Addr_Last)); + return To_Tag (Addr); + end if; + end; + + -- Handle library-level tagged types + + else + -- Make a copy of the string representing the external tag with + -- a null at the end. - Ext_Copy (External'Range) := External; - Ext_Copy (Ext_Copy'Last) := ASCII.NUL; - Res := External_Tag_HTable.Get (Ext_Copy'Address); + Ext_Copy (External'Range) := External; + Ext_Copy (Ext_Copy'Last) := ASCII.NUL; + Res := External_Tag_HTable.Get (Ext_Copy'Address); + end if; if Res = null then declare @@ -546,32 +652,30 @@ package body Ada.Tags is (Descendant : Tag; Ancestor : Tag) return Boolean is + D_TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (Descendant) + - DT_Typeinfo_Ptr_Size); + A_TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (Ancestor) - DT_Typeinfo_Ptr_Size); + D_TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (D_TSD_Ptr.all); + A_TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (A_TSD_Ptr.all); + begin return CW_Membership (Descendant, Ancestor) - and then TSD (Descendant).Access_Level = TSD (Ancestor).Access_Level; + and then D_TSD.Access_Level = A_TSD.Access_Level; end Is_Descendant_At_Same_Level; - ------------------- - -- Is_Primary_DT -- - ------------------- - - function Is_Primary_DT (T : Tag) return Boolean is - Signature : constant Storage_Offset_Ptr := - To_Storage_Offset_Ptr (To_Address (T) - K_Signature); - Sig_Values : constant Signature_Values := - To_Signature_Values (Signature.all); - begin - return Sig_Values (2) = Primary_DT; - end Is_Primary_DT; - ------------ -- Length -- ------------ function Length (Str : Cstring_Ptr) return Natural is - Len : Integer := 1; + Len : Integer; begin + Len := 1; while Str (Len) /= ASCII.Nul loop Len := Len + 1; end loop; @@ -584,31 +688,26 @@ package body Ada.Tags is ------------------- function Offset_To_Top - (This : System.Address) return System.Storage_Elements.Storage_Offset + (This : System.Address) return SSE.Storage_Offset is - Curr_DT : constant Tag := To_Tag_Ptr (This).all; - Offset_To_Top : Storage_Offset_Ptr; - begin - Offset_To_Top := To_Storage_Offset_Ptr - (To_Address (Curr_DT) - K_Offset_To_Top); - - if Offset_To_Top.all = SSE.Storage_Offset'Last then - Offset_To_Top := To_Storage_Offset_Ptr (This + Tag_Size); - end if; + Tag_Size : constant SSE.Storage_Count := + SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit)); - return Offset_To_Top.all; - end Offset_To_Top; + type Storage_Offset_Ptr is access SSE.Storage_Offset; + function To_Storage_Offset_Ptr is + new Unchecked_Conversion (System.Address, Storage_Offset_Ptr); - --------- - -- OSD -- - --------- + Curr_DT : Dispatch_Table_Ptr; - function OSD (T : Tag) return Object_Specific_Data_Ptr is - OSD_Ptr : constant Addr_Ptr := - To_Addr_Ptr (To_Address (T) - K_Typeinfo); begin - return To_Object_Specific_Data_Ptr (OSD_Ptr.all); - end OSD; + Curr_DT := DT (To_Tag_Ptr (This).all); + + if Curr_DT.Offset_To_Top = SSE.Storage_Offset'Last then + return To_Storage_Offset_Ptr (This + Tag_Size).all; + else + return Curr_DT.Offset_To_Top; + end if; + end Offset_To_Top; ----------------- -- Parent_Size -- @@ -626,16 +725,28 @@ package body Ada.Tags is -- The pointer to the _size primitive is always in the first slot of -- the dispatch table. - Parent_Tag : Tag; - -- The tag of the parent type through the dispatch table - - F : Acc_Size; + TSD_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD : constant Type_Specific_Data_Ptr := + To_Type_Specific_Data_Ptr (TSD_Ptr.all); + -- Pointer to the TSD + + Parent_Tag : constant Tag := TSD.Tags_Table (Parent_Slot); + Parent_Predef_Prims_Ptr : constant Addr_Ptr := + To_Addr_Ptr (To_Address (Parent_Tag) + - DT_Predef_Prims_Offset); + Parent_Predef_Prims : constant Predef_Prims_Table_Ptr := + To_Predef_Prims_Table_Ptr + (Parent_Predef_Prims_Ptr.all); + + -- The tag of the parent type through the dispatch table and its + -- Predef_Prims field. + + F : constant Acc_Size := + To_Acc_Size (Parent_Predef_Prims (Size_Slot)); -- Access to the _size primitive of the parent begin - Parent_Tag := TSD (T).Tags_Table (Parent_Slot); - F := To_Acc_Size (Predefined_DT (Parent_Tag).Prims_Ptr (Size_Slot)); - -- Here we compute the size of the _parent field of the object return SSE.Storage_Count (F.all (Obj)); @@ -646,50 +757,29 @@ package body Ada.Tags is ---------------- function Parent_Tag (T : Tag) return Tag is + TSD_Ptr : Addr_Ptr; + TSD : Type_Specific_Data_Ptr; + begin if T = No_Tag then raise Tag_Error; end if; + TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size); + TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all); + -- The Parent_Tag of a root-level tagged type is defined to be No_Tag. -- The first entry in the Ancestors_Tags array will be null for such -- a type, but it's better to be explicit about returning No_Tag in -- this case. - if TSD (T).Idepth = 0 then + if TSD.Idepth = 0 then return No_Tag; else - return TSD (T).Tags_Table (1); + return TSD.Tags_Table (1); end if; end Parent_Tag; - ------------------- - -- Predefined_DT -- - ------------------- - - function Predefined_DT (T : Tag) return Tag is - begin - return To_Tag (To_Address (T) - DT_Prologue_Size); - end Predefined_DT; - - ---------------------------- - -- Register_Interface_Tag -- - ---------------------------- - - procedure Register_Interface_Tag - (T : Tag; - Interface_T : Tag; - Position : Positive) - is - New_T_TSD : Type_Specific_Data_Ptr; - Iface_Table : Interface_Data_Ptr; - - begin - New_T_TSD := TSD (T); - Iface_Table := To_Interface_Data_Ptr (New_T_TSD.Ifaces_Table_Ptr); - Iface_Table.Ifaces_Table (Position).Iface_Tag := Interface_T; - end Register_Interface_Tag; - ------------------ -- Register_Tag -- ------------------ @@ -712,86 +802,54 @@ package body Ada.Tags is SSD (T).SSD_Table (Position).Index := Value; end Set_Entry_Index; - ------------------------- - -- Set_Interface_Table -- - ------------------------- - - procedure Set_Interface_Table (T : Tag; Value : System.Address) is - begin - TSD (T).Ifaces_Table_Ptr := Value; - end Set_Interface_Table; - - ---------------------- - -- Set_Offset_Index -- - ---------------------- - - procedure Set_Offset_Index - (T : Tag; - Position : Positive; - Value : Positive) - is - begin - OSD (T).OSD_Table (Position) := Value; - end Set_Offset_Index; - ----------------------- -- Set_Offset_To_Top -- ----------------------- procedure Set_Offset_To_Top - (This : System.Address; - Interface_T : Tag; - Is_Static : Boolean; - Offset_Value : System.Storage_Elements.Storage_Offset; - Offset_Func : System.Address) + (This : System.Address; + Interface_T : Tag; + Is_Static : Boolean; + Offset_Value : SSE.Storage_Offset; + Offset_Func : Offset_To_Top_Function_Ptr) is - Prim_DT : Tag; - Sec_Base : System.Address; - Sec_DT : Tag; - Offset_To_Top : Storage_Offset_Ptr; - Iface_Table : Interface_Data_Ptr; - Obj_TSD : Type_Specific_Data_Ptr; - begin - if System."=" (This, System.Null_Address) then - Offset_To_Top := - To_Storage_Offset_Ptr (To_Address (Interface_T) - K_Offset_To_Top); - Offset_To_Top.all := Offset_Value; - return; - end if; - - -- "This" points to the primary DT and we must save Offset_Value in the - -- Offset_To_Top field of the corresponding secondary dispatch table. - - Prim_DT := To_Tag_Ptr (This).all; + Prim_DT : Dispatch_Table_Ptr; + Sec_Base : System.Address; + Sec_DT : Dispatch_Table_Ptr; + Iface_Table : Interface_Data_Ptr; - -- Save the offset to top field in the secondary dispatch table. + begin + -- Save the offset to top field in the secondary dispatch table if Offset_Value /= 0 then Sec_Base := This + Offset_Value; - Sec_DT := To_Tag_Ptr (Sec_Base).all; - Offset_To_Top := - To_Storage_Offset_Ptr (To_Address (Sec_DT) - K_Offset_To_Top); + Sec_DT := DT (To_Tag_Ptr (Sec_Base).all); if Is_Static then - Offset_To_Top.all := Offset_Value; + Sec_DT.Offset_To_Top := Offset_Value; else - Offset_To_Top.all := SSE.Storage_Offset'Last; + Sec_DT.Offset_To_Top := SSE.Storage_Offset'Last; end if; end if; - -- Save Offset_Value in the table of interfaces of the primary DT. This - -- data will be used by the subprogram "Displace" to give support to - -- backward abstract interface type conversions. + -- "This" points to the primary DT and we must save Offset_Value in + -- the Offset_To_Top field of the corresponding secondary dispatch + -- table. + + Prim_DT := DT (To_Tag_Ptr (This).all); + Iface_Table := To_Type_Specific_Data_Ptr (Prim_DT.TSD).Interfaces_Table; - Obj_TSD := TSD (Prim_DT); - Iface_Table := To_Interface_Data_Ptr (Obj_TSD.Ifaces_Table_Ptr); + -- Save Offset_Value in the table of interfaces of the primary DT. + -- This data will be used by the subprogram "Displace" to give support + -- to backward abstract interface type conversions. -- Register the offset in the table of interfaces if Iface_Table /= null then for Id in 1 .. Iface_Table.Nb_Ifaces loop if Iface_Table.Ifaces_Table (Id).Iface_Tag = Interface_T then - Iface_Table.Ifaces_Table (Id).Static_Offset_To_Top := Is_Static; + Iface_Table.Ifaces_Table (Id).Static_Offset_To_Top := + Is_Static; if Is_Static then Iface_Table.Ifaces_Table (Id).Offset_To_Top_Value @@ -811,17 +869,6 @@ package body Ada.Tags is raise Program_Error; end Set_Offset_To_Top; - ------------- - -- Set_OSD -- - ------------- - - procedure Set_OSD (T : Tag; Value : System.Address) is - OSD_Ptr : constant Addr_Ptr := - To_Addr_Ptr (To_Address (T) - K_Typeinfo); - begin - OSD_Ptr.all := Value; - end Set_OSD; - ---------------------- -- Set_Prim_Op_Kind -- ---------------------- @@ -835,70 +882,6 @@ package body Ada.Tags is SSD (T).SSD_Table (Position).Kind := Value; end Set_Prim_Op_Kind; - ------------------- - -- Set_Signature -- - ------------------- - - procedure Set_Signature (T : Tag; Value : Signature_Kind) is - Signature : constant System.Address := To_Address (T) - K_Signature; - Sig_Ptr : constant Signature_Values_Ptr := - To_Signature_Values_Ptr (Signature); - begin - Sig_Ptr.all (1) := Valid_Signature; - Sig_Ptr.all (2) := Value; - end Set_Signature; - - ------------- - -- Set_SSD -- - ------------- - - procedure Set_SSD (T : Tag; Value : System.Address) is - begin - TSD (T).SSD_Ptr := Value; - end Set_SSD; - - --------------------- - -- Set_Tagged_Kind -- - --------------------- - - procedure Set_Tagged_Kind (T : Tag; Value : Tagged_Kind) is - Tagged_Kind_Ptr : constant System.Address := - To_Address (T) - K_Tagged_Kind; - begin - To_Tagged_Kind_Ptr (Tagged_Kind_Ptr).all := Value; - end Set_Tagged_Kind; - - --------- - -- SSD -- - --------- - - function SSD (T : Tag) return Select_Specific_Data_Ptr is - begin - return To_Select_Specific_Data_Ptr (TSD (T).SSD_Ptr); - end SSD; - - ------------------ - -- Typeinfo_Ptr -- - ------------------ - - function Typeinfo_Ptr (T : Tag) return System.Address is - TSD_Ptr : constant Addr_Ptr := - To_Addr_Ptr (To_Address (T) - K_Typeinfo); - begin - return TSD_Ptr.all; - end Typeinfo_Ptr; - - --------- - -- TSD -- - --------- - - function TSD (T : Tag) return Type_Specific_Data_Ptr is - TSD_Ptr : constant Addr_Ptr := - To_Addr_Ptr (To_Address (T) - K_Typeinfo); - begin - return To_Type_Specific_Data_Ptr (TSD_Ptr.all); - end TSD; - ------------------------ -- Wide_Expanded_Name -- ------------------------ diff --git a/gcc/ada/a-tags.ads b/gcc/ada/a-tags.ads index bc39cd509e2..538c3e97af2 100644 --- a/gcc/ada/a-tags.ads +++ b/gcc/ada/a-tags.ads @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2006, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2007, Free Software Foundation, Inc. -- -- -- -- This specification is derived from the Ada Reference Manual for use with -- -- GNAT. The copyright notice above, and the license provisions that follow -- @@ -37,7 +37,7 @@ with System; with System.Storage_Elements; -with Unchecked_Conversion; +with Ada.Unchecked_Conversion; package Ada.Tags is pragma Preelaborate_05; @@ -83,18 +83,16 @@ package Ada.Tags is private -- Structure of the GNAT Primary Dispatch Table - -- +--------------------+ - -- | table of | - -- :predefined primitive: - -- | ops pointers | -- +--------------------+ -- | Signature | -- +--------------------+ -- | Tagged_Kind | - -- +--------------------+ - -- | Offset_To_Top | - -- +--------------------+ - -- |Typeinfo_Ptr/TSD_Ptr---> Type Specific Data + -- +--------------------+ Predef Prims + -- | Predef_Prims -----------------------------> +------------+ + -- +--------------------+ | table of | + -- | Offset_To_Top | | predefined | + -- +--------------------+ | primitives | + -- |Typeinfo_Ptr/TSD_Ptr---> Type Specific Data +------------+ -- Tag ---> +--------------------+ +-------------------+ -- | table of | | inheritance depth | -- : primitive ops : +-------------------+ @@ -110,16 +108,14 @@ private -- +-------------------+ -- | rec ctrler offset | -- +-------------------+ - -- | num prim ops | - -- +-------------------+ - -- | Ifaces_Table_Ptr --> Interface Data + -- | Ifaces_Table ---> Interface Data -- +-------------------+ +------------+ - -- Select Specific Data <---- SSD_Ptr | | table | - -- +------------------+ +-------------------+ : of : - -- |table of primitive| | table of | | interfaces | - -- : operation : : ancestor : +------------+ - -- | kinds | | tags | - -- +------------------+ +-------------------+ + -- Select Specific Data <---- SSD | | Nb_Ifaces | + -- +------------------+ +-------------------+ +------------+ + -- |table of primitive| | table of | | table | + -- : operation : : ancestor : : of : + -- | kinds | | tags | | interfaces | + -- +------------------+ +-------------------+ +------------+ -- |table of | -- : entry : -- | indices | @@ -148,77 +144,88 @@ private -- +---------------+ -- The runtime information kept for each tagged type is separated into two - -- objects: the Dispatch Table and the Type Specific Data record. These - -- two objects are allocated statically using the constants: - - -- DT Size = DT_Prologue_Size + Nb_Prim * DT_Entry_Size - - -- where Nb_prim is the number of primitive operations of the given - -- type and Idepth its inheritance depth. - - type Address_Array is array (Natural range <>) of System.Address; - pragma Suppress (Index_Check, On => Address_Array); - -- The reason we suppress index checks is that in the dispatch table, - -- the component of this type is declared with a dummy size of 1, the - -- actual size depending on the number of primitive operations. - - type Dispatch_Table is record - - -- According to the C++ ABI the components Offset_To_Top and - -- Typeinfo_Ptr are stored just "before" the dispatch table (that is, - -- the Prims_Ptr table), and they are referenced with negative offsets - -- referring to the base of the dispatch table. The _Tag (or the - -- VTable_Ptr in C++ terminology) must point to the base of the virtual - -- table, just after these components, to point to the Prims_Ptr table. - -- For this purpose the expander generates a Prims_Ptr table that has - -- enough space for these additional components, and generates code that - -- displaces the _Tag to point after these components. - - -- Signature : Signature_Kind; - -- Tagged_Kind : Tagged_Kind; - -- Offset_To_Top : Natural; - -- Typeinfo_Ptr : System.Address; - - Prims_Ptr : Address_Array (1 .. 1); - -- The size of the Prims_Ptr array actually depends on the tagged type - -- to which it applies. For each tagged type, the expander computes the - -- actual array size, allocates the Dispatch_Table record accordingly, - -- and generates code that displaces the base of the record after the - -- Typeinfo_Ptr component. For this reason the first two components have - -- been commented in the previous declaration. The access to these - -- components is done by means of local functions. - -- - -- To avoid the use of discriminants to define the actual size of the - -- dispatch table, we used to declare the tag as a pointer to a record - -- that contains an arbitrary array of addresses, using Positive as its - -- index. This ensures that there are never range checks when accessing - -- the dispatch table, but it prevents GDB from displaying tagged types - -- properly. A better approach is to declare this record type as holding - -- small number of addresses, and to explicitly suppress checks on it. - -- - -- Note that in both cases, this type is never allocated, and serves - -- only to declare the corresponding access type. - end record; + -- objects: the Dispatch Table and the Type Specific Data record. + + package SSE renames System.Storage_Elements; subtype Cstring is String (Positive); type Cstring_Ptr is access all Cstring; pragma No_Strict_Aliasing (Cstring_Ptr); - -- We suppress index checks because the declared size in the record below - -- is a dummy size of one (see below). + -- Declarations for the table of interfaces - type Tag_Table is array (Natural range <>) of Tag; - pragma Suppress_Initialization (Tag_Table); - pragma Suppress (Index_Check, On => Tag_Table); + type Offset_To_Top_Function_Ptr is + access function (This : System.Address) return SSE.Storage_Offset; + -- Type definition used to call the function that is generated by the + -- expander in case of tagged types with discriminants that have secondary + -- dispatch tables. This function provides the Offset_To_Top value in this + -- specific case. - package SSE renames System.Storage_Elements; + type Interface_Data_Element is record + Iface_Tag : Tag; + Static_Offset_To_Top : Boolean; + Offset_To_Top_Value : SSE.Storage_Offset; + Offset_To_Top_Func : Offset_To_Top_Function_Ptr; + end record; + -- If some ancestor of the tagged type has discriminants the field + -- Static_Offset_To_Top is False and the field Offset_To_Top_Func + -- is used to store the access to the function generated by the + -- expander which provides this value; otherwise Static_Offset_To_Top + -- is True and such value is stored in the Offset_To_Top_Value field. - -- Type specific data types + type Interfaces_Array is array (Natural range <>) of Interface_Data_Element; + + type Interface_Data (Nb_Ifaces : Positive) is record + Ifaces_Table : Interfaces_Array (1 .. Nb_Ifaces); + end record; + + type Interface_Data_Ptr is access all Interface_Data; + -- Table of abstract interfaces used to give support to backward interface + -- conversions and also to IW_Membership. + + -- Primitive operation kinds. These values differentiate the kinds of + -- callable entities stored in the dispatch table. Certain kinds may + -- not be used, but are added for completeness. + + type Prim_Op_Kind is + (POK_Function, + POK_Procedure, + POK_Protected_Entry, + POK_Protected_Function, + POK_Protected_Procedure, + POK_Task_Entry, + POK_Task_Function, + POK_Task_Procedure); + + -- Select specific data types + + type Select_Specific_Data_Element is record + Index : Positive; + Kind : Prim_Op_Kind; + end record; + + type Select_Specific_Data_Array is + array (Positive range <>) of Select_Specific_Data_Element; + + type Select_Specific_Data (Nb_Prim : Positive) is record + SSD_Table : Select_Specific_Data_Array (1 .. Nb_Prim); + -- NOTE: Nb_Prim is the number of non-predefined primitive operations + end record; + + type Select_Specific_Data_Ptr is access all Select_Specific_Data; + -- A table used to store the primitive operation kind and entry index of + -- primitive subprograms of a type that implements a limited interface. + -- The Select Specific Data table resides in the Type Specific Data of a + -- type. This construct is used in the handling of dispatching triggers + -- in select statements. + + type Tag_Table is array (Natural range <>) of Tag; type Type_Specific_Data (Idepth : Natural) is record - -- Inheritance Depth Level: Used to implement the membership test - -- associated with single inheritance of tagged types in constant-time. - -- It also indicates the size of the Tags_Table component. + -- The discriminant Idepth is the Inheritance Depth Level: Used to + -- implement the membership test associated with single inheritance of + -- tagged types in constant-time. It also indicates the size of the + -- Tags_Table component. Access_Level : Natural; -- Accessibility level required to give support to Ada 2005 nested type @@ -232,22 +239,29 @@ private Expanded_Name : Cstring_Ptr; External_Tag : Cstring_Ptr; HT_Link : Tag; - -- Components used to support to the Ada.Tags subprograms in RM 3.9. - -- Note: Expanded_Name is referenced by GDB ??? + -- Components used to support to the Ada.Tags subprograms in RM 3.9 + + -- Note: Expanded_Name is referenced by GDB to determine the actual name + -- of the tagged type. Its requirements are: 1) it must have this exact + -- name, and 2) its contents must point to a C-style Nul terminated + -- string containing its expanded name. GDB has no requirement on a + -- given position inside the record. - Remotely_Callable : Boolean; - -- Used to check ARM E.4 (18) + Transportable : Boolean; + -- Used to check RM E.4(18), set for types that satisfy the requirements + -- for being used in remote calls as actuals for classwide formals or as + -- return values for classwide functions. RC_Offset : SSE.Storage_Offset; -- Controller Offset: Used to give support to tagged controlled objects -- (see Get_Deep_Controller at s-finimp) - Ifaces_Table_Ptr : System.Address; + Interfaces_Table : Interface_Data_Ptr; -- Pointer to the table of interface tags. It is used to implement the -- membership test associated with interfaces and also for backward -- abstract interface type conversions (Ada 2005:AI-251) - SSD_Ptr : System.Address; + SSD : Select_Specific_Data_Ptr; -- Pointer to a table of records used in dispatching selects. This -- field has a meaningful value for all tagged types that implement -- a limited, protected, synchronized or task interfaces and have @@ -258,66 +272,14 @@ private -- depth level of the tagged type. end record; - -- Declarations for the table of interfaces - - type Interface_Data_Element is record - Iface_Tag : Tag; - Static_Offset_To_Top : Boolean; - Offset_To_Top_Value : System.Storage_Elements.Storage_Offset; - Offset_To_Top_Func : System.Address; - end record; - -- If some ancestor of the tagged type has discriminants the field - -- Static_Offset_To_Top is False and the field Offset_To_Top_Func - -- is used to store the address of the function generated by the - -- expander which provides this value; otherwise Static_Offset_To_Top - -- is True and such value is stored in the Offset_To_Top_Value field. - - type Interfaces_Array is - array (Natural range <>) of Interface_Data_Element; - - type Interface_Data (Nb_Ifaces : Positive) is record - Ifaces_Table : Interfaces_Array (1 .. Nb_Ifaces); - end record; - - -- Declaration of tag types - - type Tag is access all Dispatch_Table; - type Tag_Ptr is access Tag; - type Interface_Tag is access all Dispatch_Table; type Type_Specific_Data_Ptr is access all Type_Specific_Data; - No_Tag : constant Tag := null; + -- Declarations for the dispatch table record - type Interface_Data_Ptr is access all Interface_Data; - -- Table of abstract interfaces used to give support to backward interface - -- conversions and also to IW_Membership. - - type Object_Specific_Data (Nb_Prim : Positive); - type Object_Specific_Data_Ptr is access all Object_Specific_Data; - -- Information associated with the secondary dispatch table of tagged-type - -- objects implementing abstract interfaces. - - type Select_Specific_Data (Nb_Prim : Positive); - type Select_Specific_Data_Ptr is access all Select_Specific_Data; - -- A table used to store the primitive operation kind and entry index of - -- primitive subprograms of a type that implements a limited interface. - -- The Select Specific Data table resides in the Type Specific Data of a - -- type. This construct is used in the handling of dispatching triggers - -- in select statements. - - -- Primitive operation kinds. These values differentiate the kinds of - -- callable entities stored in the dispatch table. Certain kinds may - -- not be used, but are added for completeness. - - type Prim_Op_Kind is - (POK_Function, - POK_Procedure, - POK_Protected_Entry, - POK_Protected_Function, - POK_Protected_Procedure, - POK_Task_Entry, - POK_Task_Function, - POK_Task_Procedure); + type Signature_Kind is + (Unknown, + Primary_DT, + Secondary_DT); -- Tagged type kinds with respect to concurrency and limitedness @@ -329,53 +291,66 @@ private TK_Tagged, TK_Task); - type Tagged_Kind_Ptr is access all Tagged_Kind; + type Address_Array is array (Positive range <>) of System.Address; + + type Dispatch_Table_Wrapper (Num_Prims : Natural) is record + Signature : Signature_Kind; + Tag_Kind : Tagged_Kind; + Predef_Prims : System.Address; + -- Pointer to the dispatch table of predefined Ada primitives + + -- According to the C++ ABI the components Offset_To_Top and TSD are + -- stored just "before" the dispatch table, and they are referenced with + -- negative offsets referring to the base of the dispatch table. The + -- _Tag (or the VTable_Ptr in C++ terminology) must point to the base + -- of the virtual table, just after these components, to point to the + -- Prims_Ptr table. + + Offset_To_Top : SSE.Storage_Offset; + TSD : System.Address; + + Prims_Ptr : aliased Address_Array (1 .. Num_Prims); + -- The size of the Prims_Ptr array actually depends on the tagged type + -- to which it applies. For each tagged type, the expander computes the + -- actual array size, allocates the Dispatch_Table record accordingly. + end record; + + subtype Dispatch_Table is Address_Array (1 .. 1); + -- Used by GDB to identify the _tags and traverse the run-time structure + -- associated with tagged types. For compatibility with older versions of + -- gdb, its name must not be changed. + + type Tag is access all Dispatch_Table; + type Interface_Tag is access all Dispatch_Table; + + No_Tag : constant Tag := null; + + -- The expander ensures that Tag objects reference the Prims_Ptr component + -- of the wrapper. + + type Tag_Ptr is access all Tag; + type Dispatch_Table_Ptr is access all Dispatch_Table_Wrapper; + + -- The following type declaration is used by the compiler when the program + -- is compiled with restriction No_Dispatching_Calls. It is also used with + -- interface types to generate the tag and run-time information associated + -- with them. + + type No_Dispatch_Table_Wrapper is record + NDT_TSD : System.Address; + NDT_Prims_Ptr : Natural; + end record; Default_Prim_Op_Count : constant Positive := 15; - -- Maximum number of predefined primitive operations of a tagged type. + -- Number of predefined ada primitives: Size, Alignment, Read, Write, + -- Input, Output, "=", assignment, deep adjust, deep finalize, async + -- select, conditional select, prim_op kind, task_id, and timed select. - type Signature_Kind is - (Unknown, - Valid_Signature, - Primary_DT, - Secondary_DT, - Abstract_Interface); - for Signature_Kind'Size use 8; - -- Kind of signature found in the header of the dispatch table. These - -- signatures are generated by the frontend and are used by the Check_XXX - -- routines to ensure that the kind of dispatch table managed by each of - -- the routines in this package is correct. This additional check is only - -- performed with this run-time package is compiled with assertions enabled - - -- The signature is a sequence of two bytes. The first byte must have the - -- value Valid_Signature, and the second byte must have a value in the - -- range Primary_DT .. Abstract_Interface. The Unknown value is used by - -- the Check_XXX routines to indicate that the signature is wrong. - - DT_Min_Prologue_Size : constant SSE.Storage_Count := + DT_Predef_Prims_Size : constant SSE.Storage_Count := SSE.Storage_Count - (2 * (Standard'Address_Size / + (1 * (Standard'Address_Size / System.Storage_Unit)); - -- Size of the hidden part of the dispatch table used when the program - -- is compiled under restriction No_Dispatching_Calls. It contains the - -- pointer to the TSD record plus a dummy entry whose address is used - -- at run-time as the Tag. - - DT_Prologue_Size : constant SSE.Storage_Count := - SSE.Storage_Count - ((Default_Prim_Op_Count + 4) * - (Standard'Address_Size / System.Storage_Unit)); - -- Size of the hidden part of the dispatch table. It contains the table of - -- predefined primitive operations plus the C++ ABI header. - - DT_Signature_Size : constant SSE.Storage_Count := - SSE.Storage_Count - (1 * (Standard'Address_Size / System.Storage_Unit)); - -- Size of the Signature field of the dispatch table - - DT_Tagged_Kind_Size : constant SSE.Storage_Count := - SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit)); - -- Size of the Tagged_Type_Kind field of the dispatch table + -- Size of the Predef_Prims field of the Dispatch_Table DT_Offset_To_Top_Size : constant SSE.Storage_Count := SSE.Storage_Count @@ -389,28 +364,27 @@ private System.Storage_Unit)); -- Size of the Typeinfo_Ptr field of the Dispatch Table - DT_Entry_Size : constant SSE.Storage_Count := - SSE.Storage_Count - (1 * (Standard'Address_Size / System.Storage_Unit)); - -- Size of each primitive operation entry in the Dispatch Table - - Tag_Size : constant SSE.Storage_Count := - SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit)); - -- Size of each tag - - -- Constants used by the code generated by the frontend to get access - -- to the header of the dispatch table. - - K_Typeinfo : constant SSE.Storage_Count := DT_Typeinfo_Ptr_Size; - K_Offset_To_Top : constant SSE.Storage_Count := - System.Storage_Elements."+" - (K_Typeinfo, DT_Offset_To_Top_Size); - K_Tagged_Kind : constant SSE.Storage_Count := - System.Storage_Elements."+" - (K_Offset_To_Top, DT_Tagged_Kind_Size); - K_Signature : constant SSE.Storage_Count := - System.Storage_Elements."+" - (K_Tagged_Kind, DT_Signature_Size); + use type System.Storage_Elements.Storage_Offset; + + DT_Predef_Prims_Offset : constant SSE.Storage_Count := + DT_Typeinfo_Ptr_Size + + DT_Offset_To_Top_Size + + DT_Predef_Prims_Size; + -- Offset from Prims_Ptr to Predef_Prims component + + -- Object Specific Data record of secondary dispatch tables + + type Object_Specific_Data_Array is array (Positive range <>) of Positive; + + type Object_Specific_Data (OSD_Num_Prims : Positive) is record + OSD_Table : Object_Specific_Data_Array (1 .. OSD_Num_Prims); + -- Table used in secondary DT to reference their counterpart in the + -- select specific data (in the TSD of the primary DT). This construct + -- is used in the handling of dispatching triggers in select statements. + -- Nb_Prim is the number of non-predefined primitive operations. + end record; + + type Object_Specific_Data_Ptr is access all Object_Specific_Data; -- The following subprogram specifications are placed here instead of -- the package body to see them from the frontend through rtsfind. @@ -419,21 +393,17 @@ private -- Ada 2005 (AI-251): Displace "This" to point to the base address of -- the object (that is, the address of the primary tag of the object). - function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean; - -- Given the tag of an object and the tag associated to a type, return - -- true if Obj is in Typ'Class. - function Displace (This : System.Address; T : Tag) return System.Address; -- Ada 2005 (AI-251): Displace "This" to point to the secondary dispatch -- table of T. + function DT (T : Tag) return Dispatch_Table_Ptr; + -- Return the pointer to the TSD record associated with T + function Get_Entry_Index (T : Tag; Position : Positive) return Positive; -- Ada 2005 (AI-251): Return a primitive operation's entry index (if entry) -- given a dispatch table T and a position of a primitive operation in T. - function Get_External_Tag (T : Tag) return System.Address; - -- Returns address of a null terminated string containing the external name - function Get_Offset_Index (T : Tag; Position : Positive) return Positive; @@ -450,7 +420,7 @@ private function Get_RC_Offset (T : Tag) return SSE.Storage_Offset; -- Return the Offset of the implicit record controller when the object - -- has controlled components. O otherwise. + -- has controlled components, returns zero if no controlled components. pragma Export (Ada, Get_RC_Offset, "ada__tags__get_rc_offset"); -- This procedure is used in s-finimp to compute the deep routines @@ -477,17 +447,12 @@ private -- end Test; function Offset_To_Top - (This : System.Address) return System.Storage_Elements.Storage_Offset; + (This : System.Address) return SSE.Storage_Offset; -- Ada 2005 (AI-251): Returns the current value of the offset_to_top -- component available in the prologue of the dispatch table. If the parent -- of the tagged type has discriminants this value is stored in a record -- component just immediately after the tag component. - function OSD (T : Tag) return Object_Specific_Data_Ptr; - -- Ada 2005 (AI-251): Given a pointer T to a secondary dispatch table, - -- retrieve the address of the record containing the Object Specific - -- Data table. - function Parent_Size (Obj : System.Address; T : Tag) return SSE.Storage_Count; @@ -499,14 +464,6 @@ private pragma Export (Ada, Parent_Size, "ada__tags__parent_size"); -- This procedure is used in s-finimp and is thus exported manually - procedure Register_Interface_Tag - (T : Tag; - Interface_T : Tag; - Position : Positive); - -- Ada 2005 (AI-251): Used to initialize the table of interfaces - -- implemented by a type. Required to give support to backward interface - -- conversions and also to IW_Membership. - procedure Register_Tag (T : Tag); -- Insert the Tag and its associated external_tag in a table for the -- sake of Internal_Tag @@ -515,23 +472,12 @@ private -- Ada 2005 (AI-345): Set the entry index of a primitive operation in T's -- TSD table indexed by Position. - procedure Set_Interface_Table (T : Tag; Value : System.Address); - -- Ada 2005 (AI-251): Given a pointer T to a dispatch Table, stores the - -- pointer to the table of interfaces. - - procedure Set_Offset_Index - (T : Tag; - Position : Positive; - Value : Positive); - -- Ada 2005 (AI-345): Set the offset value of a primitive operation in a - -- secondary dispatch table denoted by T, indexed by Position. - procedure Set_Offset_To_Top (This : System.Address; Interface_T : Tag; Is_Static : Boolean; - Offset_Value : System.Storage_Elements.Storage_Offset; - Offset_Func : System.Address); + Offset_Value : SSE.Storage_Offset; + Offset_Func : Offset_To_Top_Function_Ptr); -- Ada 2005 (AI-251): Initialize the Offset_To_Top field in the prologue of -- the dispatch table. In primary dispatch tables the value of "This" is -- not required (and the compiler passes always the Null_Address value) and @@ -541,11 +487,6 @@ private -- distance from "This" to the object component containing the tag of the -- secondary dispatch table. - procedure Set_OSD (T : Tag; Value : System.Address); - -- Ada 2005 (AI-251): Given a pointer T to a secondary dispatch table, - -- store the pointer to the record containing the Object Specific Data - -- generated by GNAT. - procedure Set_Prim_Op_Kind (T : Tag; Position : Positive; @@ -553,94 +494,52 @@ private -- Ada 2005 (AI-251): Set the kind of a primitive operation in T's TSD -- table indexed by Position. - procedure Set_Signature (T : Tag; Value : Signature_Kind); - -- Given a pointer T to a dispatch table, store the signature id - - procedure Set_SSD (T : Tag; Value : System.Address); - -- Ada 2005 (AI-345): Given a pointer T to a dispatch Table, stores the - -- pointer to the record containing the Select Specific Data generated by - -- GNAT. - - procedure Set_Tagged_Kind (T : Tag; Value : Tagged_Kind); - -- Ada 2005 (AI-345): Set the tagged kind of a type in either a primary or - -- a secondary dispatch table denoted by T. - - function SSD (T : Tag) return Select_Specific_Data_Ptr; - -- Ada 2005 (AI-251): Given a pointer T to a dispatch Table, retrieves the - -- address of the record containing the Select Specific Data in T's TSD. - - function TSD (T : Tag) return Type_Specific_Data_Ptr; - -- Given a pointer T to a dispatch Table, retrieves the address of the - -- record containing the Type Specific Data generated by GNAT. - -- Unchecked Conversions - type Addr_Ptr is access System.Address; + Max_Predef_Prims : constant Natural := 16; + -- Compiler should check this constant is OK ??? - type Signature_Values is - array (1 .. DT_Signature_Size) of Signature_Kind; - -- Type used to see the signature as a sequence of Signature_Kind values + subtype Predef_Prims_Table is Address_Array (1 .. Max_Predef_Prims); + type Predef_Prims_Table_Ptr is access Predef_Prims_Table; - type Signature_Values_Ptr is access all Signature_Values; + type Addr_Ptr is access System.Address; function To_Addr_Ptr is - new Unchecked_Conversion (System.Address, Addr_Ptr); - - function To_Type_Specific_Data_Ptr is - new Unchecked_Conversion (System.Address, Type_Specific_Data_Ptr); + new Ada.Unchecked_Conversion (System.Address, Addr_Ptr); function To_Address is - new Unchecked_Conversion (Tag, System.Address); + new Ada.Unchecked_Conversion (Tag, System.Address); - function To_Interface_Data_Ptr is - new Unchecked_Conversion (System.Address, Interface_Data_Ptr); + function To_Dispatch_Table_Ptr is + new Ada.Unchecked_Conversion (Tag, Dispatch_Table_Ptr); - function To_Object_Specific_Data_Ptr is - new Unchecked_Conversion (System.Address, Object_Specific_Data_Ptr); - - function To_Select_Specific_Data_Ptr is - new Unchecked_Conversion (System.Address, Select_Specific_Data_Ptr); - - function To_Signature_Values is - new Unchecked_Conversion (System.Storage_Elements.Storage_Offset, - Signature_Values); + function To_Dispatch_Table_Ptr is + new Ada.Unchecked_Conversion (System.Address, Dispatch_Table_Ptr); - function To_Signature_Values_Ptr is - new Unchecked_Conversion (System.Address, - Signature_Values_Ptr); + function To_Object_Specific_Data_Ptr is + new Ada.Unchecked_Conversion (System.Address, Object_Specific_Data_Ptr); - function To_Tag is - new Unchecked_Conversion (System.Address, Tag); + function To_Predef_Prims_Table_Ptr is + new Ada.Unchecked_Conversion (System.Address, Predef_Prims_Table_Ptr); function To_Tag_Ptr is - new Unchecked_Conversion (System.Address, Tag_Ptr); + new Ada.Unchecked_Conversion (System.Address, Tag_Ptr); - function To_Tagged_Kind_Ptr is - new Unchecked_Conversion (System.Address, Tagged_Kind_Ptr); + function To_Type_Specific_Data_Ptr is + new Ada.Unchecked_Conversion (System.Address, Type_Specific_Data_Ptr); - -- Primitive dispatching operations are always inlined, to facilitate - -- use in a minimal/no run-time environment for high integrity use. + -- Primitive dispatching operations are always inlined, to facilitate use + -- in a minimal/no run-time environment for high integrity use. - pragma Inline_Always (CW_Membership); pragma Inline_Always (Displace); pragma Inline_Always (IW_Membership); pragma Inline_Always (Get_Entry_Index); pragma Inline_Always (Get_Offset_Index); pragma Inline_Always (Get_Prim_Op_Kind); pragma Inline_Always (Get_Tagged_Kind); - pragma Inline_Always (OSD); - pragma Inline_Always (Register_Interface_Tag); pragma Inline_Always (Register_Tag); pragma Inline_Always (Set_Entry_Index); - pragma Inline_Always (Set_Interface_Table); - pragma Inline_Always (Set_Offset_Index); pragma Inline_Always (Set_Offset_To_Top); pragma Inline_Always (Set_Prim_Op_Kind); - pragma Inline_Always (Set_Signature); - pragma Inline_Always (Set_OSD); - pragma Inline_Always (Set_SSD); - pragma Inline_Always (Set_Tagged_Kind); - pragma Inline_Always (SSD); - pragma Inline_Always (TSD); end Ada.Tags; diff --git a/gcc/ada/exp_atag.adb b/gcc/ada/exp_atag.adb index 8756136a15a..54bf33fb02f 100644 --- a/gcc/ada/exp_atag.adb +++ b/gcc/ada/exp_atag.adb @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 2006, Free Software Foundation, Inc. -- +-- Copyright (C) 2006-2007, 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- -- @@ -24,16 +24,15 @@ -- -- ------------------------------------------------------------------------------ -with Atree; use Atree; with Einfo; use Einfo; +with Elists; use Elists; with Exp_Util; use Exp_Util; with Nlists; use Nlists; with Nmake; use Nmake; with Rtsfind; use Rtsfind; -with Sinfo; use Sinfo; +with Stand; use Stand; with Snames; use Snames; with Tbuild; use Tbuild; -with Uintp; use Uintp; package body Exp_Atag is @@ -41,33 +40,107 @@ package body Exp_Atag is -- Local Subprograms -- ----------------------- - function Build_Predefined_DT + function Build_DT (Loc : Source_Ptr; Tag_Node : Node_Id) return Node_Id; - -- Build code that displaces the Tag to reference the dispatch table - -- containing the predefined primitives. + -- Build code that displaces the Tag to reference the base of the wrapper + -- record -- - -- Generates: To_Tag (To_Address (Tag_Node) - DT_Prologue_Size); - pragma Inline (Build_Predefined_DT); - - function Build_Typeinfo_Offset (Loc : Source_Ptr) return Node_Id; - -- Build code that gives access to the distance from the tag to the - -- Typeinfo component of the dispatch table. - -- - -- Generates: DT_Typeinfo_Ptr_Size - pragma Inline (Build_Typeinfo_Offset); + -- Generates: + -- To_Dispatch_Table_Ptr + -- (To_Address (Tag_Node) - Tag_Node.Prims_Ptr'Position); function Build_TSD (Loc : Source_Ptr; Tag_Node : Node_Id) return Node_Id; -- Build code that retrieves the address of the record containing the Type -- Specific Data generated by GNAT. -- -- Generate: To_Type_Specific_Data_Ptr - -- (To_Address_Ptr (To_Address (Tag) - Typeinfo_Offset).all); - pragma Inline (Build_TSD); + -- (To_Addr_Ptr (To_Address (Tag) - Typeinfo_Offset).all); + + function Build_Predef_Prims + (Loc : Source_Ptr; + Tag_Node : Node_Id) return Node_Id; + -- Build code that retrieves the address of the dispatch table containing + -- the predefined Ada primitives: + -- + -- Generate: To_Predef_Prims_Table_Ptr + -- (To_Addr_Ptr (To_Address (Tag) - Predef_Prims_Offset).all); + + ------------------------------------------------ + -- Build_Common_Dispatching_Select_Statements -- + ------------------------------------------------ - function RTE_Tag_Node return Entity_Id; - -- Returns the entity associated with Ada.Tags.Tag - pragma Inline (RTE_Tag_Node); + procedure Build_Common_Dispatching_Select_Statements + (Loc : Source_Ptr; + DT_Ptr : Entity_Id; + Stmts : List_Id) + is + begin + -- Generate: + -- C := get_prim_op_kind (tag! (VP), S); + + -- where C is the out parameter capturing the call kind and S is the + -- dispatch table slot number. + + Append_To (Stmts, + Make_Assignment_Statement (Loc, + Name => + Make_Identifier (Loc, Name_uC), + Expression => + Make_Function_Call (Loc, + Name => New_Occurrence_Of (RTE (RE_Get_Prim_Op_Kind), Loc), + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Tag), + New_Reference_To (DT_Ptr, Loc)), + Make_Identifier (Loc, Name_uS))))); + + -- Generate: + + -- if C = POK_Procedure + -- or else C = POK_Protected_Procedure + -- or else C = POK_Task_Procedure; + -- then + -- F := True; + -- return; + + -- where F is the out parameter capturing the status of a potential + -- entry call. + + Append_To (Stmts, + Make_If_Statement (Loc, + + Condition => + Make_Or_Else (Loc, + Left_Opnd => + Make_Op_Eq (Loc, + Left_Opnd => + Make_Identifier (Loc, Name_uC), + Right_Opnd => + New_Reference_To (RTE (RE_POK_Procedure), Loc)), + Right_Opnd => + Make_Or_Else (Loc, + Left_Opnd => + Make_Op_Eq (Loc, + Left_Opnd => + Make_Identifier (Loc, Name_uC), + Right_Opnd => + New_Reference_To (RTE ( + RE_POK_Protected_Procedure), Loc)), + Right_Opnd => + Make_Op_Eq (Loc, + Left_Opnd => + Make_Identifier (Loc, Name_uC), + Right_Opnd => + New_Reference_To (RTE ( + RE_POK_Task_Procedure), Loc)))), + + Then_Statements => + New_List ( + Make_Assignment_Statement (Loc, + Name => Make_Identifier (Loc, Name_uF), + Expression => New_Reference_To (Standard_True, Loc)), + Make_Return_Statement (Loc)))); + end Build_Common_Dispatching_Select_Statements; ------------------------- -- Build_CW_Membership -- @@ -103,27 +176,42 @@ package body Exp_Atag is begin return Make_And_Then (Loc, - Left_Opnd => - Make_Op_Ge (Loc, - Left_Opnd => Build_Pos, - Right_Opnd => Make_Integer_Literal (Loc, Uint_0)), - - Right_Opnd => - Make_Op_Eq (Loc, - Left_Opnd => - Make_Indexed_Component (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => Build_TSD (Loc, Obj_Tag_Node), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Tags_Table), Loc)), - Expressions => - New_List (Build_Pos)), - - Right_Opnd => Typ_Tag_Node)); + Left_Opnd => + Make_Op_Ge (Loc, + Left_Opnd => Build_Pos, + Right_Opnd => Make_Integer_Literal (Loc, Uint_0)), + + Right_Opnd => + Make_Op_Eq (Loc, + Left_Opnd => + Make_Indexed_Component (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => Build_TSD (Loc, Obj_Tag_Node), + Selector_Name => + New_Reference_To + (RTE_Record_Component (RE_Tags_Table), Loc)), + Expressions => + New_List (Build_Pos)), + + Right_Opnd => Typ_Tag_Node)); end Build_CW_Membership; + -------------- + -- Build_DT -- + -------------- + + function Build_DT + (Loc : Source_Ptr; + Tag_Node : Node_Id) return Node_Id is + begin + return + Make_Function_Call (Loc, + Name => New_Reference_To (RTE (RE_DT), Loc), + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Tag), Tag_Node))); + end Build_DT; + ---------------------------- -- Build_Get_Access_Level -- ---------------------------- @@ -146,125 +234,18 @@ package body Exp_Atag is ------------------------------------------ function Build_Get_Predefined_Prim_Op_Address - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Position_Node : Node_Id) return Node_Id - is - begin - return - Make_Indexed_Component (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Build_Predefined_DT (Loc, Tag_Node), - - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Prims_Ptr), Loc)), - - Expressions => - New_List (Position_Node)); - end Build_Get_Predefined_Prim_Op_Address; - - ------------------------------- - -- Build_Get_Prim_Op_Address -- - ------------------------------- - - function Build_Get_Prim_Op_Address - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Position_Node : Node_Id) return Node_Id + (Loc : Source_Ptr; + Tag_Node : Node_Id; + Position : Uint) return Node_Id is begin return Make_Indexed_Component (Loc, Prefix => - Make_Selected_Component (Loc, - Prefix => - Unchecked_Convert_To - (RTE_Tag_Node, Tag_Node), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Prims_Ptr), Loc)), - - Expressions => New_List (Position_Node)); - end Build_Get_Prim_Op_Address; - - ------------------------- - -- Build_Get_RC_Offset -- - ------------------------- - - function Build_Get_RC_Offset - (Loc : Source_Ptr; - Tag_Node : Node_Id) return Node_Id - is - begin - return - Make_Selected_Component (Loc, - Prefix => Build_TSD (Loc, Tag_Node), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_RC_Offset), Loc)); - end Build_Get_RC_Offset; - - --------------------------------- - -- Build_Get_Remotely_Callable -- - --------------------------------- - - function Build_Get_Remotely_Callable - (Loc : Source_Ptr; - Tag_Node : Node_Id) return Node_Id - is - begin - return - Make_Selected_Component (Loc, - Prefix => Build_TSD (Loc, Tag_Node), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Remotely_Callable), Loc)); - end Build_Get_Remotely_Callable; - - ------------------------------------ - -- Build_Inherit_Predefined_Prims -- - ------------------------------------ - - function Build_Inherit_Predefined_Prims - (Loc : Source_Ptr; - Old_Tag_Node : Node_Id; - New_Tag_Node : Node_Id) return Node_Id - is - begin - return - Make_Assignment_Statement (Loc, - Name => - Make_Slice (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Build_Predefined_DT (Loc, New_Tag_Node), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Prims_Ptr), Loc)), - - Discrete_Range => Make_Range (Loc, - Make_Integer_Literal (Loc, Uint_1), - New_Reference_To (RTE (RE_Default_Prim_Op_Count), Loc))), - - Expression => - Make_Slice (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => Build_Predefined_DT (Loc, Old_Tag_Node), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Prims_Ptr), Loc)), - Discrete_Range => - Make_Range (Loc, - Low_Bound => Make_Integer_Literal (Loc, 1), - High_Bound => - New_Reference_To (RTE (RE_Default_Prim_Op_Count), Loc)))); - - end Build_Inherit_Predefined_Prims; + Build_Predef_Prims (Loc, Tag_Node), + Expressions => + New_List (Make_Integer_Literal (Loc, Position))); + end Build_Get_Predefined_Prim_Op_Address; ------------------------- -- Build_Inherit_Prims -- @@ -284,7 +265,7 @@ package body Exp_Atag is Prefix => Make_Selected_Component (Loc, Prefix => - Unchecked_Convert_To (RTE_Tag_Node, New_Tag_Node), + Build_DT (Loc, New_Tag_Node), Selector_Name => New_Reference_To (RTE_Record_Component (RE_Prims_Ptr), Loc)), @@ -298,7 +279,7 @@ package body Exp_Atag is Prefix => Make_Selected_Component (Loc, Prefix => - Unchecked_Convert_To (RTE_Tag_Node, Old_Tag_Node), + Build_DT (Loc, Old_Tag_Node), Selector_Name => New_Reference_To (RTE_Record_Component (RE_Prims_Ptr), Loc)), @@ -308,281 +289,139 @@ package body Exp_Atag is High_Bound => Make_Integer_Literal (Loc, Num_Prims)))); end Build_Inherit_Prims; - ------------------- - -- Build_New_TSD -- - ------------------- + ------------------------------- + -- Build_Get_Prim_Op_Address -- + ------------------------------- - function Build_New_TSD - (Loc : Source_Ptr; - New_Tag_Node : Node_Id) return List_Id + function Build_Get_Prim_Op_Address + (Loc : Source_Ptr; + Typ : Entity_Id; + Tag_Node : Node_Id; + Position : Uint) return Node_Id is begin - return New_List ( - Make_Assignment_Statement (Loc, - Name => - Make_Indexed_Component (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => Build_TSD (Loc, Duplicate_Subexpr (New_Tag_Node)), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Tags_Table), Loc)), - Expressions => New_List (Make_Integer_Literal (Loc, Uint_0))), - - Expression => New_Tag_Node)); - end Build_New_TSD; + pragma Assert + (Position <= DT_Entry_Count (First_Tag_Component (Typ))); - ----------------------- - -- Build_Inherit_TSD -- - ----------------------- - - function Build_Inherit_TSD - (Loc : Source_Ptr; - Old_Tag_Node : Node_Id; - New_Tag_Node : Node_Id; - I_Depth : Nat; - Parent_Num_Ifaces : Nat) return Node_Id - is - function Build_Iface_Table_Ptr (Tag_Node : Node_Id) return Node_Id; - -- Generates: Interface_Data_Ptr! (TSD (Tag).Ifaces_Table_Ptr).all + -- At the end of the Access_Disp_Table list we have the type + -- declaration required to convert the tag into a pointer to + -- the prims_ptr table (see Freeze_Record_Type). - ---------------------------- - -- Build_Iface_Table_Ptr -- - ---------------------------- - - function Build_Iface_Table_Ptr (Tag_Node : Node_Id) return Node_Id is - begin - return - Unchecked_Convert_To (RTE (RE_Interface_Data_Ptr), - Make_Selected_Component (Loc, - Prefix => Tag_Node, - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Ifaces_Table_Ptr), Loc))); - end Build_Iface_Table_Ptr; - - -- Local variables - - L : constant List_Id := New_List; - Old_TSD : Node_Id; - New_TSD : Node_Id; + return + Make_Indexed_Component (Loc, + Prefix => + Unchecked_Convert_To + (Node (Last_Elmt (Access_Disp_Table (Typ))), Tag_Node), + Expressions => New_List (Make_Integer_Literal (Loc, Position))); + end Build_Get_Prim_Op_Address; - -- Start of processing for Build_Inherit_TSD + ----------------------------- + -- Build_Get_Transportable -- + ----------------------------- + function Build_Get_Transportable + (Loc : Source_Ptr; + Tag_Node : Node_Id) return Node_Id + is begin - Old_TSD := - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, New_Internal_Name ('T')), - Object_Definition => - New_Reference_To (RTE (RE_Type_Specific_Data_Ptr), Loc), - Expression => - Build_TSD (Loc, Duplicate_Subexpr (Old_Tag_Node))); - - New_TSD := - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, New_Internal_Name ('T')), - Object_Definition => - New_Reference_To (RTE (RE_Type_Specific_Data_Ptr), Loc), - Expression => - Build_TSD (Loc, Duplicate_Subexpr (New_Tag_Node))); - - Append_List_To (L, New_List ( + return + Make_Selected_Component (Loc, + Prefix => Build_TSD (Loc, Tag_Node), + Selector_Name => + New_Reference_To + (RTE_Record_Component (RE_Transportable), Loc)); + end Build_Get_Transportable; - -- Copy the table of ancestors of the parent - -- TSD (New_Tag).Tags_Table (1 .. I_Depth) := - -- TSD (Old_Tag).Tags_Table (0 .. I_Depth - 1); + ------------------------------------ + -- Build_Inherit_Predefined_Prims -- + ------------------------------------ - Make_Assignment_Statement (Loc, - Name => - Make_Slice (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Make_Explicit_Dereference (Loc, - New_Reference_To (Defining_Identifier (New_TSD), Loc)), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Tags_Table), Loc)), - Discrete_Range => Make_Range (Loc, - Make_Integer_Literal (Loc, Uint_1), - Make_Integer_Literal (Loc, I_Depth))), - - Expression => - Make_Slice (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Make_Explicit_Dereference (Loc, - New_Reference_To (Defining_Identifier (Old_TSD), Loc)), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Tags_Table), Loc)), - Discrete_Range => Make_Range (Loc, - Make_Integer_Literal (Loc, Uint_0), - Make_Integer_Literal (Loc, I_Depth - 1)))))); - - -- Copy the table of interfaces of the parent - - -- if not System."=" (TSD (Old_Tag).Ifaces_Table_Ptr, - -- System.Null_Address) - -- then - -- New_Iface_Table_Ptr.Table (1 .. Parent_Num_Ifaces):= - -- Old_Iface_Table_Ptr.Table (1 .. Parent_Num_Ifaces); - -- end if; - - -- The table of interfaces is not available under certified run-time - - if RTE_Record_Component_Available (RE_Nb_Ifaces) then - Append_To (L, - Make_If_Statement (Loc, - Condition => - Make_Op_Not (Loc, - Right_Opnd => - Make_Op_Eq (Loc, - Left_Opnd => - Make_Selected_Component (Loc, - Prefix => - Make_Explicit_Dereference (Loc, - New_Reference_To - (Defining_Identifier (Old_TSD), Loc)), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Ifaces_Table_Ptr), - Loc)), - Right_Opnd => - New_Reference_To (RTE (RE_Null_Address), Loc))), - - Then_Statements => New_List ( - Make_Assignment_Statement (Loc, - Name => - Make_Slice (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Build_Iface_Table_Ptr - (New_Reference_To - (Defining_Identifier (New_TSD), Loc)), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Ifaces_Table), Loc)), - - Discrete_Range => Make_Range (Loc, - Make_Integer_Literal (Loc, Uint_1), - Make_Integer_Literal (Loc, Parent_Num_Ifaces))), - - Expression => - Make_Slice (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Build_Iface_Table_Ptr - (New_Reference_To - (Defining_Identifier (Old_TSD), Loc)), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RE_Ifaces_Table), Loc)), - - Discrete_Range => Make_Range (Loc, - Make_Integer_Literal (Loc, Uint_1), - Make_Integer_Literal (Loc, Parent_Num_Ifaces))))))); - end if; - - -- TSD (New_Tag).Tags_Table (0) := New_Tag; - - Append_To (L, - Make_Assignment_Statement (Loc, - Name => - Make_Indexed_Component (Loc, - Prefix => + function Build_Inherit_Predefined_Prims + (Loc : Source_Ptr; + Old_Tag_Node : Node_Id; + New_Tag_Node : Node_Id) return Node_Id + is + begin + return + Make_Assignment_Statement (Loc, + Name => + Make_Slice (Loc, + Prefix => + Make_Explicit_Dereference (Loc, + Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr), Make_Selected_Component (Loc, Prefix => - Make_Explicit_Dereference (Loc, - New_Reference_To - (Defining_Identifier (New_TSD), Loc)), + Build_DT (Loc, New_Tag_Node), Selector_Name => New_Reference_To - (RTE_Record_Component (RE_Tags_Table), Loc)), - Expressions => - New_List (Make_Integer_Literal (Loc, Uint_0))), - - Expression => New_Tag_Node)); - - return - Make_Block_Statement (Loc, - Declarations => New_List ( - Old_TSD, - New_TSD), - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, L)); + (RTE_Record_Component (RE_Predef_Prims), Loc)))), + Discrete_Range => Make_Range (Loc, + Make_Integer_Literal (Loc, Uint_1), + New_Reference_To (RTE (RE_Default_Prim_Op_Count), Loc))), - end Build_Inherit_TSD; + Expression => + Make_Slice (Loc, + Prefix => + Make_Explicit_Dereference (Loc, + Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr), + Make_Selected_Component (Loc, + Prefix => + Build_DT (Loc, Old_Tag_Node), + Selector_Name => + New_Reference_To + (RTE_Record_Component (RE_Predef_Prims), Loc)))), + Discrete_Range => + Make_Range (Loc, + Low_Bound => Make_Integer_Literal (Loc, 1), + High_Bound => + New_Reference_To (RTE (RE_Default_Prim_Op_Count), Loc)))); + end Build_Inherit_Predefined_Prims; - ------------------------- - -- Build_Predefined_DT -- - ------------------------- + ------------------------ + -- Build_Predef_Prims -- + ------------------------ - function Build_Predefined_DT + function Build_Predef_Prims (Loc : Source_Ptr; Tag_Node : Node_Id) return Node_Id is begin return - Unchecked_Convert_To (RTE_Tag_Node, - Make_Function_Call (Loc, - Name => - Make_Expanded_Name (Loc, - Chars => Name_Op_Subtract, - Prefix => - New_Reference_To (RTU_Entity (System_Storage_Elements), Loc), - Selector_Name => - Make_Identifier (Loc, - Chars => Name_Op_Subtract)), - - Parameter_Associations => New_List ( - Unchecked_Convert_To (RTE (RE_Address), Tag_Node), - New_Reference_To (RTE (RE_DT_Prologue_Size), Loc)))); - end Build_Predefined_DT; - - ---------------------------- - -- Build_Set_External_Tag -- - ---------------------------- - - function Build_Set_External_Tag - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Value_Node : Node_Id) return Node_Id - is - begin - return - Make_Assignment_Statement (Loc, - Name => - Make_Selected_Component (Loc, - Prefix => Build_TSD (Loc, Tag_Node), - Selector_Name => - New_Reference_To - (RTE_Record_Component (RO_TA_External_Tag), Loc)), - - Expression => - Unchecked_Convert_To (RTE (RE_Cstring_Ptr), Value_Node)); - end Build_Set_External_Tag; + Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr), + Make_Explicit_Dereference (Loc, + Unchecked_Convert_To (RTE (RE_Addr_Ptr), + Make_Function_Call (Loc, + Name => + Make_Expanded_Name (Loc, + Chars => Name_Op_Subtract, + Prefix => + New_Reference_To + (RTU_Entity (System_Storage_Elements), Loc), + Selector_Name => + Make_Identifier (Loc, + Chars => Name_Op_Subtract)), + + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Address), Tag_Node), + New_Reference_To (RTE (RE_DT_Predef_Prims_Offset), + Loc)))))); + end Build_Predef_Prims; ------------------------------------------ -- Build_Set_Predefined_Prim_Op_Address -- ------------------------------------------ function Build_Set_Predefined_Prim_Op_Address - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Position_Node : Node_Id; - Address_Node : Node_Id) return Node_Id + (Loc : Source_Ptr; + Tag_Node : Node_Id; + Position : Uint; + Address_Node : Node_Id) return Node_Id is begin return Make_Assignment_Statement (Loc, - Name => Build_Get_Predefined_Prim_Op_Address - (Loc, Tag_Node, Position_Node), + Name => Build_Get_Predefined_Prim_Op_Address (Loc, + Tag_Node, Position), Expression => Address_Node); end Build_Set_Predefined_Prim_Op_Address; @@ -591,52 +430,20 @@ package body Exp_Atag is ------------------------------- function Build_Set_Prim_Op_Address - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Position_Node : Node_Id; - Address_Node : Node_Id) return Node_Id + (Loc : Source_Ptr; + Typ : Entity_Id; + Tag_Node : Node_Id; + Position : Uint; + Address_Node : Node_Id) return Node_Id is begin return - Make_Assignment_Statement (Loc, - Name => Build_Get_Prim_Op_Address (Loc, - Tag_Node, Position_Node), - Expression => Address_Node); + Make_Assignment_Statement (Loc, + Name => Build_Get_Prim_Op_Address + (Loc, Typ, Tag_Node, Position), + Expression => Address_Node); end Build_Set_Prim_Op_Address; - ------------------- - -- Build_Set_TSD -- - ------------------- - - function Build_Set_TSD - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Value_Node : Node_Id) return Node_Id - is - begin - return - Make_Assignment_Statement (Loc, - Name => - Make_Explicit_Dereference (Loc, - Prefix => Unchecked_Convert_To (RTE (RE_Addr_Ptr), - Make_Function_Call (Loc, - Name => - Make_Expanded_Name (Loc, - Chars => Name_Op_Subtract, - Prefix => - New_Reference_To - (RTU_Entity (System_Storage_Elements), Loc), - Selector_Name => - Make_Identifier (Loc, - Chars => Name_Op_Subtract)), - - Parameter_Associations => New_List ( - Unchecked_Convert_To (RTE (RE_Address), Tag_Node), - Build_Typeinfo_Offset (Loc))))), - - Expression => Value_Node); - end Build_Set_TSD; - --------------- -- Build_TSD -- --------------- @@ -647,42 +454,21 @@ package body Exp_Atag is Unchecked_Convert_To (RTE (RE_Type_Specific_Data_Ptr), Make_Explicit_Dereference (Loc, Prefix => Unchecked_Convert_To (RTE (RE_Addr_Ptr), - Make_Function_Call (Loc, - Name => - Make_Expanded_Name (Loc, - Chars => Name_Op_Subtract, - Prefix => - New_Reference_To - (RTU_Entity (System_Storage_Elements), Loc), - Selector_Name => - Make_Identifier (Loc, - Chars => Name_Op_Subtract)), - - Parameter_Associations => New_List ( - Unchecked_Convert_To (RTE (RE_Address), Tag_Node), - Build_Typeinfo_Offset (Loc)))))); + Make_Function_Call (Loc, + Name => + Make_Expanded_Name (Loc, + Chars => Name_Op_Subtract, + Prefix => + New_Reference_To + (RTU_Entity (System_Storage_Elements), Loc), + Selector_Name => + Make_Identifier (Loc, + Chars => Name_Op_Subtract)), + + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Address), Tag_Node), + New_Reference_To + (RTE (RE_DT_Typeinfo_Ptr_Size), Loc)))))); end Build_TSD; - --------------------------- - -- Build_Typeinfo_Offset -- - --------------------------- - - function Build_Typeinfo_Offset (Loc : Source_Ptr) return Node_Id is - begin - return New_Reference_To (RTE (RE_DT_Typeinfo_Ptr_Size), Loc); - end Build_Typeinfo_Offset; - - --------------- - -- Tag_Node -- - --------------- - - function RTE_Tag_Node return Entity_Id is - E : constant Entity_Id := RTE (RE_Tag); - begin - if Atree.Present (Full_View (E)) then - return Full_View (E); - else - return E; - end if; - end RTE_Tag_Node; end Exp_Atag; diff --git a/gcc/ada/exp_atag.ads b/gcc/ada/exp_atag.ads index 8eb456b0612..6b0fce75c9e 100644 --- a/gcc/ada/exp_atag.ads +++ b/gcc/ada/exp_atag.ads @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 2006, Free Software Foundation, Inc. -- +-- Copyright (C) 2006-2007, 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- -- @@ -28,18 +28,24 @@ -- subprograms of package Ada.Tags with Types; use Types; +with Uintp; use Uintp; package Exp_Atag is + procedure Build_Common_Dispatching_Select_Statements + (Loc : Source_Ptr; + DT_Ptr : Entity_Id; + Stmts : List_Id); + -- Ada 2005 (AI-345): Generate statements that are common between timed, + -- asynchronous, and conditional select expansion. + function Build_CW_Membership (Loc : Source_Ptr; Obj_Tag_Node : Node_Id; Typ_Tag_Node : Node_Id) return Node_Id; - -- Build code that returns true if Obj_Tag is in Typ_Tag'Class. Each - -- dispatch table contains a reference to a table of ancestors (stored - -- in the first part of the Tags_Table) and a count of the level of - -- inheritance "Idepth". Obj is in Typ'Class if Typ'Tag is in the table - -- of ancestors that are contained in the dispatch table referenced by + -- Build code that returns true if Obj_Tag is in Typ_Tag'Class. Each DT + -- has a table of ancestors and its inheritance level (Idepth). Obj is in + -- Typ'Class if Typ'Tag is found in the table of ancestors referenced by -- Obj'Tag. Knowing the level of inheritance of both types, this can be -- computed in constant time by the formula: -- @@ -54,9 +60,9 @@ package Exp_Atag is -- Generates: TSD (Tag).Access_Level function Build_Get_Predefined_Prim_Op_Address - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Position_Node : Node_Id) return Node_Id; + (Loc : Source_Ptr; + Tag_Node : Node_Id; + Position : Uint) return Node_Id; -- Given a pointer to a dispatch table (T) and a position in the DT, build -- code that gets the address of the predefined virtual function stored in -- it (used for dispatching calls). @@ -64,29 +70,22 @@ package Exp_Atag is -- Generates: Predefined_DT (Tag).D (Position); function Build_Get_Prim_Op_Address - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Position_Node : Node_Id) return Node_Id; + (Loc : Source_Ptr; + Typ : Entity_Id; + Tag_Node : Node_Id; + Position : Uint) return Node_Id; -- Build code that retrieves the address of the virtual function stored in -- a given position of the dispatch table (used for dispatching calls). -- -- Generates: To_Tag (Tag).D (Position); - function Build_Get_RC_Offset - (Loc : Source_Ptr; - Tag_Node : Node_Id) return Node_Id; - -- Build code that retrieves the Offset of the implicit record controller - -- when the object has controlled components. O otherwise. - -- - -- Generates: TSD (T).RC_Offset; - - function Build_Get_Remotely_Callable - (Loc : Source_Ptr; - Tag_Node : Node_Id) return Node_Id; - -- Build code that retrieves the value previously saved by Set_Remotely - -- Callable + function Build_Get_Transportable + (Loc : Source_Ptr; + Tag_Node : Node_Id) return Node_Id; + -- Build code that retrieves the value of the Transportable flag for + -- the given Tag. -- - -- Generates: TSD (Tag).Remotely_Callable + -- Generates: TSD (Tag).Transportable; function Build_Inherit_Predefined_Prims (Loc : Source_Ptr; @@ -96,6 +95,8 @@ package Exp_Atag is -- -- Generates: Predefined_DT (New_T).D (All_Predefined_Prims) := -- Predefined_DT (Old_T).D (All_Predefined_Prims); + -- + -- Required to build the dispatch tables with the 3.4 backend. function Build_Inherit_Prims (Loc : Source_Ptr; @@ -103,80 +104,39 @@ package Exp_Atag is New_Tag_Node : Node_Id; Num_Prims : Nat) return Node_Id; -- Build code that inherits Num_Prims user-defined primitives from the - -- dispatch table of the parent type. + -- dispatch table of the parent type. It is used to copy the dispatch + -- table of the parent in case of derivations of CPP_Class types. -- -- Generates: -- New_Tag.Prims_Ptr (1 .. Num_Prims) := -- Old_Tag.Prims_Ptr (1 .. Num_Prims); - function Build_Inherit_TSD - (Loc : Source_Ptr; - Old_Tag_Node : Node_Id; - New_Tag_Node : Node_Id; - I_Depth : Nat; - Parent_Num_Ifaces : Nat) return Node_Id; - -- Generates code that initializes the TSD of a type knowing the tag, - -- inheritance depth, and number of interface types of the parent type. - -- - -- Generates: - -- -- Copy the table of ancestors of the parent - -- - -- TSD (New_Tag).Tags_Table (1 .. I_Depth) := - -- TSD (Old_Tag).Tags_Table (0 .. I_Depth - 1); - -- - -- -- Copy the table of interfaces of the parent - -- - -- if TSD (Old_Tag).Ifaces_Table_Ptr /= null then - -- New_Iface_Table_Ptr.Table (1 .. Parent_Num_Ifaces):= - -- Old_Iface_Table_Ptr.Table (1 .. Parent_Num_Ifaces); - -- end if; - -- - -- TSD (New_Tag).Tags_Table (0) := New_Tag; - - function Build_New_TSD - (Loc : Source_Ptr; - New_Tag_Node : Node_Id) return List_Id; - -- Build code that initializes the TSD of a root type. - -- Generates: TSD (New_Tag).Tags_Table (0) := New_Tag; - - function Build_Set_External_Tag - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Value_Node : Node_Id) return Node_Id; - -- Build code that saves the address of the string containing the external - -- tag in the dispatch table. - -- - -- Generates: TSD (Tag).External_Tag := Cstring_Ptr! (Value); - function Build_Set_Predefined_Prim_Op_Address - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Position_Node : Node_Id; - Address_Node : Node_Id) return Node_Id; + (Loc : Source_Ptr; + Tag_Node : Node_Id; + Position : Uint; + Address_Node : Node_Id) return Node_Id; -- Build code that saves the address of a virtual function in a given -- Position of the portion of the dispatch table associated with the - -- predefined primitives of Tag (used for overriding). + -- predefined primitives of Tag. Called from Exp_Disp.Fill_DT_Entry + -- and Exp_Disp.Fill_Secondary_DT_Entry. It is used for: + -- 1) Filling the dispatch table of CPP_Class types. + -- 2) Late overriding (see Check_Dispatching_Operation). -- -- Generates: Predefined_DT (Tag).D (Position) := Value function Build_Set_Prim_Op_Address - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Position_Node : Node_Id; - Address_Node : Node_Id) return Node_Id; + (Loc : Source_Ptr; + Typ : Entity_Id; + Tag_Node : Node_Id; + Position : Uint; + Address_Node : Node_Id) return Node_Id; -- Build code that saves the address of a virtual function in a given - -- Position of the dispatch table associated with the Tag (used for - -- overriding). + -- Position of the dispatch table associated with the Tag. Called from + -- Exp_Disp.Fill_DT_Entry and Exp_Disp.Fill_Secondary_DT_Entry. Used for: + -- 1) Filling the dispatch table of CPP_Class types. + -- 2) Late overriding (see Check_Dispatching_Operation). -- -- Generates: Tag.D (Position) := Value - function Build_Set_TSD - (Loc : Source_Ptr; - Tag_Node : Node_Id; - Value_Node : Node_Id) return Node_Id; - -- Build code that saves the address of the record containing the Type - -- Specific Data generated by GNAT. - -- - -- Generates: To_Addr_Ptr (To_Address (Tag) - K_Typeinfo).all := Value - end Exp_Atag; diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index f8dc4caa2ef..1c079893d5d 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2006, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2007, 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- -- @@ -37,6 +37,7 @@ with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; with Freeze; use Freeze; with Itypes; use Itypes; +with Lib; use Lib; with Nlists; use Nlists; with Nmake; use Nmake; with Namet; use Namet; @@ -46,309 +47,26 @@ with Restrict; use Restrict; with Rident; use Rident; with Rtsfind; use Rtsfind; with Sem; use Sem; +with Sem_Ch6; use Sem_Ch6; +with Sem_Ch8; use Sem_Ch8; with Sem_Disp; use Sem_Disp; +with Sem_Eval; use Sem_Eval; with Sem_Res; use Sem_Res; with Sem_Type; use Sem_Type; with Sem_Util; use Sem_Util; with Sinfo; use Sinfo; with Snames; use Snames; with Stand; use Stand; +with Stringt; use Stringt; +with Targparm; use Targparm; with Tbuild; use Tbuild; with Uintp; use Uintp; package body Exp_Disp is - -------------------------------- - -- Select_Expansion_Utilities -- - -------------------------------- - - -- The following package contains helper routines used in the expansion of - -- dispatching asynchronous, conditional and timed selects. - - package Select_Expansion_Utilities is - procedure Build_B - (Loc : Source_Ptr; - Params : List_Id); - -- Generate: - -- B : out Communication_Block - - procedure Build_C - (Loc : Source_Ptr; - Params : List_Id); - -- Generate: - -- C : out Prim_Op_Kind - - procedure Build_Common_Dispatching_Select_Statements - (Loc : Source_Ptr; - Typ : Entity_Id; - DT_Ptr : Entity_Id; - Stmts : List_Id); - -- Ada 2005 (AI-345): Generate statements that are common between - -- asynchronous, conditional and timed select expansion. - - procedure Build_F - (Loc : Source_Ptr; - Params : List_Id); - -- Generate: - -- F : out Boolean - - procedure Build_P - (Loc : Source_Ptr; - Params : List_Id); - -- Generate: - -- P : Address - - procedure Build_S - (Loc : Source_Ptr; - Params : List_Id); - -- Generate: - -- S : Integer - - procedure Build_T - (Loc : Source_Ptr; - Typ : Entity_Id; - Params : List_Id); - -- Generate: - -- T : in out Typ - end Select_Expansion_Utilities; - - package body Select_Expansion_Utilities is - - ------------- - -- Build_B -- - ------------- - - procedure Build_B - (Loc : Source_Ptr; - Params : List_Id) - is - begin - Append_To (Params, - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uB), - Parameter_Type => - New_Reference_To (RTE (RE_Communication_Block), Loc), - Out_Present => True)); - end Build_B; - - ------------- - -- Build_C -- - ------------- - - procedure Build_C - (Loc : Source_Ptr; - Params : List_Id) - is - begin - Append_To (Params, - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uC), - Parameter_Type => - New_Reference_To (RTE (RE_Prim_Op_Kind), Loc), - Out_Present => True)); - end Build_C; - - ------------------------------------------------ - -- Build_Common_Dispatching_Select_Statements -- - ------------------------------------------------ - - procedure Build_Common_Dispatching_Select_Statements - (Loc : Source_Ptr; - Typ : Entity_Id; - DT_Ptr : Entity_Id; - Stmts : List_Id) - is - begin - -- Generate: - -- C := get_prim_op_kind (tag! (VP), S); - - -- where C is the out parameter capturing the call kind and S is the - -- dispatch table slot number. - - Append_To (Stmts, - Make_Assignment_Statement (Loc, - Name => - Make_Identifier (Loc, Name_uC), - Expression => - Make_DT_Access_Action (Typ, - Action => - Get_Prim_Op_Kind, - Args => - New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (DT_Ptr, Loc)), - Make_Identifier (Loc, Name_uS))))); - - -- Generate: - - -- if C = POK_Procedure - -- or else C = POK_Protected_Procedure - -- or else C = POK_Task_Procedure; - -- then - -- F := True; - -- return; - - -- where F is the out parameter capturing the status of a potential - -- entry call. - - Append_To (Stmts, - Make_If_Statement (Loc, - - Condition => - Make_Or_Else (Loc, - Left_Opnd => - Make_Op_Eq (Loc, - Left_Opnd => - Make_Identifier (Loc, Name_uC), - Right_Opnd => - New_Reference_To (RTE (RE_POK_Procedure), Loc)), - Right_Opnd => - Make_Or_Else (Loc, - Left_Opnd => - Make_Op_Eq (Loc, - Left_Opnd => - Make_Identifier (Loc, Name_uC), - Right_Opnd => - New_Reference_To (RTE ( - RE_POK_Protected_Procedure), Loc)), - Right_Opnd => - Make_Op_Eq (Loc, - Left_Opnd => - Make_Identifier (Loc, Name_uC), - Right_Opnd => - New_Reference_To (RTE ( - RE_POK_Task_Procedure), Loc)))), - - Then_Statements => - New_List ( - Make_Assignment_Statement (Loc, - Name => Make_Identifier (Loc, Name_uF), - Expression => New_Reference_To (Standard_True, Loc)), - - Make_Return_Statement (Loc)))); - end Build_Common_Dispatching_Select_Statements; - - ------------- - -- Build_F -- - ------------- - - procedure Build_F - (Loc : Source_Ptr; - Params : List_Id) - is - begin - Append_To (Params, - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uF), - Parameter_Type => - New_Reference_To (Standard_Boolean, Loc), - Out_Present => True)); - end Build_F; - - ------------- - -- Build_P -- - ------------- - - procedure Build_P - (Loc : Source_Ptr; - Params : List_Id) - is - begin - Append_To (Params, - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uP), - Parameter_Type => - New_Reference_To (RTE (RE_Address), Loc))); - end Build_P; - - ------------- - -- Build_S -- - ------------- - - procedure Build_S - (Loc : Source_Ptr; - Params : List_Id) - is - begin - Append_To (Params, - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uS), - Parameter_Type => - New_Reference_To (Standard_Integer, Loc))); - end Build_S; - - ------------- - -- Build_T -- - ------------- - - procedure Build_T - (Loc : Source_Ptr; - Typ : Entity_Id; - Params : List_Id) - is - begin - Append_To (Params, - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uT), - Parameter_Type => - New_Reference_To (Typ, Loc), - In_Present => True, - Out_Present => True)); - end Build_T; - end Select_Expansion_Utilities; - - package SEU renames Select_Expansion_Utilities; - - Ada_Actions : constant array (DT_Access_Action) of RE_Id := - (IW_Membership => RE_IW_Membership, - Get_Entry_Index => RE_Get_Entry_Index, - Get_Prim_Op_Kind => RE_Get_Prim_Op_Kind, - Get_Tagged_Kind => RE_Get_Tagged_Kind, - Register_Interface_Tag => RE_Register_Interface_Tag, - Register_Tag => RE_Register_Tag, - Set_Entry_Index => RE_Set_Entry_Index, - Set_Offset_Index => RE_Set_Offset_Index, - Set_OSD => RE_Set_OSD, - Set_Prim_Op_Kind => RE_Set_Prim_Op_Kind, - Set_Signature => RE_Set_Signature, - Set_SSD => RE_Set_SSD, - Set_Tagged_Kind => RE_Set_Tagged_Kind); - - Action_Is_Proc : constant array (DT_Access_Action) of Boolean := - (IW_Membership => False, - Get_Entry_Index => False, - Get_Prim_Op_Kind => False, - Get_Tagged_Kind => False, - Register_Interface_Tag => True, - Register_Tag => True, - Set_Entry_Index => True, - Set_Offset_Index => True, - Set_OSD => True, - Set_Prim_Op_Kind => True, - Set_Signature => True, - Set_SSD => True, - Set_Tagged_Kind => True); - - Action_Nb_Arg : constant array (DT_Access_Action) of Int := - (IW_Membership => 2, - Get_Entry_Index => 2, - Get_Prim_Op_Kind => 2, - Get_Tagged_Kind => 1, - Register_Interface_Tag => 3, - Register_Tag => 1, - Set_Entry_Index => 3, - Set_Offset_Index => 3, - Set_OSD => 2, - Set_Prim_Op_Kind => 3, - Set_Signature => 2, - Set_SSD => 2, - Set_Tagged_Kind => 2); + ----------------------- + -- Local Subprograms -- + ----------------------- function Default_Prim_Op_Position (E : Entity_Id) return Uint; -- Ada 2005 (AI-251): Returns the fixed position in the dispatch table @@ -485,6 +203,11 @@ package body Exp_Disp is -- Start of processing for Expand_Dispatching_Call begin + if No_Run_Time_Mode then + Error_Msg_CRT ("tagged types", Call_Node); + return; + end if; + -- Expand_Dispatching_Call is called directly from the semantics, -- so we need a check to see whether expansion is active before -- proceeding. In addition, there is no need to expand the call @@ -527,11 +250,16 @@ package body Exp_Disp is then CW_Typ := Class_Wide_Type (Find_Dispatching_Type (Subp)); + -- Class_Wide_Type is applied to the expressions used to initialize + -- CW_Typ, to ensure that CW_Typ always denotes a class-wide type, since + -- there are cases where the controlling type is resolved to a specific + -- type (such as for designated types of arguments such as CW'Access). + elsif Is_Access_Type (Etype (Ctrl_Arg)) then - CW_Typ := Designated_Type (Etype (Ctrl_Arg)); + CW_Typ := Class_Wide_Type (Designated_Type (Etype (Ctrl_Arg))); else - CW_Typ := Etype (Ctrl_Arg); + CW_Typ := Class_Wide_Type (Etype (Ctrl_Arg)); end if; Typ := Root_Type (CW_Typ); @@ -665,7 +393,7 @@ package body Exp_Disp is declare Old_Formal : Entity_Id := First_Formal (Subp); New_Formal : Entity_Id; - Extra : Entity_Id; + Extra : Entity_Id := Empty; begin if Present (Old_Formal) then @@ -707,27 +435,16 @@ package body Exp_Disp is Set_Next_Entity (New_Formal, Empty); Set_Last_Entity (Subp_Typ, Extra); + end if; - -- Copy extra formals - - New_Formal := First_Entity (Subp_Typ); - while Present (New_Formal) loop - if Present (Extra_Constrained (New_Formal)) then - Set_Extra_Formal (Extra, - New_Copy (Extra_Constrained (New_Formal))); - Extra := Extra_Formal (Extra); - Set_Extra_Constrained (New_Formal, Extra); - - elsif Present (Extra_Accessibility (New_Formal)) then - Set_Extra_Formal (Extra, - New_Copy (Extra_Accessibility (New_Formal))); - Extra := Extra_Formal (Extra); - Set_Extra_Accessibility (New_Formal, Extra); - end if; + -- Now that the explicit formals have been duplicated, any extra + -- formals needed by the subprogram must be created. - Next_Formal (New_Formal); - end loop; + if Present (Extra) then + Set_Extra_Formal (Extra, Empty); end if; + + Create_Extra_Formals (Subp_Typ); end; Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ); @@ -782,8 +499,7 @@ package body Exp_Disp is Unchecked_Convert_To (Subp_Ptr_Typ, Build_Get_Predefined_Prim_Op_Address (Loc, Tag_Node => Controlling_Tag, - Position_Node => Make_Integer_Literal (Loc, - DT_Position (Subp)))); + Position => DT_Position (Subp))); -- Handle dispatching calls to user-defined primitives @@ -791,70 +507,43 @@ package body Exp_Disp is New_Call_Name := Unchecked_Convert_To (Subp_Ptr_Typ, Build_Get_Prim_Op_Address (Loc, - Tag_Node => Controlling_Tag, - Position_Node => Make_Integer_Literal (Loc, - DT_Position (Subp)))); + Typ => Find_Dispatching_Type (Subp), + Tag_Node => Controlling_Tag, + Position => DT_Position (Subp))); end if; if Nkind (Call_Node) = N_Function_Call then - -- Ada 2005 (AI-251): A dispatching "=" with an abstract interface - -- just requires the comparison of the tags. + New_Call := + Make_Function_Call (Loc, + Name => New_Call_Name, + Parameter_Associations => New_Params); - if Ekind (Etype (Ctrl_Arg)) = E_Class_Wide_Type - and then Is_Interface (Etype (Ctrl_Arg)) - and then Subp = Eq_Prim_Op - then - Param := First_Actual (Call_Node); + -- If this is a dispatching "=", we must first compare the tags so + -- we generate: x.tag = y.tag and then x = y + if Subp = Eq_Prim_Op then + Param := First_Actual (Call_Node); New_Call := - Make_Op_Eq (Loc, - Left_Opnd => - Make_Selected_Component (Loc, - Prefix => New_Value (Param), - Selector_Name => - New_Reference_To (First_Tag_Component (Typ), Loc)), - - Right_Opnd => - Make_Selected_Component (Loc, - Prefix => - Unchecked_Convert_To (Typ, - New_Value (Next_Actual (Param))), - Selector_Name => - New_Reference_To (First_Tag_Component (Typ), Loc))); + Make_And_Then (Loc, + Left_Opnd => + Make_Op_Eq (Loc, + Left_Opnd => + Make_Selected_Component (Loc, + Prefix => New_Value (Param), + Selector_Name => + New_Reference_To (First_Tag_Component (Typ), + Loc)), - else - New_Call := - Make_Function_Call (Loc, - Name => New_Call_Name, - Parameter_Associations => New_Params); - - -- If this is a dispatching "=", we must first compare the tags so - -- we generate: x.tag = y.tag and then x = y - - if Subp = Eq_Prim_Op then - Param := First_Actual (Call_Node); - New_Call := - Make_And_Then (Loc, - Left_Opnd => - Make_Op_Eq (Loc, - Left_Opnd => - Make_Selected_Component (Loc, - Prefix => New_Value (Param), - Selector_Name => - New_Reference_To (First_Tag_Component (Typ), - Loc)), - - Right_Opnd => - Make_Selected_Component (Loc, - Prefix => - Unchecked_Convert_To (Typ, - New_Value (Next_Actual (Param))), - Selector_Name => - New_Reference_To (First_Tag_Component (Typ), - Loc))), - Right_Opnd => New_Call); - end if; + Right_Opnd => + Make_Selected_Component (Loc, + Prefix => + Unchecked_Convert_To (Typ, + New_Value (Next_Actual (Param))), + Selector_Name => + New_Reference_To (First_Tag_Component (Typ), + Loc))), + Right_Opnd => New_Call); end if; else @@ -865,7 +554,11 @@ package body Exp_Disp is end if; Rewrite (Call_Node, New_Call); - Analyze_And_Resolve (Call_Node, Call_Typ); + + -- Suppress all checks during the analysis of the expanded code + -- to avoid the generation of spureous warnings under ZFP run-time. + + Analyze_And_Resolve (Call_Node, Call_Typ, Suppress => All_Checks); end Expand_Dispatching_Call; --------------------------------- @@ -885,10 +578,9 @@ package body Exp_Disp is Iface_Typ : Entity_Id := Etype (N); Iface_Tag : Entity_Id; New_Itype : Entity_Id; + Stats : List_Id; begin - pragma Assert (Nkind (Operand) /= N_Attribute_Reference); - -- Ada 2005 (AI-345): Handle synchronized interface type derivations if Is_Concurrent_Type (Operand_Typ) then @@ -905,13 +597,22 @@ package body Exp_Disp is -- explicitly in the source code. Example: I'Class (Obj) if Is_Class_Wide_Type (Iface_Typ) then - Iface_Typ := Etype (Iface_Typ); + Iface_Typ := Root_Type (Iface_Typ); end if; pragma Assert (not Is_Static or else (not Is_Class_Wide_Type (Iface_Typ) and then Is_Interface (Iface_Typ))); + if VM_Target /= No_VM then + + -- For VM, just do a conversion ??? + + Rewrite (N, Unchecked_Convert_To (Etype (N), N)); + Analyze (N); + return; + end if; + if not Is_Static then -- Give error if configurable run time and Displace not available @@ -921,9 +622,9 @@ package body Exp_Disp is return; end if; - -- Handle conversion of access to class-wide interface types. The - -- target can be an access to object or an access to another class - -- wide interfac (see -1- and -2- in the following example): + -- Handle conversion of access-to-class-wide interface types. Target + -- can be an access to an object or an access to another class-wide + -- interface (see -1- and -2- in the following example): -- type Iface1_Ref is access all Iface1'Class; -- type Iface2_Ref is access all Iface1'Class; @@ -934,9 +635,7 @@ package body Exp_Disp is if Is_Access_Type (Operand_Typ) then pragma Assert - (Is_Class_Wide_Type (Directly_Designated_Type (Operand_Typ)) - and then - Is_Interface (Directly_Designated_Type (Operand_Typ))); + (Is_Interface (Directly_Designated_Type (Operand_Typ))); Rewrite (N, Unchecked_Convert_To (Etype (N), @@ -1019,7 +718,6 @@ package body Exp_Disp is -- end Func; Fent := Make_Defining_Identifier (Loc, New_Internal_Name ('F')); - Set_Is_Internal (Fent); declare Desig_Typ : Entity_Id; @@ -1037,6 +735,36 @@ package body Exp_Disp is Set_Directly_Designated_Type (New_Itype, Desig_Typ); end; + Stats := New_List ( + Make_Return_Statement (Loc, + Unchecked_Convert_To (Etype (N), + Make_Attribute_Reference (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => Unchecked_Convert_To (New_Itype, + Make_Identifier (Loc, Name_uO)), + Selector_Name => + New_Occurrence_Of (Iface_Tag, Loc)), + Attribute_Name => Name_Address)))); + + -- If the type is null-excluding, no need for the null branch. + -- Otherwise we need to check for it and return null. + + if not Can_Never_Be_Null (Etype (N)) then + Stats := New_List ( + Make_If_Statement (Loc, + Condition => + Make_Op_Eq (Loc, + Left_Opnd => Make_Identifier (Loc, Name_uO), + Right_Opnd => New_Reference_To + (RTE (RE_Null_Address), Loc)), + + Then_Statements => New_List ( + Make_Return_Statement (Loc, + Make_Null (Loc))), + Else_Statements => Stats)); + end if; + Func := Make_Subprogram_Body (Loc, Specification => @@ -1056,36 +784,16 @@ package body Exp_Disp is Declarations => Empty_List, Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Make_If_Statement (Loc, - Condition => - Make_Op_Eq (Loc, - Left_Opnd => Make_Identifier (Loc, Name_uO), - Right_Opnd => New_Reference_To - (RTE (RE_Null_Address), Loc)), - - Then_Statements => New_List ( - Make_Return_Statement (Loc, - Make_Null (Loc))), - - Else_Statements => New_List ( - Make_Return_Statement (Loc, - Unchecked_Convert_To (Etype (N), - Make_Attribute_Reference (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => Unchecked_Convert_To (New_Itype, - Make_Identifier (Loc, Name_uO)), - Selector_Name => - New_Occurrence_Of (Iface_Tag, Loc)), - Attribute_Name => Name_Address)))))))); + Make_Handled_Sequence_Of_Statements (Loc, Stats)); - -- Place function body before the expression containing - -- the conversion + -- Place function body before the expression containing the + -- conversion. We suppress all checks because the body of the + -- internally generated function already takes care of the case + -- in which the actual is null; therefore there is no need to + -- double check that the pointer is not null when the program + -- executes the alternative that performs the type conversion). - Insert_Action (N, Func); - Analyze (Func); + Insert_Action (N, Func, Suppress => All_Checks); if Is_Access_Type (Etype (Expression (N))) then @@ -1155,14 +863,13 @@ package body Exp_Disp is Subp := Entity (Name (Call_Node)); end if; + -- Ada 2005 (AI-251): Look for interface type formals to force "this" + -- displacement + Formal := First_Formal (Subp); Actual := First_Actual (Call_Node); while Present (Formal) loop - - -- Ada 2005 (AI-251): Conversion to interface to force "this" - -- displacement. - - Formal_Typ := Etype (Etype (Formal)); + Formal_Typ := Etype (Formal); if Ekind (Formal_Typ) = E_Record_Type_With_Private then Formal_Typ := Full_View (Formal_Typ); @@ -1178,49 +885,42 @@ package body Exp_Disp is Actual_DDT := Directly_Designated_Type (Actual_Typ); end if; - if Is_Interface (Formal_Typ) then - + if Is_Interface (Formal_Typ) + and then Is_Class_Wide_Type (Formal_Typ) + then -- No need to displace the pointer if the type of the actual - -- is class-wide of the formal-type interface; in this case the - -- displacement of the pointer was already done at the point of - -- the call to the enclosing subprogram. This case corresponds - -- with the call to P (Obj) in the following example: + -- coindices with the type of the formal. - -- type I is interface; - -- procedure P (X : I) is abstract; - - -- procedure General_Op (Obj : I'Class) is - -- begin - -- P (Obj); - -- end General_Op; - - if Is_Class_Wide_Type (Actual_Typ) - and then Etype (Actual_Typ) = Formal_Typ - then + if Actual_Typ = Formal_Typ then null; - -- No need to displace the pointer if the type of the actual is a - -- derivation of the formal-type interface because in this case - -- the interface primitives are located in the primary dispatch - -- table. + -- No need to displace the pointer if the interface type is + -- a parent of the type of the actual because in this case the + -- interface primitives are located in the primary dispatch table. elsif Is_Parent (Formal_Typ, Actual_Typ) then null; + -- Implicit conversion to the class-wide formal type to force + -- the displacement of the pointer. + else Conversion := Convert_To (Formal_Typ, Relocate_Node (Actual)); - Rewrite (Actual, Conversion); + Rewrite (Actual, Conversion); Analyze_And_Resolve (Actual, Formal_Typ); end if; - -- Anonymous access type + -- Access to class-wide interface type elsif Is_Access_Type (Formal_Typ) - and then Is_Interface (Etype (Formal_DDT)) + and then Is_Interface (Formal_DDT) + and then Is_Class_Wide_Type (Formal_DDT) and then Interface_Present_In_Ancestor (Typ => Actual_DDT, Iface => Etype (Formal_DDT)) then + -- Handle attributes 'Access and 'Unchecked_Access + if Nkind (Actual) = N_Attribute_Reference and then (Attribute_Name (Actual) = Name_Access @@ -1228,33 +928,26 @@ package body Exp_Disp is then Nam := Attribute_Name (Actual); - Conversion := Convert_To (Etype (Formal_DDT), Prefix (Actual)); - + Conversion := Convert_To (Formal_DDT, Prefix (Actual)); Rewrite (Actual, Conversion); - Analyze_And_Resolve (Actual, Etype (Formal_DDT)); + Analyze_And_Resolve (Actual, Formal_DDT); Rewrite (Actual, Unchecked_Convert_To (Formal_Typ, Make_Attribute_Reference (Loc, Prefix => Relocate_Node (Actual), Attribute_Name => Nam))); - Analyze_And_Resolve (Actual, Formal_Typ); - -- No need to displace the pointer if the actual is a class-wide - -- type of the formal-type interface because in this case the - -- displacement of the pointer was already done at the point of - -- the call to the enclosing subprogram (this case is similar - -- to the example described above for the non access-type case) + -- No need to displace the pointer if the type of the actual + -- coincides with the type of the formal. - elsif Is_Class_Wide_Type (Actual_DDT) - and then Etype (Actual_DDT) = Formal_DDT - then + elsif Actual_DDT = Formal_DDT then null; - -- No need to displace the pointer if the type of the actual is a - -- derivation of the interface (because in this case the interface - -- primitives are located in the primary dispatch table) + -- No need to displace the pointer if the interface type is + -- a parent of the type of the actual because in this case the + -- interface primitives are located in the primary dispatch table. elsif Is_Parent (Formal_DDT, Actual_DDT) then null; @@ -1320,24 +1013,35 @@ package body Exp_Disp is -- Expand_Interface_Thunk -- ---------------------------- - function Expand_Interface_Thunk + procedure Expand_Interface_Thunk (N : Node_Id; Thunk_Alias : Entity_Id; - Thunk_Id : Entity_Id) return Node_Id + Thunk_Id : out Entity_Id; + Thunk_Code : out Node_Id) is - Loc : constant Source_Ptr := Sloc (N); - Actuals : constant List_Id := New_List; - Decl : constant List_Id := New_List; - Formals : constant List_Id := New_List; - Target : Entity_Id; - New_Code : Node_Id; - Formal : Node_Id; - New_Formal : Node_Id; - Decl_1 : Node_Id; - Decl_2 : Node_Id; - E : Entity_Id; + Loc : constant Source_Ptr := Sloc (N); + Actuals : constant List_Id := New_List; + Decl : constant List_Id := New_List; + Formals : constant List_Id := New_List; + + Controlling_Typ : Entity_Id; + Decl_1 : Node_Id; + Decl_2 : Node_Id; + Formal : Node_Id; + Target : Entity_Id; + Target_Formal : Entity_Id; begin + Thunk_Id := Empty; + Thunk_Code := Empty; + + -- Give message if configurable run-time and Offset_To_Top unavailable + + if not RTE_Available (RE_Offset_To_Top) then + Error_Msg_CRT ("abstract interface types", N); + return; + end if; + -- Traverse the list of alias to find the final target Target := Thunk_Alias; @@ -1345,167 +1049,182 @@ package body Exp_Disp is Target := Alias (Target); end loop; + -- In case of primitives that are functions without formals and + -- a controlling result there is no need to build the thunk. + + if not Present (First_Formal (Target)) then + pragma Assert (Ekind (Target) = E_Function + and then Has_Controlling_Result (Target)); + return; + end if; + -- Duplicate the formals Formal := First_Formal (Target); - E := First_Formal (N); while Present (Formal) loop - New_Formal := Copy_Separate_Tree (Parent (Formal)); - - -- Propagate the parameter type to the copy. This is required to - -- properly handle the case in which the subprogram covering the - -- interface has been inherited: - - -- Example: - -- type I is interface; - -- procedure P (X : I) is abstract; - - -- type T is tagged null record; - -- procedure P (X : T); - - -- type DT is new T and I with ... - - Set_Parameter_Type (New_Formal, New_Reference_To (Etype (E), Loc)); - Append_To (Formals, New_Formal); + Append_To (Formals, + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Sloc (Formal), + Chars => Chars (Formal)), + In_Present => In_Present (Parent (Formal)), + Out_Present => Out_Present (Parent (Formal)), + Parameter_Type => + New_Reference_To (Etype (Formal), Loc), + Expression => New_Copy_Tree (Expression (Parent (Formal))))); Next_Formal (Formal); - Next_Formal (E); end loop; - -- Give message if configurable run-time and Offset_To_Top unavailable - - if not RTE_Available (RE_Offset_To_Top) then - Error_Msg_CRT ("abstract interface types", N); - return Empty; - end if; - if Ekind (First_Formal (Target)) = E_In_Parameter and then Ekind (Etype (First_Formal (Target))) = E_Anonymous_Access_Type then - -- Generate: - - -- type T is access all <> - -- S1 := Storage_Offset!(First_formal) - -- - Offset_To_Top (First_Formal.Tag) + Controlling_Typ := + Directly_Designated_Type (Etype (First_Formal (Target))); + else + Controlling_Typ := Etype (First_Formal (Target)); + end if; - -- ... and the first actual of the call is generated as T!(S1) + Target_Formal := First_Formal (Target); + Formal := First (Formals); + while Present (Formal) loop + if Ekind (Target_Formal) = E_In_Parameter + and then Ekind (Etype (Target_Formal)) = E_Anonymous_Access_Type + and then Directly_Designated_Type (Etype (Target_Formal)) + = Controlling_Typ + then + -- Generate: - Decl_2 := - Make_Full_Type_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, - New_Internal_Name ('T')), - Type_Definition => - Make_Access_To_Object_Definition (Loc, - All_Present => True, - Null_Exclusion_Present => False, - Constant_Present => False, - Subtype_Indication => - New_Reference_To - (Directly_Designated_Type - (Etype (First_Formal (Target))), Loc))); - - Decl_1 := - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, - New_Internal_Name ('S')), - Constant_Present => True, - Object_Definition => - New_Reference_To (RTE (RE_Storage_Offset), Loc), - Expression => - Make_Op_Subtract (Loc, - Left_Opnd => - Unchecked_Convert_To - (RTE (RE_Storage_Offset), + -- type T is access all <> + -- S1 := Storage_Offset!(formal) + -- - Offset_To_Top (Formal.Tag) + + -- ... and the first actual of the call is generated as T!(S1) + + Decl_2 := + Make_Full_Type_Declaration (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, + New_Internal_Name ('T')), + Type_Definition => + Make_Access_To_Object_Definition (Loc, + All_Present => True, + Null_Exclusion_Present => False, + Constant_Present => False, + Subtype_Indication => New_Reference_To - (Defining_Identifier (First (Formals)), Loc)), - Right_Opnd => - Make_Function_Call (Loc, - Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc), - Parameter_Associations => New_List ( - Unchecked_Convert_To - (RTE (RE_Address), - New_Reference_To - (Defining_Identifier (First (Formals)), Loc)))))); + (Directly_Designated_Type + (Etype (Target_Formal)), Loc))); + + Decl_1 := + Make_Object_Declaration (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, + New_Internal_Name ('S')), + Constant_Present => True, + Object_Definition => + New_Reference_To (RTE (RE_Storage_Offset), Loc), + Expression => + Make_Op_Subtract (Loc, + Left_Opnd => + Unchecked_Convert_To + (RTE (RE_Storage_Offset), + New_Reference_To (Defining_Identifier (Formal), Loc)), + Right_Opnd => + Make_Function_Call (Loc, + Name => + New_Reference_To (RTE (RE_Offset_To_Top), Loc), + Parameter_Associations => New_List ( + Unchecked_Convert_To + (RTE (RE_Address), + New_Reference_To + (Defining_Identifier (Formal), Loc)))))); + + Append_To (Decl, Decl_2); + Append_To (Decl, Decl_1); + + -- Reference the new first actual + + Append_To (Actuals, + Unchecked_Convert_To + (Defining_Identifier (Decl_2), + New_Reference_To (Defining_Identifier (Decl_1), Loc))); + + elsif Etype (Target_Formal) = Controlling_Typ then + -- Generate: - Append_To (Decl, Decl_2); - Append_To (Decl, Decl_1); + -- S1 := Storage_Offset!(Formal'Address) + -- - Offset_To_Top (Formal.Tag) + -- S2 := Tag_Ptr!(S3) - -- Reference the new first actual + Decl_1 := + Make_Object_Declaration (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, New_Internal_Name ('S')), + Constant_Present => True, + Object_Definition => + New_Reference_To (RTE (RE_Storage_Offset), Loc), + Expression => + Make_Op_Subtract (Loc, + Left_Opnd => + Unchecked_Convert_To + (RTE (RE_Storage_Offset), + Make_Attribute_Reference (Loc, + Prefix => + New_Reference_To + (Defining_Identifier (Formal), Loc), + Attribute_Name => Name_Address)), + Right_Opnd => + Make_Function_Call (Loc, + Name => + New_Reference_To (RTE (RE_Offset_To_Top), Loc), + Parameter_Associations => New_List ( + Make_Attribute_Reference (Loc, + Prefix => + New_Reference_To + (Defining_Identifier (Formal), Loc), + Attribute_Name => Name_Address))))); - Append_To (Actuals, - Unchecked_Convert_To - (Defining_Identifier (Decl_2), - New_Reference_To (Defining_Identifier (Decl_1), Loc))); + Decl_2 := + Make_Object_Declaration (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, New_Internal_Name ('S')), + Constant_Present => True, + Object_Definition => New_Reference_To (RTE (RE_Addr_Ptr), Loc), + Expression => + Unchecked_Convert_To + (RTE (RE_Addr_Ptr), + New_Reference_To (Defining_Identifier (Decl_1), Loc))); - else - -- Generate: + Append_To (Decl, Decl_1); + Append_To (Decl, Decl_2); - -- S1 := Storage_Offset!(First_formal'Address) - -- - Offset_To_Top (First_Formal.Tag) - -- S2 := Tag_Ptr!(S3) + -- Reference the new first actual - Decl_1 := - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, New_Internal_Name ('S')), - Constant_Present => True, - Object_Definition => - New_Reference_To (RTE (RE_Storage_Offset), Loc), - Expression => - Make_Op_Subtract (Loc, - Left_Opnd => - Unchecked_Convert_To - (RTE (RE_Storage_Offset), - Make_Attribute_Reference (Loc, - Prefix => - New_Reference_To - (Defining_Identifier (First (Formals)), Loc), - Attribute_Name => Name_Address)), - Right_Opnd => - Make_Function_Call (Loc, - Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc), - Parameter_Associations => New_List ( - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To - (Defining_Identifier (First (Formals)), - Loc), - Attribute_Name => Name_Address))))); + Append_To (Actuals, + Unchecked_Convert_To + (Etype (First_Entity (Target)), + Make_Explicit_Dereference (Loc, + New_Reference_To (Defining_Identifier (Decl_2), Loc)))); - Decl_2 := - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, New_Internal_Name ('S')), - Constant_Present => True, - Object_Definition => New_Reference_To (RTE (RE_Addr_Ptr), Loc), - Expression => - Unchecked_Convert_To - (RTE (RE_Addr_Ptr), - New_Reference_To (Defining_Identifier (Decl_1), Loc))); - - Append_To (Decl, Decl_1); - Append_To (Decl, Decl_2); - - -- Reference the new first actual - - Append_To (Actuals, - Unchecked_Convert_To - (Etype (First_Entity (Target)), - Make_Explicit_Dereference (Loc, - New_Reference_To (Defining_Identifier (Decl_2), Loc)))); - end if; + -- No special management required for this actual - Formal := Next (First (Formals)); - while Present (Formal) loop - Append_To (Actuals, - New_Reference_To (Defining_Identifier (Formal), Loc)); + else + Append_To (Actuals, + New_Reference_To (Defining_Identifier (Formal), Loc)); + end if; + + Next_Formal (Target_Formal); Next (Formal); end loop; + Thunk_Id := + Make_Defining_Identifier (Loc, + Chars => New_Internal_Name ('T')); + if Ekind (Target) = E_Procedure then - New_Code := + Thunk_Code := Make_Subprogram_Body (Loc, Specification => Make_Procedure_Specification (Loc, @@ -1516,12 +1235,12 @@ package body Exp_Disp is Make_Handled_Sequence_Of_Statements (Loc, Statements => New_List ( Make_Procedure_Call_Statement (Loc, - Name => New_Occurrence_Of (Target, Loc), - Parameter_Associations => Actuals)))); + Name => New_Occurrence_Of (Target, Loc), + Parameter_Associations => Actuals)))); else pragma Assert (Ekind (Target) = E_Function); - New_Code := + Thunk_Code := Make_Subprogram_Body (Loc, Specification => Make_Function_Specification (Loc, @@ -1538,98 +1257,8 @@ package body Exp_Disp is Name => New_Occurrence_Of (Target, Loc), Parameter_Associations => Actuals))))); end if; - - -- Analyze the code of the thunk with checks suppressed because we are - -- in the middle of building the dispatch information itself and some - -- characteristics of the type may not be fully available. - - Analyze (New_Code, Suppress => All_Checks); - return New_Code; end Expand_Interface_Thunk; - ------------------- - -- Fill_DT_Entry -- - ------------------- - - function Fill_DT_Entry - (Loc : Source_Ptr; - Prim : Entity_Id) return Node_Id - is - Typ : constant Entity_Id := Scope (DTC_Entity (Prim)); - DT_Ptr : constant Entity_Id := - Node (First_Elmt (Access_Disp_Table (Typ))); - Pos : constant Uint := DT_Position (Prim); - Tag : constant Entity_Id := First_Tag_Component (Typ); - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - if Is_Predefined_Dispatching_Operation (Prim) - or else Is_Predefined_Dispatching_Alias (Prim) - then - return - Build_Set_Predefined_Prim_Op_Address (Loc, - Tag_Node => New_Reference_To (DT_Ptr, Loc), - Position_Node => Make_Integer_Literal (Loc, Pos), - Address_Node => Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Prim, Loc), - Attribute_Name => Name_Address)); - - else - pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag)); - - return - Build_Set_Prim_Op_Address (Loc, - Tag_Node => New_Reference_To (DT_Ptr, Loc), - Position_Node => Make_Integer_Literal (Loc, Pos), - Address_Node => Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Prim, Loc), - Attribute_Name => Name_Address)); - end if; - end Fill_DT_Entry; - - ----------------------------- - -- Fill_Secondary_DT_Entry -- - ----------------------------- - - function Fill_Secondary_DT_Entry - (Loc : Source_Ptr; - Prim : Entity_Id; - Thunk_Id : Entity_Id; - Iface_DT_Ptr : Entity_Id) return Node_Id - is - Iface_Prim : constant Entity_Id := Abstract_Interface_Alias (Prim); - Pos : constant Uint := DT_Position (Iface_Prim); - Tag : constant Entity_Id := - First_Tag_Component (Scope (DTC_Entity (Iface_Prim))); - - begin - if Is_Predefined_Dispatching_Operation (Prim) - or else Is_Predefined_Dispatching_Alias (Prim) - then - return - Build_Set_Predefined_Prim_Op_Address (Loc, - Tag_Node => - New_Reference_To (Iface_DT_Ptr, Loc), - Position_Node => - Make_Integer_Literal (Loc, Pos), - Address_Node => - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Thunk_Id, Loc), - Attribute_Name => Name_Address)); - else - pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag)); - - return - Build_Set_Prim_Op_Address (Loc, - Tag_Node => New_Reference_To (Iface_DT_Ptr, Loc), - Position_Node => Make_Integer_Literal (Loc, Pos), - Address_Node => Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Thunk_Id, Loc), - Attribute_Name => Name_Address)); - end if; - end Fill_Secondary_DT_Entry; - ------------------------------------- -- Is_Predefined_Dispatching_Alias -- ------------------------------------- @@ -1662,11 +1291,12 @@ package body Exp_Disp is function Make_Disp_Asynchronous_Select_Body (Typ : Entity_Id) return Node_Id is - Conc_Typ : Entity_Id := Empty; - Decls : constant List_Id := New_List; - DT_Ptr : Entity_Id; - Loc : constant Source_Ptr := Sloc (Typ); - Stmts : constant List_Id := New_List; + Com_Block : Entity_Id; + Conc_Typ : Entity_Id := Empty; + Decls : constant List_Id := New_List; + DT_Ptr : Entity_Id; + Loc : constant Source_Ptr := Sloc (Typ); + Stmts : constant List_Id := New_List; begin pragma Assert (not Restriction_Active (No_Dispatching_Calls)); @@ -1703,24 +1333,35 @@ package body Exp_Disp is Object_Definition => New_Reference_To (Standard_Integer, Loc), Expression => - Make_DT_Access_Action (Typ, - Action => - Get_Entry_Index, - Args => - New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (DT_Ptr, Loc)), - Make_Identifier (Loc, Name_uS))))); + Make_Function_Call (Loc, + Name => New_Reference_To (RTE (RE_Get_Entry_Index), Loc), + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Tag), + New_Reference_To (DT_Ptr, Loc)), + Make_Identifier (Loc, Name_uS))))); if Ekind (Conc_Typ) = E_Protected_Type then + -- Generate: + -- Com_Block : Communication_Block; + + Com_Block := + Make_Defining_Identifier (Loc, New_Internal_Name ('B')); + + Append_To (Decls, + Make_Object_Declaration (Loc, + Defining_Identifier => + Com_Block, + Object_Definition => + New_Reference_To (RTE (RE_Communication_Block), Loc))); + -- Generate: -- Protected_Entry_Call ( -- T._object'access, -- protected_entry_index! (I), -- P, -- Asynchronous_Call, - -- B); + -- Com_Block); -- where T is the protected object, I is the entry index, P are -- the wrapped parameters and B is the name of the communication @@ -1752,7 +1393,24 @@ package body Exp_Disp is Make_Identifier (Loc, Name_uP), -- parameter block New_Reference_To ( -- Asynchronous_Call RTE (RE_Asynchronous_Call), Loc), - Make_Identifier (Loc, Name_uB)))); -- comm block + + New_Reference_To (Com_Block, Loc)))); -- comm block + + -- Generate: + -- B := Dummy_Communication_Bloc (Com_Block); + + Append_To (Stmts, + Make_Assignment_Statement (Loc, + Name => + Make_Identifier (Loc, Name_uB), + Expression => + Make_Unchecked_Type_Conversion (Loc, + Subtype_Mark => + New_Reference_To ( + RTE (RE_Dummy_Communication_Block), Loc), + Expression => + New_Reference_To (Com_Block, Loc)))); + else pragma Assert (Ekind (Conc_Typ) = E_Task_Type); @@ -1819,24 +1477,52 @@ package body Exp_Disp is begin pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - -- "T" - Object parameter - -- "S" - Primitive operation slot - -- "P" - Wrapped parameters - -- "B" - Communication block - -- "F" - Status flag + -- T : in out Typ; -- Object parameter + -- S : Integer; -- Primitive operation slot + -- P : Address; -- Wrapped parameters + -- B : out Dummy_Communication_Block; -- Communication block dummy + -- F : out Boolean; -- Status flag - SEU.Build_T (Loc, Typ, Params); - SEU.Build_S (Loc, Params); - SEU.Build_P (Loc, Params); - SEU.Build_B (Loc, Params); - SEU.Build_F (Loc, Params); + Append_List_To (Params, New_List ( + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uT), + Parameter_Type => + New_Reference_To (Typ, Loc), + In_Present => True, + Out_Present => True), + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uS), + Parameter_Type => + New_Reference_To (Standard_Integer, Loc)), + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uP), + Parameter_Type => + New_Reference_To (RTE (RE_Address), Loc)), + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uB), + Parameter_Type => + New_Reference_To (RTE (RE_Dummy_Communication_Block), Loc), + Out_Present => True), - Set_Is_Internal (Def_Id); + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uF), + Parameter_Type => + New_Reference_To (Standard_Boolean, Loc), + Out_Present => True))); return - Make_Procedure_Specification (Loc, - Defining_Unit_Name => Def_Id, - Parameter_Specifications => Params); + Make_Procedure_Specification (Loc, + Defining_Unit_Name => Def_Id, + Parameter_Specifications => Params); end Make_Disp_Asynchronous_Select_Spec; --------------------------------------- @@ -1899,8 +1585,7 @@ package body Exp_Disp is -- return; -- end if; - SEU.Build_Common_Dispatching_Select_Statements - (Loc, Typ, DT_Ptr, Stmts); + Build_Common_Dispatching_Select_Statements (Loc, DT_Ptr, Stmts); -- Generate: -- Bnn : Communication_Block; @@ -1927,14 +1612,12 @@ package body Exp_Disp is Name => Make_Identifier (Loc, Name_uI), Expression => - Make_DT_Access_Action (Typ, - Action => - Get_Entry_Index, - Args => - New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (DT_Ptr, Loc)), - Make_Identifier (Loc, Name_uS))))); + Make_Function_Call (Loc, + Name => New_Reference_To (RTE (RE_Get_Entry_Index), Loc), + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Tag), + New_Reference_To (DT_Ptr, Loc)), + Make_Identifier (Loc, Name_uS))))); if Ekind (Conc_Typ) = E_Protected_Type then @@ -2064,19 +1747,47 @@ package body Exp_Disp is begin pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - -- "T" - Object parameter - -- "S" - Primitive operation slot - -- "P" - Wrapped parameters - -- "C" - Call kind - -- "F" - Status flag + -- T : in out Typ; -- Object parameter + -- S : Integer; -- Primitive operation slot + -- P : Address; -- Wrapped parameters + -- C : out Prim_Op_Kind; -- Call kind + -- F : out Boolean; -- Status flag + + Append_List_To (Params, New_List ( + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uT), + Parameter_Type => + New_Reference_To (Typ, Loc), + In_Present => True, + Out_Present => True), + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uS), + Parameter_Type => + New_Reference_To (Standard_Integer, Loc)), + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uP), + Parameter_Type => + New_Reference_To (RTE (RE_Address), Loc)), - SEU.Build_T (Loc, Typ, Params); - SEU.Build_S (Loc, Params); - SEU.Build_P (Loc, Params); - SEU.Build_C (Loc, Params); - SEU.Build_F (Loc, Params); + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uC), + Parameter_Type => + New_Reference_To (RTE (RE_Prim_Op_Kind), Loc), + Out_Present => True), - Set_Is_Internal (Def_Id); + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uF), + Parameter_Type => + New_Reference_To (Standard_Boolean, Loc), + Out_Present => True))); return Make_Procedure_Specification (Loc, @@ -2130,14 +1841,13 @@ package body Exp_Disp is Name => Make_Identifier (Loc, Name_uC), Expression => - Make_DT_Access_Action (Typ, - Action => - Get_Prim_Op_Kind, - Args => - New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (DT_Ptr, Loc)), - Make_Identifier (Loc, Name_uS))))))); + Make_Function_Call (Loc, + Name => + New_Reference_To (RTE (RE_Get_Prim_Op_Kind), Loc), + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Tag), + New_Reference_To (DT_Ptr, Loc)), + Make_Identifier (Loc, Name_uS))))))); end Make_Disp_Get_Prim_Op_Kind_Body; ------------------------------------- @@ -2156,15 +1866,32 @@ package body Exp_Disp is begin pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - -- "T" - Object parameter - -- "S" - Primitive operation slot - -- "C" - Call kind + -- T : in out Typ; -- Object parameter + -- S : Integer; -- Primitive operation slot + -- C : out Prim_Op_Kind; -- Call kind + + Append_List_To (Params, New_List ( + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uT), + Parameter_Type => + New_Reference_To (Typ, Loc), + In_Present => True, + Out_Present => True), - SEU.Build_T (Loc, Typ, Params); - SEU.Build_S (Loc, Params); - SEU.Build_C (Loc, Params); + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uS), + Parameter_Type => + New_Reference_To (Standard_Integer, Loc)), - Set_Is_Internal (Def_Id); + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uC), + Parameter_Type => + New_Reference_To (RTE (RE_Prim_Op_Kind), Loc), + Out_Present => True))); return Make_Procedure_Specification (Loc, @@ -2188,22 +1915,32 @@ package body Exp_Disp is if Is_Concurrent_Record_Type (Typ) and then Ekind (Corresponding_Concurrent_Type (Typ)) = E_Task_Type then + -- Generate: + -- return To_Address (_T._task_id); + Ret := Make_Return_Statement (Loc, Expression => - Make_Selected_Component (Loc, - Prefix => - Make_Identifier (Loc, Name_uT), - Selector_Name => - Make_Identifier (Loc, Name_uTask_Id))); + Make_Unchecked_Type_Conversion (Loc, + Subtype_Mark => + New_Reference_To (RTE (RE_Address), Loc), + Expression => + Make_Selected_Component (Loc, + Prefix => + Make_Identifier (Loc, Name_uT), + Selector_Name => + Make_Identifier (Loc, Name_uTask_Id)))); -- A null body is constructed for non-task types else + -- Generate: + -- return Null_Address; + Ret := Make_Return_Statement (Loc, Expression => - New_Reference_To (RTE (RO_ST_Null_Task), Loc)); + New_Reference_To (RTE (RE_Null_Address), Loc)); end if; return @@ -2224,19 +1961,15 @@ package body Exp_Disp is function Make_Disp_Get_Task_Id_Spec (Typ : Entity_Id) return Node_Id is - Loc : constant Source_Ptr := Sloc (Typ); - Def_Id : constant Node_Id := - Make_Defining_Identifier (Loc, - Name_uDisp_Get_Task_Id); + Loc : constant Source_Ptr := Sloc (Typ); begin pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - Set_Is_Internal (Def_Id); - return Make_Function_Specification (Loc, - Defining_Unit_Name => Def_Id, + Defining_Unit_Name => + Make_Defining_Identifier (Loc, Name_uDisp_Get_Task_Id), Parameter_Specifications => New_List ( Make_Parameter_Specification (Loc, Defining_Identifier => @@ -2244,7 +1977,7 @@ package body Exp_Disp is Parameter_Type => New_Reference_To (Typ, Loc))), Result_Definition => - New_Reference_To (RTE (RO_ST_Task_Id), Loc)); + New_Reference_To (RTE (RE_Address), Loc)); end Make_Disp_Get_Task_Id_Spec; --------------------------------- @@ -2306,8 +2039,7 @@ package body Exp_Disp is -- return; -- end if; - SEU.Build_Common_Dispatching_Select_Statements - (Loc, Typ, DT_Ptr, Stmts); + Build_Common_Dispatching_Select_Statements (Loc, DT_Ptr, Stmts); -- Generate: -- I := Get_Entry_Index (tag! (VP), S); @@ -2319,14 +2051,12 @@ package body Exp_Disp is Name => Make_Identifier (Loc, Name_uI), Expression => - Make_DT_Access_Action (Typ, - Action => - Get_Entry_Index, - Args => - New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (DT_Ptr, Loc)), - Make_Identifier (Loc, Name_uS))))); + Make_Function_Call (Loc, + Name => New_Reference_To (RTE (RE_Get_Entry_Index), Loc), + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Tag), + New_Reference_To (DT_Ptr, Loc)), + Make_Identifier (Loc, Name_uS))))); if Ekind (Conc_Typ) = E_Protected_Type then @@ -2439,36 +2169,62 @@ package body Exp_Disp is begin pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - -- "T" - Object parameter - -- "S" - Primitive operation slot - -- "P" - Wrapped parameters - -- "D" - Delay - -- "M" - Delay Mode - -- "C" - Call kind - -- "F" - Status flag + -- T : in out Typ; -- Object parameter + -- S : Integer; -- Primitive operation slot + -- P : Address; -- Wrapped parameters + -- D : Duration; -- Delay + -- M : Integer; -- Delay Mode + -- C : out Prim_Op_Kind; -- Call kind + -- F : out Boolean; -- Status flag - SEU.Build_T (Loc, Typ, Params); - SEU.Build_S (Loc, Params); - SEU.Build_P (Loc, Params); + Append_List_To (Params, New_List ( + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uT), + Parameter_Type => + New_Reference_To (Typ, Loc), + In_Present => True, + Out_Present => True), + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uS), + Parameter_Type => + New_Reference_To (Standard_Integer, Loc)), + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uP), + Parameter_Type => + New_Reference_To (RTE (RE_Address), Loc)), - Append_To (Params, Make_Parameter_Specification (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Name_uD), Parameter_Type => - New_Reference_To (Standard_Duration, Loc))); + New_Reference_To (Standard_Duration, Loc)), - Append_To (Params, Make_Parameter_Specification (Loc, Defining_Identifier => Make_Defining_Identifier (Loc, Name_uM), Parameter_Type => - New_Reference_To (Standard_Integer, Loc))); + New_Reference_To (Standard_Integer, Loc)), - SEU.Build_C (Loc, Params); - SEU.Build_F (Loc, Params); + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uC), + Parameter_Type => + New_Reference_To (RTE (RE_Prim_Op_Kind), Loc), + Out_Present => True))); - Set_Is_Internal (Def_Id); + Append_To (Params, + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, Name_uF), + Parameter_Type => + New_Reference_To (Standard_Boolean, Loc), + Out_Present => True)); return Make_Procedure_Specification (Loc, @@ -2480,320 +2236,898 @@ package body Exp_Disp is -- Make_DT -- ------------- - function Make_DT (Typ : Entity_Id) return List_Id is - Loc : constant Source_Ptr := Sloc (Typ); - Result : constant List_Id := New_List; - Elab_Code : constant List_Id := New_List; - - Tname : constant Name_Id := Chars (Typ); - Name_DT : constant Name_Id := New_External_Name (Tname, 'T'); - Name_DT_Ptr : constant Name_Id := New_External_Name (Tname, 'P'); - Name_SSD : constant Name_Id := New_External_Name (Tname, 'S'); - Name_TSD : constant Name_Id := New_External_Name (Tname, 'B'); - Name_Exname : constant Name_Id := New_External_Name (Tname, 'E'); - Name_No_Reg : constant Name_Id := New_External_Name (Tname, 'F'); - - -- The following external name is only generated if Typ has interfaces - Name_ITable : Name_Id; - - DT : constant Node_Id := Make_Defining_Identifier (Loc, Name_DT); - DT_Ptr : constant Node_Id := Make_Defining_Identifier (Loc, Name_DT_Ptr); - SSD : constant Node_Id := Make_Defining_Identifier (Loc, Name_SSD); - TSD : constant Node_Id := Make_Defining_Identifier (Loc, Name_TSD); - Exname : constant Node_Id := Make_Defining_Identifier (Loc, Name_Exname); - No_Reg : constant Node_Id := Make_Defining_Identifier (Loc, Name_No_Reg); + -- The frontend supports two models for expanding dispatch tables + -- associated with library-level defined tagged types: statically + -- and non-statically allocated dispatch tables. In the former case + -- the object containing the dispatch table is constant and it is + -- initialized by means of a positional aggregate. In the latter case, + -- the object containing the dispatch table is a variable which is + -- initialized by means of assignments. + + -- In case of locally defined tagged types, the object containing the + -- object containing the dispatch table is always a variable (instead + -- of a constant). This is currently required to give support to late + -- overriding of primitives. For example: + + -- procedure Example is + -- package Pkg is + -- type T1 is tagged null record; + -- procedure Prim (O : T1); + -- end Pkg; + + -- type T2 is new Pkg.T1 with null record; + -- procedure Prim (X : T2) is -- late overriding + -- begin + -- ... + -- ... + -- end; - Generalized_Tag : constant Entity_Id := RTE (RE_Tag); - Ancestor_Ifaces : Elist_Id; - AI : Elmt_Id; - Has_Dispatch_Table : Boolean := True; - I_Depth : Nat := 0; - ITable : Node_Id; - Iface_Table_Node : Node_Id; - Nb_Prim : Nat := 0; - Null_Parent_Tag : Boolean := False; - Num_Ifaces : Nat := 0; - Old_Tag1 : Node_Id; - Old_Tag2 : Node_Id; - Parent : Entity_Id; - Parent_Num_Ifaces : Nat := 0; - Remotely_Callable : Entity_Id; - RC_Offset_Node : Node_Id; - Size_Expr_Node : Node_Id; - Typ_Ifaces : Elist_Id; - TSD_Aggr_List : List_Id; + function Make_DT (Typ : Entity_Id) return List_Id is + Loc : constant Source_Ptr := Sloc (Typ); + Is_Local_DT : constant Boolean := + Ekind (Cunit_Entity (Get_Source_Unit (Typ))) + /= E_Package; + Max_Predef_Prims : constant Int := + UI_To_Int + (Intval + (Expression + (Parent (RTE (RE_Default_Prim_Op_Count))))); + + procedure Make_Secondary_DT + (Typ : Entity_Id; + Iface : Entity_Id; + AI_Tag : Entity_Id; + Iface_DT_Ptr : Entity_Id; + Result : List_Id); + -- Ada 2005 (AI-251): Expand the declarations for the Secondary Dispatch + -- Table of Typ associated with Iface (each abstract interface of Typ + -- has a secondary dispatch table). The arguments Typ, Ancestor_Typ + -- and Suffix_Index are used to generate an unique external name which + -- is added at the end of Acc_Disp_Tables; this external name will be + -- used later by the subprogram Exp_Ch3.Build_Init_Procedure. - begin - if not RTE_Available (RE_Tag) then - Error_Msg_CRT ("tagged types", Typ); - return New_List; - end if; + ----------------------- + -- Make_Secondary_DT -- + ----------------------- - -- Ensure that the unit System_Storage_Elements is loaded. This is - -- required to properly expand the routines of Ada.Tags + procedure Make_Secondary_DT + (Typ : Entity_Id; + Iface : Entity_Id; + AI_Tag : Entity_Id; + Iface_DT_Ptr : Entity_Id; + Result : List_Id) + is + Loc : constant Source_Ptr := Sloc (Typ); + Generalized_Tag : constant Entity_Id := RTE (RE_Interface_Tag); + + Name_DT : constant Name_Id := New_Internal_Name ('T'); + Iface_DT : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_DT); + Name_Predef_Prims : constant Name_Id := New_Internal_Name ('R'); + Predef_Prims : constant Entity_Id := + Make_Defining_Identifier (Loc, + Name_Predef_Prims); + DT_Constr_List : List_Id; + DT_Aggr_List : List_Id; + Empty_DT : Boolean := False; + Nb_Predef_Prims : Nat := 0; + Nb_Prim : Nat; + New_Node : Node_Id; + OSD : Entity_Id; + OSD_Aggr_List : List_Id; + Pos : Nat; + Prim : Entity_Id; + Prim_Elmt : Elmt_Id; + Prim_Ops_Aggr_List : List_Id; - if not RTU_Loaded (System_Storage_Elements) - and then not Present (RTE (RE_Storage_Offset)) - then - raise Program_Error; - end if; + begin + -- Handle the case where the backend does not support statically + -- allocated dispatch tables. - if Ada_Version >= Ada_05 then + if not Static_Dispatch_Tables + or else Is_Local_DT + then + Set_Ekind (Predef_Prims, E_Variable); + Set_Is_Statically_Allocated (Predef_Prims); - -- Count the interface types of the parents + Set_Ekind (Iface_DT, E_Variable); + Set_Is_Statically_Allocated (Iface_DT); - Parent := Empty; + -- Statically allocated dispatch tables and related entities are + -- constants. - if Typ /= Etype (Typ) then - Parent := Etype (Typ); + else + Set_Ekind (Predef_Prims, E_Constant); + Set_Is_Statically_Allocated (Predef_Prims); + Set_Is_True_Constant (Predef_Prims); - elsif Is_Concurrent_Record_Type (Typ) then - Parent := Etype (First (Abstract_Interface_List (Typ))); + Set_Ekind (Iface_DT, E_Constant); + Set_Is_Statically_Allocated (Iface_DT); + Set_Is_True_Constant (Iface_DT); end if; - if Present (Parent) then - Collect_Abstract_Interfaces (Parent, Ancestor_Ifaces); + -- Generate code to create the storage for the Dispatch_Table object. + -- If the number of primitives of Typ is 0 we reserve a dummy single + -- entry for its DT because at run-time the pointer to this dummy + -- entry will be used as the tag. - AI := First_Elmt (Ancestor_Ifaces); - while Present (AI) loop - Parent_Num_Ifaces := Parent_Num_Ifaces + 1; - Next_Elmt (AI); - end loop; - end if; + Nb_Prim := UI_To_Int (DT_Entry_Count (AI_Tag)); - -- Count the additional interfaces implemented by Typ + if Nb_Prim = 0 then + Empty_DT := True; + Nb_Prim := 1; + end if; - Collect_Abstract_Interfaces (Typ, Typ_Ifaces); + -- Generate: - AI := First_Elmt (Typ_Ifaces); - while Present (AI) loop - Num_Ifaces := Num_Ifaces + 1; - Next_Elmt (AI); - end loop; - end if; + -- Predef_Prims : Address_Array (1 .. Default_Prim_Ops_Count) := + -- (predef-prim-op-thunk-1'address, + -- predef-prim-op-thunk-2'address, + -- ... + -- predef-prim-op-thunk-n'address); + -- for Predef_Prims'Alignment use Address'Alignment - -- Count ancestors to compute the inheritance depth. For private - -- extensions, always go to the full view in order to compute the - -- real inheritance depth. + -- Stage 1: Calculate the number of predefined primitives - declare - Parent_Type : Entity_Id := Typ; - P : Entity_Id; + if not Static_Dispatch_Tables then + Nb_Predef_Prims := Max_Predef_Prims; + else + Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); + while Present (Prim_Elmt) loop + Prim := Node (Prim_Elmt); - begin - I_Depth := 0; - loop - P := Etype (Parent_Type); + if Is_Predefined_Dispatching_Operation (Prim) + and then not Is_Abstract_Subprogram (Prim) + then + Pos := UI_To_Int (DT_Position (Prim)); - if Is_Private_Type (P) then - P := Full_View (Base_Type (P)); - end if; + if Pos > Nb_Predef_Prims then + Nb_Predef_Prims := Pos; + end if; + end if; - exit when P = Parent_Type; + Next_Elmt (Prim_Elmt); + end loop; + end if; - I_Depth := I_Depth + 1; - Parent_Type := P; - end loop; - end; + -- Stage 2: Create the thunks associated with the predefined + -- primitives and save their entity to fill the aggregate. - -- Calculate the number of primitives of the dispatch table and the - -- size of the Type_Specific_Data record. + declare + Prim_Table : array (Nat range 1 .. Nb_Predef_Prims) of Entity_Id; + Thunk_Id : Entity_Id; + Thunk_Code : Node_Id; - -- Abstract interfaces don't need the dispatch table. In addition, - -- compiling with restriction No_Dispatching_Calls we do not generate - -- the dispatch table. + begin + Prim_Ops_Aggr_List := New_List; + Prim_Table := (others => Empty); - Has_Dispatch_Table := - not Is_Interface (Typ) - and then not Restriction_Active (No_Dispatching_Calls); + Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); + while Present (Prim_Elmt) loop + Prim := Node (Prim_Elmt); - if Has_Dispatch_Table then - Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ))); - end if; + if Is_Predefined_Dispatching_Operation (Prim) + and then not Is_Abstract_Subprogram (Prim) + and then not Present (Prim_Table + (UI_To_Int (DT_Position (Prim)))) + then + while Present (Alias (Prim)) loop + Prim := Alias (Prim); + end loop; - -- Dispatch table and related entities are allocated statically + Expand_Interface_Thunk + (N => Prim, + Thunk_Alias => Prim, + Thunk_Id => Thunk_Id, + Thunk_Code => Thunk_Code); - Set_Ekind (DT, E_Variable); - Set_Is_Statically_Allocated (DT); + if Present (Thunk_Id) then + Append_To (Result, Thunk_Code); + Prim_Table (UI_To_Int (DT_Position (Prim))) := Thunk_Id; + end if; + end if; - Set_Ekind (DT_Ptr, E_Variable); - Set_Is_Statically_Allocated (DT_Ptr); + Next_Elmt (Prim_Elmt); + end loop; - if Num_Ifaces > 0 then - Name_ITable := New_External_Name (Tname, 'I'); - ITable := Make_Defining_Identifier (Loc, Name_ITable); + for J in Prim_Table'Range loop + if Present (Prim_Table (J)) then + New_Node := + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Prim_Table (J), Loc), + Attribute_Name => Name_Address); + else + New_Node := + New_Reference_To (RTE (RE_Null_Address), Loc); + end if; - Set_Ekind (ITable, E_Variable); - Set_Is_Statically_Allocated (ITable); - end if; + Append_To (Prim_Ops_Aggr_List, New_Node); + end loop; - Set_Ekind (SSD, E_Variable); - Set_Is_Statically_Allocated (SSD); + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => Predef_Prims, + Constant_Present => Static_Dispatch_Tables, + Aliased_Present => True, + Object_Definition => + New_Reference_To (RTE (RE_Address_Array), Loc), + Expression => Make_Aggregate (Loc, + Expressions => Prim_Ops_Aggr_List))); - Set_Ekind (TSD, E_Variable); - Set_Is_Statically_Allocated (TSD); + Append_To (Result, + Make_Attribute_Definition_Clause (Loc, + Name => New_Reference_To (Predef_Prims, Loc), + Chars => Name_Alignment, + Expression => + Make_Attribute_Reference (Loc, + Prefix => + New_Reference_To (RTE (RE_Integer_Address), Loc), + Attribute_Name => Name_Alignment))); + end; - Set_Ekind (Exname, E_Variable); - Set_Is_Statically_Allocated (Exname); + -- Generate - Set_Ekind (No_Reg, E_Variable); - Set_Is_Statically_Allocated (No_Reg); + -- OSD : Ada.Tags.Object_Specific_Data (Nb_Prims) := + -- (OSD_Table => (1 => , + -- ... + -- N => )); - -- Generate code to create the storage for the Dispatch_Table object: + -- Iface_DT : Dispatch_Table (Nb_Prims) := + -- ([ Signature => ], + -- Tag_Kind => , + -- Predef_Prims => Predef_Prims'Address, + -- Offset_To_Top => 0, + -- OSD => OSD'Address, + -- Prims_Ptr => (prim-op-1'address, + -- prim-op-2'address, + -- ... + -- prim-op-n'address)); - -- DT : Storage_Array (1 .. Size_Expr); - -- for DT'Alignment use Address'Alignment + -- Stage 3: Initialize the discriminant and the record components - -- Under No_Dispatching_Calls the size of the table is small just - -- containing: - -- 1) the pointer to the TSD - -- 2) a dummy entry used as the Tag of the type (see a-tags.ads). + DT_Constr_List := New_List; + DT_Aggr_List := New_List; - if not Has_Dispatch_Table then - Size_Expr_Node := - New_Reference_To (RTE (RE_DT_Min_Prologue_Size), Loc); + -- Nb_Prim. If the tagged type has no primitives we add a dummy + -- slot whose address will be the tag of this type. - -- If the object has no primitives we ensure that the table will - -- have at least a dummy entry which will be used as the Tag. + if Nb_Prim = 0 then + New_Node := Make_Integer_Literal (Loc, 1); + else + New_Node := Make_Integer_Literal (Loc, Nb_Prim); + end if; - -- Size_Expr := DT_Prologue_Size + DT_Entry_Size + Append_To (DT_Constr_List, New_Node); + Append_To (DT_Aggr_List, New_Copy (New_Node)); - elsif Nb_Prim = 0 then - Size_Expr_Node := - Make_Op_Add (Loc, - Left_Opnd => - New_Reference_To (RTE (RE_DT_Prologue_Size), Loc), - Right_Opnd => - New_Reference_To (RTE (RE_DT_Entry_Size), Loc)); + -- Signature - -- Common case. The dispatch table has space to save the pointers to - -- all the predefined primitives, the C++ ABI header of the DT, and - -- the pointers to the primitives of Typ. That is, + if RTE_Record_Component_Available (RE_Signature) then + Append_To (DT_Aggr_List, + New_Reference_To (RTE (RE_Secondary_DT), Loc)); + end if; - -- Size_Expr := DT_Prologue_Size + nb_prim * DT_Entry_Size + -- Tag_Kind - else - Size_Expr_Node := - Make_Op_Add (Loc, - Left_Opnd => - New_Reference_To (RTE (RE_DT_Prologue_Size), Loc), - Right_Opnd => - Make_Op_Multiply (Loc, - Left_Opnd => - New_Reference_To (RTE (RE_DT_Entry_Size), Loc), - Right_Opnd => - Make_Integer_Literal (Loc, Nb_Prim))); - end if; + if RTE_Record_Component_Available (RE_Tag_Kind) then + Append_To (DT_Aggr_List, Tagged_Kind (Typ)); + end if; - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => DT, - Aliased_Present => True, - Object_Definition => - Make_Subtype_Indication (Loc, - Subtype_Mark => New_Reference_To - (RTE (RE_Storage_Array), Loc), - Constraint => Make_Index_Or_Discriminant_Constraint (Loc, - Constraints => New_List ( - Make_Range (Loc, - Low_Bound => Make_Integer_Literal (Loc, 1), - High_Bound => Size_Expr_Node)))))); + -- Predef_Prims - Append_To (Result, - Make_Attribute_Definition_Clause (Loc, - Name => New_Reference_To (DT, Loc), - Chars => Name_Alignment, - Expression => - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc), - Attribute_Name => Name_Alignment))); + Append_To (DT_Aggr_List, + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Predef_Prims, Loc), + Attribute_Name => Name_Address)); - -- Generate code to create the pointer to the dispatch table + -- Note: The correct value of Offset_To_Top will be set by the init + -- subprogram - -- DT_Ptr : Tag := Tag!(DT'Address); + Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0)); - -- According to the C++ ABI, the base of the vtable is located after a - -- prologue containing Offset_To_Top, and Typeinfo_Ptr. Hence, we move - -- down the pointer to the real base of the vtable + -- Generate the Object Specific Data table required to dispatch calls + -- through synchronized interfaces. - if not Has_Dispatch_Table then - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => DT_Ptr, - Constant_Present => True, - Object_Definition => New_Reference_To (Generalized_Tag, Loc), - Expression => - Unchecked_Convert_To (Generalized_Tag, - Make_Op_Add (Loc, - Left_Opnd => - Unchecked_Convert_To (RTE (RE_Storage_Offset), - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (DT, Loc), - Attribute_Name => Name_Address)), - Right_Opnd => - New_Reference_To (RTE (RE_DT_Typeinfo_Ptr_Size), Loc))))); + if Empty_DT + or else Is_Abstract_Type (Typ) + or else Is_Controlled (Typ) + or else Restriction_Active (No_Dispatching_Calls) + or else not Is_Limited_Type (Typ) + or else not Has_Abstract_Interfaces (Typ) + then + -- No OSD table required - else - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => DT_Ptr, - Constant_Present => True, - Object_Definition => New_Reference_To (Generalized_Tag, Loc), - Expression => - Unchecked_Convert_To (Generalized_Tag, - Make_Op_Add (Loc, - Left_Opnd => - Unchecked_Convert_To (RTE (RE_Storage_Offset), - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (DT, Loc), - Attribute_Name => Name_Address)), - Right_Opnd => - New_Reference_To (RTE (RE_DT_Prologue_Size), Loc))))); - end if; + Append_To (DT_Aggr_List, + New_Reference_To (RTE (RE_Null_Address), Loc)); - -- Save the tag in the Access_Disp_Table attribute + else + OSD_Aggr_List := New_List; - if No (Access_Disp_Table (Typ)) then - Set_Access_Disp_Table (Typ, New_Elmt_List); - end if; + declare + Prim_Table : array (Nat range 1 .. Nb_Prim) of Entity_Id; + Prim : Entity_Id; + Prim_Alias : Entity_Id; + Prim_Elmt : Elmt_Id; + E : Entity_Id; + Count : Nat := 0; + Pos : Nat; - Prepend_Elmt (DT_Ptr, Access_Disp_Table (Typ)); + begin + Prim_Table := (others => Empty); + Prim_Alias := Empty; - -- Generate code to define the boolean that controls registration, in - -- order to avoid multiple registrations for tagged types defined in - -- multiple-called scopes. + Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); + while Present (Prim_Elmt) loop + Prim := Node (Prim_Elmt); - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => No_Reg, - Object_Definition => New_Reference_To (Standard_Boolean, Loc), - Expression => New_Reference_To (Standard_True, Loc))); + if Present (Abstract_Interface_Alias (Prim)) + and then Find_Dispatching_Type + (Abstract_Interface_Alias (Prim)) = Iface + then + Prim_Alias := Abstract_Interface_Alias (Prim); - -- Generate: - -- Set_Signature (DT_Ptr, Value); + E := Prim; + while Present (Alias (E)) loop + E := Alias (E); + end loop; - if Has_Dispatch_Table - and then RTE_Available (RE_Set_Signature) - then - if Is_Interface (Typ) then - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_Signature, - Args => New_List ( - New_Reference_To (DT_Ptr, Loc), - New_Reference_To (RTE (RE_Abstract_Interface), Loc)))); + Pos := UI_To_Int (DT_Position (Prim_Alias)); - else - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_Signature, - Args => New_List ( - New_Reference_To (DT_Ptr, Loc), - New_Reference_To (RTE (RE_Primary_DT), Loc)))); - end if; - end if; + if Present (Prim_Table (Pos)) then + pragma Assert (Prim_Table (Pos) = E); + null; - -- Generate: Exname : constant String := full_qualified_name (typ); + else + Prim_Table (Pos) := E; + + Append_To (OSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + Make_Integer_Literal (Loc, + DT_Position (Prim_Alias))), + Expression => + Make_Integer_Literal (Loc, + DT_Position (Alias (Prim))))); + + Count := Count + 1; + end if; + end if; + + Next_Elmt (Prim_Elmt); + end loop; + pragma Assert (Count = Nb_Prim); + end; + + OSD := Make_Defining_Identifier (Loc, New_Internal_Name ('I')); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => OSD, + Object_Definition => + Make_Subtype_Indication (Loc, + Subtype_Mark => + New_Reference_To (RTE (RE_Object_Specific_Data), Loc), + Constraint => + Make_Index_Or_Discriminant_Constraint (Loc, + Constraints => New_List ( + Make_Integer_Literal (Loc, Nb_Prim)))), + Expression => Make_Aggregate (Loc, + Component_Associations => New_List ( + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_OSD_Num_Prims), Loc)), + Expression => + Make_Integer_Literal (Loc, Nb_Prim)), + + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_OSD_Table), Loc)), + Expression => Make_Aggregate (Loc, + Component_Associations => OSD_Aggr_List)))))); + + -- In secondary dispatch tables the Typeinfo component contains + -- the address of the Object Specific Data (see a-tags.ads) + + Append_To (DT_Aggr_List, + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (OSD, Loc), + Attribute_Name => Name_Address)); + end if; + + -- Initialize the table of primitive operations + + Prim_Ops_Aggr_List := New_List; + + if Empty_DT then + Append_To (Prim_Ops_Aggr_List, + New_Reference_To (RTE (RE_Null_Address), Loc)); + + elsif Is_Abstract_Type (Typ) + or else not Static_Dispatch_Tables + then + for J in 1 .. Nb_Prim loop + Append_To (Prim_Ops_Aggr_List, + New_Reference_To (RTE (RE_Null_Address), Loc)); + end loop; + + else + declare + Prim_Table : array (Nat range 1 .. Nb_Prim) of Entity_Id; + Pos : Nat; + Thunk_Code : Node_Id; + Thunk_Id : Entity_Id; + + begin + Prim_Table := (others => Empty); + + Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); + while Present (Prim_Elmt) loop + Prim := Node (Prim_Elmt); + + if not Is_Predefined_Dispatching_Operation (Prim) + and then Present (Abstract_Interface_Alias (Prim)) + and then not Is_Abstract_Subprogram (Alias (Prim)) + and then not Is_Imported (Alias (Prim)) + and then Find_Dispatching_Type + (Abstract_Interface_Alias (Prim)) = Iface + + -- Generate the code of the thunk only if the abstract + -- interface type is not an immediate ancestor of + -- Tagged_Type; otherwise the DT associated with the + -- interface is the primary DT. + + and then not Is_Parent (Iface, Typ) + then + Expand_Interface_Thunk + (N => Prim, + Thunk_Alias => Alias (Prim), + Thunk_Id => Thunk_Id, + Thunk_Code => Thunk_Code); + + if Present (Thunk_Id) then + Pos := + UI_To_Int + (DT_Position (Abstract_Interface_Alias (Prim))); + + Prim_Table (Pos) := Thunk_Id; + Append_To (Result, Thunk_Code); + end if; + end if; + + Next_Elmt (Prim_Elmt); + end loop; + + for J in Prim_Table'Range loop + if Present (Prim_Table (J)) then + New_Node := + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Prim_Table (J), Loc), + Attribute_Name => Name_Address); + else + New_Node := + New_Reference_To (RTE (RE_Null_Address), Loc); + end if; + + Append_To (Prim_Ops_Aggr_List, New_Node); + end loop; + end; + end if; + + Append_To (DT_Aggr_List, + Make_Aggregate (Loc, + Expressions => Prim_Ops_Aggr_List)); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => Iface_DT, + Aliased_Present => True, + Object_Definition => + Make_Subtype_Indication (Loc, + Subtype_Mark => New_Reference_To + (RTE (RE_Dispatch_Table_Wrapper), Loc), + Constraint => Make_Index_Or_Discriminant_Constraint (Loc, + Constraints => DT_Constr_List)), + + Expression => Make_Aggregate (Loc, + Expressions => DT_Aggr_List))); + + -- Generate code to create the pointer to the dispatch table + + -- Iface_DT_Ptr : Tag := Tag!(DT'Address); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => Iface_DT_Ptr, + Constant_Present => True, + Object_Definition => + New_Reference_To (RTE (RE_Interface_Tag), Loc), + Expression => + Unchecked_Convert_To (Generalized_Tag, + Make_Attribute_Reference (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => New_Reference_To (Iface_DT, Loc), + Selector_Name => + New_Occurrence_Of + (RTE_Record_Component (RE_Prims_Ptr), Loc)), + Attribute_Name => Name_Address)))); + + end Make_Secondary_DT; + + -- Local variables + + -- Seems a huge list, shouldn't some of these be commented??? + -- Seems like we are counting too much on guessing from names here??? + + Elab_Code : constant List_Id := New_List; + Generalized_Tag : constant Entity_Id := RTE (RE_Tag); + Result : constant List_Id := New_List; + Tname : constant Name_Id := Chars (Typ); + Name_DT : constant Name_Id := New_External_Name (Tname, 'T'); + Name_Exname : constant Name_Id := New_External_Name (Tname, 'E'); + Name_Predef_Prims : constant Name_Id := New_External_Name (Tname, 'R'); + Name_SSD : constant Name_Id := New_External_Name (Tname, 'S'); + Name_TSD : constant Name_Id := New_External_Name (Tname, 'B'); + DT : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_DT); + Exname : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_Exname); + Predef_Prims : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_Predef_Prims); + SSD : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_SSD); + TSD : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_TSD); + AI : Elmt_Id; + AI_Tag_Comp : Elmt_Id; + AI_Ptr_Elmt : Elmt_Id; + DT_Constr_List : List_Id; + DT_Aggr_List : List_Id; + DT_Ptr : Entity_Id; + Has_Dispatch_Table : Boolean := True; + ITable : Node_Id; + I_Depth : Nat := 0; + Iface_Table_Node : Node_Id; + Name_ITable : Name_Id; + Name_No_Reg : Name_Id; + Nb_Predef_Prims : Nat := 0; + Nb_Prim : Nat := 0; + New_Node : Node_Id; + No_Reg : Node_Id; + Null_Parent_Tag : Boolean := False; + Num_Ifaces : Nat := 0; + Old_Tag1 : Node_Id; + Old_Tag2 : Node_Id; + Prim : Entity_Id; + Prim_Elmt : Elmt_Id; + Prim_Ops_Aggr_List : List_Id; + Transportable : Entity_Id; + RC_Offset_Node : Node_Id; + Suffix_Index : Int; + Typ_Comps : Elist_Id; + Typ_Ifaces : Elist_Id; + TSD_Aggr_List : List_Id; + TSD_Tags_List : List_Id; + TSD_Ifaces_List : List_Id; + + -- Start of processing for Make_DT + + begin + -- Fill the contents of Access_Disp_Table + + -- 1) Generate the primary and secondary tag entities + + declare + DT_Ptr : Node_Id; + Name_DT_Ptr : Name_Id; + Typ_Name : Name_Id; + Iface_DT_Ptr : Node_Id; + Suffix_Index : Int; + AI_Tag_Comp : Elmt_Id; + + begin + -- Collect the components associated with secondary dispatch tables + + if Has_Abstract_Interfaces (Typ) then + Collect_Interface_Components (Typ, Typ_Comps); + end if; + + -- Generate the primary tag entity + + Name_DT_Ptr := New_External_Name (Tname, 'P'); + DT_Ptr := Make_Defining_Identifier (Loc, Name_DT_Ptr); + Set_Ekind (DT_Ptr, E_Constant); + Set_Is_Statically_Allocated (DT_Ptr); + Set_Is_True_Constant (DT_Ptr); + + pragma Assert (No (Access_Disp_Table (Typ))); + Set_Access_Disp_Table (Typ, New_Elmt_List); + Append_Elmt (DT_Ptr, Access_Disp_Table (Typ)); + + -- Generate the secondary tag entities + + if Has_Abstract_Interfaces (Typ) then + Suffix_Index := 0; + + -- For each interface type we build an unique external name + -- associated with its corresponding secondary dispatch table. + -- This external name will be used to declare an object that + -- references this secondary dispatch table, value that will be + -- used for the elaboration of Typ's objects and also for the + -- elaboration of objects of derivations of Typ that do not + -- override the primitive operation of this interface type. + + AI_Tag_Comp := First_Elmt (Typ_Comps); + while Present (AI_Tag_Comp) loop + Get_Secondary_DT_External_Name + (Typ, Related_Interface (Node (AI_Tag_Comp)), Suffix_Index); + + Typ_Name := Name_Find; + Name_DT_Ptr := New_External_Name (Typ_Name, "P"); + Iface_DT_Ptr := Make_Defining_Identifier (Loc, Name_DT_Ptr); + + Set_Ekind (Iface_DT_Ptr, E_Constant); + Set_Is_Statically_Allocated (Iface_DT_Ptr); + Set_Is_True_Constant (Iface_DT_Ptr); + Append_Elmt (Iface_DT_Ptr, Access_Disp_Table (Typ)); + + Next_Elmt (AI_Tag_Comp); + end loop; + end if; + end; + + -- 2) At the end of Access_Disp_Table we add the entity of an access + -- type declaration. It is used by Build_Get_Prim_Op_Address to + -- expand dispatching calls through the primary dispatch table. + + -- Generate: + -- type Typ_DT is array (1 .. Nb_Prims) of Address; + -- type Typ_DT_Acc is access Typ_DT; + + declare + Name_DT_Prims : constant Name_Id := + New_External_Name (Tname, 'G'); + Name_DT_Prims_Acc : constant Name_Id := + New_External_Name (Tname, 'H'); + DT_Prims : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_DT_Prims); + DT_Prims_Acc : constant Entity_Id := + Make_Defining_Identifier (Loc, + Name_DT_Prims_Acc); + begin + Append_To (Result, + Make_Full_Type_Declaration (Loc, + Defining_Identifier => DT_Prims, + Type_Definition => + Make_Constrained_Array_Definition (Loc, + Discrete_Subtype_Definitions => New_List ( + Make_Range (Loc, + Low_Bound => Make_Integer_Literal (Loc, 1), + High_Bound => Make_Integer_Literal (Loc, + DT_Entry_Count + (First_Tag_Component (Typ))))), + Component_Definition => + Make_Component_Definition (Loc, + Subtype_Indication => + New_Reference_To (RTE (RE_Address), Loc))))); + + Append_To (Result, + Make_Full_Type_Declaration (Loc, + Defining_Identifier => DT_Prims_Acc, + Type_Definition => + Make_Access_To_Object_Definition (Loc, + Subtype_Indication => + New_Occurrence_Of (DT_Prims, Loc)))); + + Append_Elmt (DT_Prims_Acc, Access_Disp_Table (Typ)); + end; + + if Is_CPP_Class (Typ) then + return Result; + end if; + + if No_Run_Time_Mode or else not RTE_Available (RE_Tag) then + DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT_Ptr, + Object_Definition => New_Reference_To (RTE (RE_Tag), Loc), + Constant_Present => True, + Expression => + Unchecked_Convert_To (Generalized_Tag, + New_Reference_To (RTE (RE_Null_Address), Loc)))); + + Analyze_List (Result, Suppress => All_Checks); + Error_Msg_CRT ("tagged types", Typ); + return Result; + end if; + + if not Static_Dispatch_Tables + or else Is_Local_DT + then + Set_Ekind (DT, E_Variable); + Set_Is_Statically_Allocated (DT); + else + Set_Ekind (DT, E_Constant); + Set_Is_Statically_Allocated (DT); + Set_Is_True_Constant (DT); + end if; + + pragma Assert (Present (Access_Disp_Table (Typ))); + DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); + + -- Ada 2005 (AI-251): Build the secondary dispatch tables + + if Has_Abstract_Interfaces (Typ) then + Suffix_Index := 0; + AI_Ptr_Elmt := Next_Elmt (First_Elmt (Access_Disp_Table (Typ))); + + AI_Tag_Comp := First_Elmt (Typ_Comps); + while Present (AI_Tag_Comp) loop + Make_Secondary_DT + (Typ => Typ, + Iface => Base_Type + (Related_Interface (Node (AI_Tag_Comp))), + AI_Tag => Node (AI_Tag_Comp), + Iface_DT_Ptr => Node (AI_Ptr_Elmt), + Result => Result); + + Suffix_Index := Suffix_Index + 1; + Next_Elmt (AI_Ptr_Elmt); + Next_Elmt (AI_Tag_Comp); + end loop; + end if; + + -- Evaluate if we generate the dispatch table + + Has_Dispatch_Table := + not Is_Interface (Typ) + and then not Restriction_Active (No_Dispatching_Calls); + + -- Calculate the number of primitives of the dispatch table and the + -- size of the Type_Specific_Data record. + + if Has_Dispatch_Table then + Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ))); + end if; + + if not Static_Dispatch_Tables then + Set_Ekind (Predef_Prims, E_Variable); + Set_Is_Statically_Allocated (Predef_Prims); + else + Set_Ekind (Predef_Prims, E_Constant); + Set_Is_Statically_Allocated (Predef_Prims); + Set_Is_True_Constant (Predef_Prims); + end if; + + Set_Ekind (SSD, E_Constant); + Set_Is_Statically_Allocated (SSD); + Set_Is_True_Constant (SSD); + + Set_Ekind (TSD, E_Constant); + Set_Is_Statically_Allocated (TSD); + Set_Is_True_Constant (TSD); + + Set_Ekind (Exname, E_Constant); + Set_Is_Statically_Allocated (Exname); + Set_Is_True_Constant (Exname); + + -- Generate code to define the boolean that controls registration, in + -- order to avoid multiple registrations for tagged types defined in + -- multiple-called scopes. + + if not Is_Interface (Typ) then + Name_No_Reg := New_External_Name (Tname, 'F'); + No_Reg := Make_Defining_Identifier (Loc, Name_No_Reg); + + Set_Ekind (No_Reg, E_Variable); + Set_Is_Statically_Allocated (No_Reg); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => No_Reg, + Object_Definition => New_Reference_To (Standard_Boolean, Loc), + Expression => New_Reference_To (Standard_True, Loc))); + end if; + + -- In case of locally defined tagged type we declare the object + -- contanining the dispatch table by means of a variable. Its + -- initialization is done later by means of an assignment. This is + -- required to generate its External_Tag. + + if Is_Local_DT then + + -- Generate: + -- DT : No_Dispatch_Table_Wrapper; + -- DT_Ptr : Tag := !Tag (DT.NDT_Prims_Ptr'Address); + + if not Has_Dispatch_Table then + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT, + Aliased_Present => True, + Constant_Present => False, + Object_Definition => + New_Reference_To + (RTE (RE_No_Dispatch_Table_Wrapper), Loc))); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT_Ptr, + Object_Definition => New_Reference_To (RTE (RE_Tag), Loc), + Constant_Present => True, + Expression => + Unchecked_Convert_To (Generalized_Tag, + Make_Attribute_Reference (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => New_Reference_To (DT, Loc), + Selector_Name => + New_Occurrence_Of + (RTE_Record_Component (RE_NDT_Prims_Ptr), Loc)), + Attribute_Name => Name_Address)))); + + -- Generate: + -- DT : Dispatch_Table_Wrapper (Nb_Prim); + -- for DT'Alignment use Address'Alignment; + -- DT_Ptr : Tag := !Tag (DT.Prims_Ptr'Address); + + else + -- If the tagged type has no primitives we add a dummy slot + -- whose address will be the tag of this type. + + if Nb_Prim = 0 then + DT_Constr_List := + New_List (Make_Integer_Literal (Loc, 1)); + else + DT_Constr_List := + New_List (Make_Integer_Literal (Loc, Nb_Prim)); + end if; + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT, + Aliased_Present => True, + Constant_Present => False, + Object_Definition => + Make_Subtype_Indication (Loc, + Subtype_Mark => + New_Reference_To (RTE (RE_Dispatch_Table_Wrapper), Loc), + Constraint => Make_Index_Or_Discriminant_Constraint (Loc, + Constraints => DT_Constr_List)))); + + Append_To (Result, + Make_Attribute_Definition_Clause (Loc, + Name => New_Reference_To (DT, Loc), + Chars => Name_Alignment, + Expression => + Make_Attribute_Reference (Loc, + Prefix => + New_Reference_To (RTE (RE_Integer_Address), Loc), + Attribute_Name => Name_Alignment))); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT_Ptr, + Object_Definition => New_Reference_To (RTE (RE_Tag), Loc), + Constant_Present => True, + Expression => + Unchecked_Convert_To (Generalized_Tag, + Make_Attribute_Reference (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => New_Reference_To (DT, Loc), + Selector_Name => + New_Occurrence_Of + (RTE_Record_Component (RE_Prims_Ptr), Loc)), + Attribute_Name => Name_Address)))); + end if; + end if; + + -- Generate: Exname : constant String := full_qualified_name (typ); -- The type itself may be an anonymous parent type, so use the first -- subtype to have a user-recognizable name. @@ -2806,21 +3140,332 @@ package body Exp_Disp is Make_String_Literal (Loc, Full_Qualified_Name (First_Subtype (Typ))))); - -- Calculate the value of the RC_Offset component. These are the - -- valid valiues and their meaning: + -- Generate code to create the storage for the type specific data object + -- with enough space to store the tags of the ancestors plus the tags + -- of all the implemented interfaces (as described in a-tags.adb). + + -- TSD : Type_Specific_Data (I_Depth) := + -- (Idepth => I_Depth, + -- Access_Level => Type_Access_Level (Typ), + -- Expanded_Name => Cstring_Ptr!(Exname'Address)) + -- External_Tag => Cstring_Ptr!(Exname'Address)) + -- HT_Link => null, + -- Transportable => <>, + -- RC_Offset => <>, + -- [ Interfaces_Table => <> ] + -- [ SSD => SSD_Table'Address ] + -- Tags_Table => (0 => null, + -- 1 => Parent'Tag + -- ...); + -- for TSD'Alignment use Address'Alignment + + TSD_Aggr_List := New_List; + + -- Idepth: Count ancestors to compute the inheritance depth. For private + -- extensions, always go to the full view in order to compute the real + -- inheritance depth. + + declare + Current_Typ : Entity_Id; + Parent_Typ : Entity_Id; + + begin + I_Depth := 0; + Current_Typ := Typ; + loop + Parent_Typ := Etype (Current_Typ); + + if Is_Private_Type (Parent_Typ) then + Parent_Typ := Full_View (Base_Type (Parent_Typ)); + end if; + + exit when Parent_Typ = Current_Typ; + + I_Depth := I_Depth + 1; + Current_Typ := Parent_Typ; + end loop; + end; + + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of (RTE_Record_Component (RE_Idepth), Loc)), + Expression => + Make_Integer_Literal (Loc, I_Depth))); + + -- Access_Level + + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of (RTE_Record_Component (RE_Access_Level), Loc)), + Expression => + Make_Integer_Literal (Loc, Type_Access_Level (Typ)))); + + -- Expanded_Name + + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of (RTE_Record_Component (RE_Expanded_Name), Loc)), + Expression => + Unchecked_Convert_To (RTE (RE_Cstring_Ptr), + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Exname, Loc), + Attribute_Name => Name_Address)))); + + -- External_Tag of a local tagged type + + -- Exname : constant String := + -- "Internal tag at 16#tag-addr#: "; + + -- The reason we generate this strange name is that we do not want to + -- enter local tagged types in the global hash table used to compute + -- the Internal_Tag attribute for two reasons: + + -- 1. It is hard to avoid a tasking race condition for entering the + -- entry into the hash table. + + -- 2. It would cause a storage leak, unless we rig up considerable + -- mechanism to remove the entry from the hash table on exit. + + -- So what we do is to generate the above external tag name, where the + -- hex address is the address of the local dispatch table (i.e. exactly + -- the value we want if Internal_Tag is computed from this string). + + -- Of course this value will only be valid if the tagged type is still + -- in scope, but it clearly must be erroneous to compute the internal + -- tag of a tagged type that is out of scope! + + if Is_Local_DT then + declare + Name_Exname : constant Name_Id := New_External_Name (Tname, 'L'); + Name_Str1 : constant Name_Id := New_Internal_Name ('I'); + Name_Str2 : constant Name_Id := New_Internal_Name ('I'); + Name_Str3 : constant Name_Id := New_Internal_Name ('I'); + Exname : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_Exname); + Str1 : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_Str1); + Str2 : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_Str2); + Str3 : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_Str3); + Full_Name : constant String_Id := + Full_Qualified_Name (First_Subtype (Typ)); + Str1_Id : String_Id; + Str2_Id : String_Id; + Str3_Id : String_Id; + + begin + -- Generate: + -- Str1 : constant String := "Internal tag at 16#"; + + Set_Ekind (Str1, E_Constant); + Set_Is_Statically_Allocated (Str1); + Set_Is_True_Constant (Str1); + + Start_String; + Store_String_Chars ("Internal tag at 16#"); + Str1_Id := End_String; + + -- Generate: + -- Str2 : constant String := "#: "; + + Set_Ekind (Str2, E_Constant); + Set_Is_Statically_Allocated (Str2); + Set_Is_True_Constant (Str2); + + Start_String; + Store_String_Chars ("#: "); + Str2_Id := End_String; + + -- Generate: + -- Str3 : constant String := ; + + Set_Ekind (Str3, E_Constant); + Set_Is_Statically_Allocated (Str3); + Set_Is_True_Constant (Str3); + + Start_String; + Store_String_Chars (Full_Name); + Str3_Id := End_String; + + -- Generate: + -- Exname : constant String := + -- Str1 & Address_Image (Tag) & Str2 & Str3; + + if RTE_Available (RE_Address_Image) then + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => Exname, + Constant_Present => True, + Object_Definition => New_Reference_To + (Standard_String, Loc), + Expression => + Make_Op_Concat (Loc, + Left_Opnd => + Make_String_Literal (Loc, Str1_Id), + Right_Opnd => + Make_Op_Concat (Loc, + Left_Opnd => + Make_Function_Call (Loc, + Name => + New_Reference_To + (RTE (RE_Address_Image), Loc), + Parameter_Associations => New_List ( + Unchecked_Convert_To (RTE (RE_Address), + New_Reference_To (DT_Ptr, Loc)))), + Right_Opnd => + Make_Op_Concat (Loc, + Left_Opnd => + Make_String_Literal (Loc, Str2_Id), + Right_Opnd => + Make_String_Literal (Loc, Str3_Id)))))); + else + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => Exname, + Constant_Present => True, + Object_Definition => New_Reference_To + (Standard_String, Loc), + Expression => + Make_Op_Concat (Loc, + Left_Opnd => + Make_String_Literal (Loc, Str1_Id), + Right_Opnd => + Make_Op_Concat (Loc, + Left_Opnd => + Make_String_Literal (Loc, Str2_Id), + Right_Opnd => + Make_String_Literal (Loc, Str3_Id))))); + end if; + + New_Node := + Unchecked_Convert_To (RTE (RE_Cstring_Ptr), + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Exname, Loc), + Attribute_Name => Name_Address)); + end; + + -- External tag of a library-level tagged type: Check for a definition + -- of External_Tag. The clause is considered only if it applies to this + -- specific tagged type, as opposed to one of its ancestors. + + else + declare + Def : constant Node_Id := Get_Attribute_Definition_Clause (Typ, + Attribute_External_Tag); + Old_Val : String_Id; + New_Val : String_Id; + E : Entity_Id; + + begin + if not Present (Def) + or else Entity (Name (Def)) /= Typ + then + New_Node := + Unchecked_Convert_To (RTE (RE_Cstring_Ptr), + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Exname, Loc), + Attribute_Name => Name_Address)); + else + Old_Val := Strval (Expr_Value_S (Expression (Def))); + + -- For the rep clause "for x'external_tag use y" generate: + + -- xV : constant string := y; + -- Set_External_Tag (x'tag, xV'Address); + -- Register_Tag (x'tag); + + -- Create a new nul terminated string if it is not already + + if String_Length (Old_Val) > 0 + and then + Get_String_Char (Old_Val, String_Length (Old_Val)) = 0 + then + New_Val := Old_Val; + else + Start_String (Old_Val); + Store_String_Char (Get_Char_Code (ASCII.NUL)); + New_Val := End_String; + end if; + + E := Make_Defining_Identifier (Loc, + New_External_Name (Chars (Typ), 'A')); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => E, + Constant_Present => True, + Object_Definition => + New_Reference_To (Standard_String, Loc), + Expression => + Make_String_Literal (Loc, New_Val))); + + New_Node := + Unchecked_Convert_To (RTE (RE_Cstring_Ptr), + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (E, Loc), + Attribute_Name => Name_Address)); + end if; + end; + end if; + + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_External_Tag), Loc)), + Expression => New_Node)); + + -- HT_Link + + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_HT_Link), Loc)), + Expression => + Unchecked_Convert_To (RTE (RE_Tag), + New_Reference_To (RTE (RE_Null_Address), Loc)))); + + -- Transportable: Set for types that can be used in remote calls + -- with respect to E.4(18) legality rules. + + Transportable := + Boolean_Literals + (Is_Pure (Typ) + or else Is_Shared_Passive (Typ) + or else + ((Is_Remote_Types (Typ) + or else Is_Remote_Call_Interface (Typ)) + and then Original_View_In_Visible_Part (Typ)) + or else not Comes_From_Source (Typ)); + + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_Transportable), Loc)), + Expression => New_Occurrence_Of (Transportable, Loc))); + + -- RC_Offset: These are the valid values and their meaning: + -- >0: For simple types with controlled components is -- type._record_controller'position + -- 0: For types with no controlled components + -- -1: For complex types with controlled components where the position -- of the record controller is not statically computable but there -- are controlled components at this level. The _Controller field -- is available right after the _parent. + -- -2: There are no controlled components at this level. We need to -- get the position from the parent. - if Is_Interface (Typ) - or else not Has_Controlled_Component (Typ) - then + if not Has_Controlled_Component (Typ) then RC_Offset_Node := Make_Integer_Literal (Loc, 0); elsif Etype (Typ) /= Typ @@ -2856,131 +3501,259 @@ package body Exp_Disp is Set_Etype (RC_Offset_Node, RTE (RE_Storage_Offset)); end if; - -- Set the pointer to the Interfaces_Table (if any). Otherwise the - -- corresponding access component is set to null. The table of - -- interfaces is required for AI-405 + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of (RTE_Record_Component (RE_RC_Offset), Loc)), + Expression => RC_Offset_Node)); + + -- Interfaces_Table (required for AI-405) + + if RTE_Record_Component_Available (RE_Interfaces_Table) then + + -- Count the number of interface types implemented by Typ + + Collect_Abstract_Interfaces (Typ, Typ_Ifaces); + + AI := First_Elmt (Typ_Ifaces); + while Present (AI) loop + Num_Ifaces := Num_Ifaces + 1; + Next_Elmt (AI); + end loop; - if RTE_Record_Component_Available (RE_Ifaces_Table_Ptr) then if Num_Ifaces = 0 then - Iface_Table_Node := - New_Reference_To (RTE (RE_Null_Address), Loc); + Iface_Table_Node := Make_Null (Loc); - -- Generate the Interface_Table object. + -- Generate the Interface_Table object else + TSD_Ifaces_List := New_List; + + declare + Pos : Nat := 1; + Aggr_List : List_Id; + + begin + AI := First_Elmt (Typ_Ifaces); + while Present (AI) loop + Aggr_List := New_List ( + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_Iface_Tag), Loc)), + Expression => + Unchecked_Convert_To (Generalized_Tag, + New_Reference_To + (Node (First_Elmt (Access_Disp_Table (Node (AI)))), + Loc))), + + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_Static_Offset_To_Top), + Loc)), + Expression => + New_Reference_To (Standard_True, Loc)), + + Make_Component_Association (Loc, + Choices => New_List (Make_Others_Choice (Loc)), + Expression => Empty, + Box_Present => True)); + + Append_To (TSD_Ifaces_List, + Make_Component_Association (Loc, + Choices => New_List ( + Make_Integer_Literal (Loc, Pos)), + Expression => Make_Aggregate (Loc, + Component_Associations => Aggr_List))); + + Pos := Pos + 1; + Next_Elmt (AI); + end loop; + end; + + Name_ITable := New_External_Name (Tname, 'I'); + ITable := Make_Defining_Identifier (Loc, Name_ITable); + + Set_Ekind (ITable, E_Constant); + Set_Is_Statically_Allocated (ITable); + Set_Is_True_Constant (ITable); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => ITable, + Aliased_Present => True, + Object_Definition => + Make_Subtype_Indication (Loc, + Subtype_Mark => + New_Reference_To (RTE (RE_Interface_Data), Loc), + Constraint => Make_Index_Or_Discriminant_Constraint (Loc, + Constraints => New_List ( + Make_Integer_Literal (Loc, Num_Ifaces)))), + + Expression => Make_Aggregate (Loc, + Component_Associations => New_List ( + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_Nb_Ifaces), Loc)), + Expression => + Make_Integer_Literal (Loc, Num_Ifaces)), + + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_Ifaces_Table), Loc)), + Expression => Make_Aggregate (Loc, + Component_Associations => TSD_Ifaces_List)))))); + + Iface_Table_Node := + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (ITable, Loc), + Attribute_Name => Name_Unchecked_Access); + end if; + + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_Interfaces_Table), Loc)), + Expression => Iface_Table_Node)); + end if; + + -- Generate the Select Specific Data table for synchronized types that + -- implement synchronized interfaces. The size of the table is + -- constrained by the number of non-predefined primitive operations. + + if RTE_Record_Component_Available (RE_SSD) then + if Ada_Version >= Ada_05 + and then Has_Dispatch_Table + and then Is_Concurrent_Record_Type (Typ) + and then Has_Abstract_Interfaces (Typ) + and then Nb_Prim > 0 + and then not Is_Abstract_Type (Typ) + and then not Is_Controlled (Typ) + and then not Restriction_Active (No_Dispatching_Calls) + then Append_To (Result, Make_Object_Declaration (Loc, - Defining_Identifier => ITable, + Defining_Identifier => SSD, Aliased_Present => True, Object_Definition => Make_Subtype_Indication (Loc, - Subtype_Mark => New_Reference_To - (RTE (RE_Interface_Data), Loc), - Constraint => Make_Index_Or_Discriminant_Constraint (Loc, - Constraints => New_List ( - Make_Integer_Literal (Loc, - Num_Ifaces)))))); - - Iface_Table_Node := - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (ITable, Loc), - Attribute_Name => Name_Address); + Subtype_Mark => New_Reference_To ( + RTE (RE_Select_Specific_Data), Loc), + Constraint => + Make_Index_Or_Discriminant_Constraint (Loc, + Constraints => New_List ( + Make_Integer_Literal (Loc, Nb_Prim)))))); + + -- This table is initialized by Make_Select_Specific_Data_Table, + -- which calls Set_Entry_Index and Set_Prim_Op_Kind. + + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_SSD), Loc)), + Expression => + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (SSD, Loc), + Attribute_Name => Name_Unchecked_Access))); + else + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List ( + New_Occurrence_Of + (RTE_Record_Component (RE_SSD), Loc)), + Expression => Make_Null (Loc))); end if; end if; - -- Generate: Set_Remotely_Callable (DT_Ptr, Status); where Status is - -- described in E.4 (18) + -- Initialize the table of ancestor tags. In case of interface types + -- this table is not needed. - Remotely_Callable := - Boolean_Literals - (Is_Pure (Typ) - or else Is_Shared_Passive (Typ) - or else - ((Is_Remote_Types (Typ) - or else Is_Remote_Call_Interface (Typ)) - and then Original_View_In_Visible_Part (Typ)) - or else not Comes_From_Source (Typ)); + if Is_Interface (Typ) then + Append_To (TSD_Aggr_List, + Make_Component_Association (Loc, + Choices => New_List (Make_Others_Choice (Loc)), + Expression => Empty, + Box_Present => True)); + else + declare + Current_Typ : Entity_Id; + Parent_Typ : Entity_Id; + Pos : Nat; - -- Generate code to create the storage for the type specific data object - -- with enough space to store the tags of the ancestors plus the tags - -- of all the implemented interfaces (as described in a-tags.adb). + begin + TSD_Tags_List := New_List; - -- TSD : Type_Specific_Data (I_Depth) := - -- (Idepth => I_Depth, - -- Access_Level => Type_Access_Level (Typ), - -- Expanded_Name => Cstring_Ptr!(Exname'Address)) - -- [ External_Tag => Cstring_Ptr!(Exname'Address)) ] - -- RC_Offset => <>, - -- Remotely_Callable => <> - -- [ Ifaces_Table_Ptr => <> ] - -- others => <>); - -- for TSD'Alignment use Address'Alignment + -- Fill position 0 with null because we still have not generated + -- the tag of Typ. - TSD_Aggr_List := New_List ( - Make_Component_Association (Loc, - Choices => New_List ( - New_Occurrence_Of (RTE_Record_Component (RE_Idepth), Loc)), - Expression => Make_Integer_Literal (Loc, I_Depth)), + Append_To (TSD_Tags_List, + Make_Component_Association (Loc, + Choices => New_List ( + Make_Integer_Literal (Loc, 0)), + Expression => + Unchecked_Convert_To (RTE (RE_Tag), + New_Reference_To (RTE (RE_Null_Address), Loc)))); - Make_Component_Association (Loc, - Choices => New_List ( - New_Occurrence_Of (RTE_Record_Component (RE_Access_Level), Loc)), - Expression => Make_Integer_Literal (Loc, Type_Access_Level (Typ))), + -- Fill the rest of the table with the tags of the ancestors - Make_Component_Association (Loc, - Choices => New_List ( - New_Occurrence_Of - (RTE_Record_Component (RE_Expanded_Name), Loc)), - Expression => - Unchecked_Convert_To (RTE (RE_Cstring_Ptr), - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Exname, Loc), - Attribute_Name => Name_Address)))); + Pos := 1; + Current_Typ := Typ; + + loop + Parent_Typ := Etype (Current_Typ); - if not Has_External_Tag_Rep_Clause (Typ) then + if Is_Private_Type (Parent_Typ) then + Parent_Typ := Full_View (Base_Type (Parent_Typ)); + end if; - -- Should be the external name not the qualified name??? + exit when Parent_Typ = Current_Typ; - Append_To (TSD_Aggr_List, - Make_Component_Association (Loc, - Choices => New_List ( - New_Occurrence_Of - (RTE_Record_Component (RE_External_Tag), Loc)), - Expression => - Unchecked_Convert_To (RTE (RE_Cstring_Ptr), - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Exname, Loc), - Attribute_Name => Name_Address)))); - end if; + if Is_CPP_Class (Parent_Typ) then - Append_List_To (TSD_Aggr_List, New_List ( - Make_Component_Association (Loc, - Choices => New_List ( - New_Occurrence_Of (RTE_Record_Component (RE_RC_Offset), Loc)), - Expression => RC_Offset_Node), + -- The tags defined in the C++ side will be inherited when + -- the object is constructed. + -- (see Exp_Ch3.Build_Init_Procedure) - Make_Component_Association (Loc, - Choices => New_List ( - New_Occurrence_Of - (RTE_Record_Component (RE_Remotely_Callable), Loc)), - Expression => New_Occurrence_Of (Remotely_Callable, Loc)))); + Append_To (TSD_Tags_List, + Make_Component_Association (Loc, + Choices => New_List ( + Make_Integer_Literal (Loc, Pos)), + Expression => + Unchecked_Convert_To (RTE (RE_Tag), + New_Reference_To (RTE (RE_Null_Address), Loc)))); + else + Append_To (TSD_Tags_List, + Make_Component_Association (Loc, + Choices => New_List ( + Make_Integer_Literal (Loc, Pos)), + Expression => + New_Reference_To + (Node (First_Elmt (Access_Disp_Table (Parent_Typ))), + Loc))); + end if; + + Pos := Pos + 1; + Current_Typ := Parent_Typ; + end loop; + + pragma Assert (Pos = I_Depth + 1); + end; - if RTE_Record_Component_Available (RE_Ifaces_Table_Ptr) then Append_To (TSD_Aggr_List, Make_Component_Association (Loc, Choices => New_List ( New_Occurrence_Of - (RTE_Record_Component (RE_Ifaces_Table_Ptr), Loc)), - Expression => Iface_Table_Node)); + (RTE_Record_Component (RE_Tags_Table), Loc)), + Expression => Make_Aggregate (Loc, + Component_Associations => TSD_Tags_List))); end if; - Append_To (TSD_Aggr_List, - Make_Component_Association (Loc, - Choices => New_List (Make_Others_Choice (Loc)), - Expression => Empty, - Box_Present => True)); - - -- Save the expanded name in the dispatch table + -- Build the TSD object Append_To (Result, Make_Object_Declaration (Loc, @@ -2994,6 +3767,7 @@ package body Exp_Disp is Make_Index_Or_Discriminant_Constraint (Loc, Constraints => New_List ( Make_Integer_Literal (Loc, I_Depth)))), + Expression => Make_Aggregate (Loc, Component_Associations => TSD_Aggr_List))); @@ -3006,77 +3780,402 @@ package body Exp_Disp is Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc), Attribute_Name => Name_Alignment))); - -- Generate code to put the Address of the TSD in the dispatch table + -- Generate the dummy Dispatch_Table object associated with tagged + -- types that have no dispatch table. - Append_To (Elab_Code, - Build_Set_TSD (Loc, - Tag_Node => New_Reference_To (DT_Ptr, Loc), - Value_Node => - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (TSD, Loc), - Attribute_Name => Name_Address))); + -- DT : No_Dispatch_Table := + -- (NDT_TSD => TSD'Address; + -- NDT_Prims_Ptr => 0); - -- Generate extra code required for synchronized interfaces + if not Has_Dispatch_Table then + DT_Constr_List := New_List; + DT_Aggr_List := New_List; - if RTE_Available (RE_Set_Tagged_Kind) then - if Ada_Version >= Ada_05 - and then not Is_Interface (Typ) - and then not Is_Abstract_Type (Typ) - and then not Is_Controlled (Typ) - and then not Restriction_Active (No_Dispatching_Calls) - then - -- Generate: - -- Set_Type_Kind (T'Tag, Type_Kind (Typ)); + -- Typeinfo - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_Tagged_Kind, - Args => New_List ( - New_Reference_To (DT_Ptr, Loc), -- DTptr - Tagged_Kind (Typ)))); -- Value - - -- Generate the Select Specific Data table for synchronized - -- types that implement a synchronized interface. The size - -- of the table is constrained by the number of non-predefined - -- primitive operations. - - if Has_Dispatch_Table - and then Is_Concurrent_Record_Type (Typ) - and then Has_Abstract_Interfaces (Typ) - then - -- No need to generate this code if Nb_Prim = 0 ??? + New_Node := + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (TSD, Loc), + Attribute_Name => Name_Address); + + Append_To (DT_Constr_List, New_Node); + Append_To (DT_Aggr_List, New_Copy (New_Node)); + Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0)); + + -- In case of locally defined tagged types we have already declared + -- and uninitialized object for the dispatch table, which is now + -- initialized by means of an assignment. + + if Is_Local_DT then + Append_To (Result, + Make_Assignment_Statement (Loc, + Name => New_Reference_To (DT, Loc), + Expression => Make_Aggregate (Loc, + Expressions => DT_Aggr_List))); + + -- In case of library level tagged types we declare now the constant + -- object containing the dispatch table. + + else + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT, + Aliased_Present => True, + Constant_Present => Static_Dispatch_Tables, + Object_Definition => + New_Reference_To (RTE (RE_No_Dispatch_Table_Wrapper), Loc), + Expression => Make_Aggregate (Loc, + Expressions => DT_Aggr_List))); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT_Ptr, + Object_Definition => New_Reference_To (RTE (RE_Tag), Loc), + Constant_Present => True, + Expression => + Unchecked_Convert_To (Generalized_Tag, + Make_Attribute_Reference (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => New_Reference_To (DT, Loc), + Selector_Name => + New_Occurrence_Of + (RTE_Record_Component (RE_NDT_Prims_Ptr), Loc)), + Attribute_Name => Name_Address)))); + end if; + + -- Common case: Typ has a dispatch table + + -- Generate: + + -- Predef_Prims : Address_Array (1 .. Default_Prim_Ops_Count) := + -- (predef-prim-op-1'address, + -- predef-prim-op-2'address, + -- ... + -- predef-prim-op-n'address); + -- for Predef_Prims'Alignment use Address'Alignment + + -- DT : Dispatch_Table (Nb_Prims) := + -- (Signature => , + -- Tag_Kind => , + -- Predef_Prims => Predef_Prims'First'Address, + -- Offset_To_Top => 0, + -- TSD => TSD'Address; + -- Prims_Ptr => (prim-op-1'address, + -- prim-op-2'address, + -- ... + -- prim-op-n'address)); + + else + declare + Pos : Nat; + + begin + if not Static_Dispatch_Tables then + Nb_Predef_Prims := Max_Predef_Prims; + + else + Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); + while Present (Prim_Elmt) loop + Prim := Node (Prim_Elmt); + + if Is_Predefined_Dispatching_Operation (Prim) + and then not Is_Abstract_Subprogram (Prim) + then + Pos := UI_To_Int (DT_Position (Prim)); + + if Pos > Nb_Predef_Prims then + Nb_Predef_Prims := Pos; + end if; + end if; + + Next_Elmt (Prim_Elmt); + end loop; + end if; + + declare + Prim_Table : array + (Nat range 1 .. Nb_Predef_Prims) of Entity_Id; + E : Entity_Id; + + begin + Prim_Ops_Aggr_List := New_List; + + Prim_Table := (others => Empty); + Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); + while Present (Prim_Elmt) loop + Prim := Node (Prim_Elmt); + + if Static_Dispatch_Tables + and then Is_Predefined_Dispatching_Operation (Prim) + and then not Is_Abstract_Subprogram (Prim) + and then not Present (Prim_Table + (UI_To_Int (DT_Position (Prim)))) + then + E := Prim; + while Present (Alias (E)) loop + E := Alias (E); + end loop; + + pragma Assert (not Is_Abstract_Subprogram (E)); + Prim_Table (UI_To_Int (DT_Position (Prim))) := E; + end if; + + Next_Elmt (Prim_Elmt); + end loop; + + for J in Prim_Table'Range loop + if Present (Prim_Table (J)) then + New_Node := + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Prim_Table (J), Loc), + Attribute_Name => Name_Address); + else + New_Node := New_Reference_To (RTE (RE_Null_Address), Loc); + end if; + + Append_To (Prim_Ops_Aggr_List, New_Node); + end loop; Append_To (Result, Make_Object_Declaration (Loc, - Defining_Identifier => SSD, + Defining_Identifier => Predef_Prims, Aliased_Present => True, + Constant_Present => Static_Dispatch_Tables, Object_Definition => - Make_Subtype_Indication (Loc, - Subtype_Mark => New_Reference_To ( - RTE (RE_Select_Specific_Data), Loc), - Constraint => - Make_Index_Or_Discriminant_Constraint (Loc, - Constraints => New_List ( - Make_Integer_Literal (Loc, Nb_Prim)))))); - - -- Set the pointer to the Select Specific Data table in the TSD - - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_SSD, - Args => New_List ( - New_Reference_To (DT_Ptr, Loc), -- DTptr - Make_Attribute_Reference (Loc, -- Value - Prefix => New_Reference_To (SSD, Loc), - Attribute_Name => Name_Address)))); - end if; + New_Reference_To (RTE (RE_Address_Array), Loc), + Expression => Make_Aggregate (Loc, + Expressions => Prim_Ops_Aggr_List))); + + Append_To (Result, + Make_Attribute_Definition_Clause (Loc, + Name => New_Reference_To (Predef_Prims, Loc), + Chars => Name_Alignment, + Expression => + Make_Attribute_Reference (Loc, + Prefix => + New_Reference_To (RTE (RE_Integer_Address), Loc), + Attribute_Name => Name_Alignment))); + end; + end; + + -- Stage 1: Initialize the discriminant and the record components + + DT_Constr_List := New_List; + DT_Aggr_List := New_List; + + -- Num_Prims. If the tagged type has no primitives we add a dummy + -- slot whose address will be the tag of this type. + + if Nb_Prim = 0 then + New_Node := Make_Integer_Literal (Loc, 1); + else + New_Node := Make_Integer_Literal (Loc, Nb_Prim); + end if; + + Append_To (DT_Constr_List, New_Node); + Append_To (DT_Aggr_List, New_Copy (New_Node)); + + -- Signature + + if RTE_Record_Component_Available (RE_Signature) then + Append_To (DT_Aggr_List, + New_Reference_To (RTE (RE_Primary_DT), Loc)); + end if; + + -- Tag_Kind + + if RTE_Record_Component_Available (RE_Tag_Kind) then + Append_To (DT_Aggr_List, Tagged_Kind (Typ)); + end if; + + -- Predef_Prims + + Append_To (DT_Aggr_List, + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Predef_Prims, Loc), + Attribute_Name => Name_Address)); + + -- Offset_To_Top + + if RTE_Record_Component_Available (RE_Offset_To_Top) then + Append_To (DT_Aggr_List, Make_Integer_Literal (Loc, 0)); + end if; + + -- Typeinfo + + Append_To (DT_Aggr_List, + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (TSD, Loc), + Attribute_Name => Name_Address)); + + -- Stage 2: Initialize the table of primitive operations + + Prim_Ops_Aggr_List := New_List; + + if Nb_Prim = 0 then + Append_To (Prim_Ops_Aggr_List, + New_Reference_To (RTE (RE_Null_Address), Loc)); + + elsif not Static_Dispatch_Tables then + for J in 1 .. Nb_Prim loop + Append_To (Prim_Ops_Aggr_List, + New_Reference_To (RTE (RE_Null_Address), Loc)); + end loop; + + else + declare + Prim_Table : array (Nat range 1 .. Nb_Prim) of Entity_Id; + E : Entity_Id; + Prim : Entity_Id; + Prim_Elmt : Elmt_Id; + + begin + Prim_Table := (others => Empty); + Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); + while Present (Prim_Elmt) loop + Prim := Node (Prim_Elmt); + + if Is_Imported (Prim) + or else Present (Abstract_Interface_Alias (Prim)) + or else Is_Predefined_Dispatching_Operation (Prim) + then + null; + + else + -- Traverse the list of aliased entities to handle + -- renamings of predefined primitives. + + E := Prim; + while Present (Alias (E)) loop + E := Alias (E); + end loop; + + if not Is_Predefined_Dispatching_Operation (E) + and then not Is_Abstract_Subprogram (E) + and then not Present (Abstract_Interface_Alias (E)) + then + pragma Assert + (UI_To_Int (DT_Position (Prim)) <= Nb_Prim); + + Prim_Table (UI_To_Int (DT_Position (Prim))) := E; + + -- There is no need to set Has_Delayed_Freeze here + -- because the analysis of 'Address and 'Code_Address + -- takes care of it. + end if; + end if; + + Next_Elmt (Prim_Elmt); + end loop; + + for J in Prim_Table'Range loop + if Present (Prim_Table (J)) then + New_Node := + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Prim_Table (J), Loc), + Attribute_Name => Name_Address); + else + New_Node := New_Reference_To (RTE (RE_Null_Address), Loc); + end if; + + Append_To (Prim_Ops_Aggr_List, New_Node); + end loop; + end; + end if; + + Append_To (DT_Aggr_List, + Make_Aggregate (Loc, + Expressions => Prim_Ops_Aggr_List)); + + -- In case of locally defined tagged types we have already declared + -- and uninitialized object for the dispatch table, which is now + -- initialized by means of an assignment. + + if Is_Local_DT then + Append_To (Result, + Make_Assignment_Statement (Loc, + Name => New_Reference_To (DT, Loc), + Expression => Make_Aggregate (Loc, + Expressions => DT_Aggr_List))); + + -- In case of library level tagged types we declare now the constant + -- object containing the dispatch table. + + else + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT, + Aliased_Present => True, + Constant_Present => Static_Dispatch_Tables, + Object_Definition => + Make_Subtype_Indication (Loc, + Subtype_Mark => New_Reference_To + (RTE (RE_Dispatch_Table_Wrapper), Loc), + Constraint => Make_Index_Or_Discriminant_Constraint (Loc, + Constraints => DT_Constr_List)), + Expression => Make_Aggregate (Loc, + Expressions => DT_Aggr_List))); + + Append_To (Result, + Make_Attribute_Definition_Clause (Loc, + Name => New_Reference_To (DT, Loc), + Chars => Name_Alignment, + Expression => + Make_Attribute_Reference (Loc, + Prefix => + New_Reference_To (RTE (RE_Integer_Address), Loc), + Attribute_Name => Name_Alignment))); + + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => DT_Ptr, + Object_Definition => New_Reference_To (RTE (RE_Tag), Loc), + Constant_Present => True, + Expression => + Unchecked_Convert_To (Generalized_Tag, + Make_Attribute_Reference (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => New_Reference_To (DT, Loc), + Selector_Name => + New_Occurrence_Of + (RTE_Record_Component (RE_Prims_Ptr), Loc)), + Attribute_Name => Name_Address)))); end if; end if; + -- Initialize the table of ancestor tags + + if not Is_Interface (Typ) + and then not Is_CPP_Class (Typ) + then + Append_To (Result, + Make_Assignment_Statement (Loc, + Name => + Make_Indexed_Component (Loc, + Prefix => + Make_Selected_Component (Loc, + Prefix => + New_Reference_To (TSD, Loc), + Selector_Name => + New_Reference_To + (RTE_Record_Component (RE_Tags_Table), Loc)), + Expressions => + New_List (Make_Integer_Literal (Loc, 0))), + + Expression => + New_Reference_To + (Node (First_Elmt (Access_Disp_Table (Typ))), Loc))); + end if; + + if Static_Dispatch_Tables then + null; + -- If the ancestor is a CPP_Class type we inherit the dispatch tables -- in the init proc, and we don't need to fill them in here. - if Is_CPP_Class (Etype (Typ)) then + elsif Is_CPP_Class (Etype (Typ)) then null; -- Otherwise we fill in the dispatch tables here @@ -3111,39 +4210,32 @@ package body Exp_Disp is -- Inherit the dispatch table if not Is_Interface (Etype (Typ)) then - if Restriction_Active (No_Dispatching_Calls) then - null; + if not Null_Parent_Tag then + declare + Nb_Prims : constant Int := + UI_To_Int (DT_Entry_Count + (First_Tag_Component (Etype (Typ)))); + begin + Append_To (Elab_Code, + Build_Inherit_Predefined_Prims (Loc, + Old_Tag_Node => Old_Tag1, + New_Tag_Node => + New_Reference_To (DT_Ptr, Loc))); - else - if not Null_Parent_Tag then - declare - Nb_Prims : constant Int := - UI_To_Int (DT_Entry_Count - (First_Tag_Component (Etype (Typ)))); - begin + if Nb_Prims /= 0 then Append_To (Elab_Code, - Build_Inherit_Predefined_Prims (Loc, - Old_Tag_Node => Old_Tag1, - New_Tag_Node => - New_Reference_To (DT_Ptr, Loc))); - - if Nb_Prims /= 0 then - Append_To (Elab_Code, - Build_Inherit_Prims (Loc, - Old_Tag_Node => Old_Tag2, - New_Tag_Node => New_Reference_To (DT_Ptr, Loc), - Num_Prims => Nb_Prims)); - end if; - end; - end if; + Build_Inherit_Prims (Loc, + Old_Tag_Node => Old_Tag2, + New_Tag_Node => New_Reference_To (DT_Ptr, Loc), + Num_Prims => Nb_Prims)); + end if; + end; end if; end if; -- Inherit the secondary dispatch tables of the ancestor - if not Restriction_Active (No_Dispatching_Calls) - and then not Is_CPP_Class (Etype (Typ)) - then + if not Is_CPP_Class (Etype (Typ)) then declare Sec_DT_Ancestor : Elmt_Id := Next_Elmt @@ -3187,6 +4279,7 @@ package body Exp_Disp is E := First_Entity (Typ); while Present (E) and then Present (Node (Sec_DT_Ancestor)) + and then Ekind (Node (Sec_DT_Ancestor)) = E_Constant loop if Is_Tag (E) and then Chars (E) /= Name_uTag then if not Is_Interface (Etype (Typ)) then @@ -3238,8 +4331,9 @@ package body Exp_Disp is end Copy_Secondary_DTs; begin - if Present (Node (Sec_DT_Ancestor)) then - + if Present (Node (Sec_DT_Ancestor)) + and then Ekind (Node (Sec_DT_Ancestor)) = E_Constant + then -- Handle private types if Present (Full_View (Typ)) then @@ -3251,50 +4345,6 @@ package body Exp_Disp is end; end if; end if; - - -- Generate: - -- Inherit_TSD (parent'tag, DT_Ptr); - - if not Is_Interface (Typ) then - if Typ = Etype (Typ) - or else Is_CPP_Class (Etype (Typ)) - then - -- New_TSD (DT_Ptr); - - Append_List_To (Elab_Code, - Build_New_TSD (Loc, - New_Tag_Node => New_Reference_To (DT_Ptr, Loc))); - else - -- Inherit_TSD (parent'tag, DT_Ptr); - - Append_To (Elab_Code, - Build_Inherit_TSD (Loc, - Old_Tag_Node => - New_Reference_To - (Node (First_Elmt (Access_Disp_Table (Etype (Typ)))), - Loc), - New_Tag_Node => New_Reference_To (DT_Ptr, Loc), - I_Depth => I_Depth, - Parent_Num_Ifaces => Parent_Num_Ifaces)); - end if; - end if; - end if; - - if not Is_Interface (Typ) - and then RTE_Available (RE_Set_Offset_To_Top) - then - -- Generate: - -- Set_Offset_To_Top (0, DT_Ptr, True, 0, null); - - Append_To (Elab_Code, - Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (RTE (RE_Set_Offset_To_Top), Loc), - Parameter_Associations => New_List ( - New_Reference_To (RTE (RE_Null_Address), Loc), - New_Reference_To (DT_Ptr, Loc), - New_Occurrence_Of (Standard_True, Loc), - Make_Integer_Literal (Loc, Uint_0), - New_Reference_To (RTE (RE_Null_Address), Loc)))); end if; -- Generate code to register the Tag in the External_Tag hash table for @@ -3302,410 +4352,49 @@ package body Exp_Disp is -- Register_Tag (Dt_Ptr); - -- Skip this if routine not available, or in No_Run_Time mode or Typ is - -- an abstract interface type (because the table to register it is not - -- available in the abstract type but in types implementing this - -- interface) - - if not Has_External_Tag_Rep_Clause (Typ) - and then not No_Run_Time_Mode - and then RTE_Available (RE_Register_Tag) - and then Is_RTE (RTE (RE_Tag), RE_Tag) - and then not Is_Interface (Typ) - then - Append_To (Elab_Code, - Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (RTE (RE_Register_Tag), Loc), - Parameter_Associations => - New_List (New_Reference_To (DT_Ptr, Loc)))); - end if; + -- Skip this action in the following cases: + -- 1) if Register_Tag is not available. + -- 2) in No_Run_Time mode. + -- 3) if Typ is an abstract interface type (the secondary tags will + -- be registered later in types implementing this interface type). + -- 4) if Typ is not defined at the library level (this is required + -- to avoid adding concurrency control to the hash table used + -- by the run-time to register the tags). -- Generate: -- if No_Reg then - -- + -- [ Elab_Code ] + -- [ Register_Tag (Dt_Ptr); ] -- No_Reg := False; -- end if; - Append_To (Elab_Code, - Make_Assignment_Statement (Loc, - Name => New_Reference_To (No_Reg, Loc), - Expression => New_Reference_To (Standard_False, Loc))); - - Append_To (Result, - Make_Implicit_If_Statement (Typ, - Condition => New_Reference_To (No_Reg, Loc), - Then_Statements => Elab_Code)); - - -- Ada 2005 (AI-251): Register the tag of the interfaces into the table - -- of interfaces. - - if Num_Ifaces > 0 then - declare - Position : Nat; - - begin - -- If the parent is an interface we must generate code to register - -- all its interfaces; otherwise this code is not needed because - -- Inherit_TSD has already inherited such interfaces. - - if Is_Concurrent_Record_Type (Typ) - or else (Etype (Typ) /= Typ and then Is_Interface (Etype (Typ))) - then - Position := 1; - - AI := First_Elmt (Ancestor_Ifaces); - while Present (AI) loop - -- Generate: - -- Register_Interface (DT_Ptr, Interface'Tag); - - Append_To (Result, - Make_DT_Access_Action (Typ, - Action => Register_Interface_Tag, - Args => New_List ( - Node1 => New_Reference_To (DT_Ptr, Loc), - Node2 => New_Reference_To - (Node - (First_Elmt - (Access_Disp_Table (Node (AI)))), - Loc), - Node3 => Make_Integer_Literal (Loc, Position)))); - - Position := Position + 1; - Next_Elmt (AI); - end loop; - end if; - - -- Register the interfaces that are not implemented by the - -- ancestor - - AI := First_Elmt (Typ_Ifaces); - - -- Skip the interfaces implemented by the ancestor - - for Count in 1 .. Parent_Num_Ifaces loop - Next_Elmt (AI); - end loop; - - -- Register the additional interfaces - - Position := Parent_Num_Ifaces + 1; - while Present (AI) loop - - -- Generate: - -- Register_Interface (DT_Ptr, Interface'Tag); - - if not Is_Interface (Typ) - or else Typ /= Node (AI) - then - Append_To (Result, - Make_DT_Access_Action (Typ, - Action => Register_Interface_Tag, - Args => New_List ( - Node1 => New_Reference_To (DT_Ptr, Loc), - Node2 => New_Reference_To - (Node - (First_Elmt - (Access_Disp_Table (Node (AI)))), - Loc), - Node3 => Make_Integer_Literal (Loc, Position)))); - - Position := Position + 1; - end if; + if not Is_Interface (Typ) then + if not No_Run_Time_Mode + and then not Is_Local_DT + and then RTE_Available (RE_Register_Tag) + then + Append_To (Elab_Code, + Make_Procedure_Call_Statement (Loc, + Name => New_Reference_To (RTE (RE_Register_Tag), Loc), + Parameter_Associations => + New_List (New_Reference_To (DT_Ptr, Loc)))); + end if; - Next_Elmt (AI); - end loop; + Append_To (Elab_Code, + Make_Assignment_Statement (Loc, + Name => New_Reference_To (No_Reg, Loc), + Expression => New_Reference_To (Standard_False, Loc))); - pragma Assert (Position = Num_Ifaces + 1); - end; + Append_To (Result, + Make_Implicit_If_Statement (Typ, + Condition => New_Reference_To (No_Reg, Loc), + Then_Statements => Elab_Code)); end if; + Analyze_List (Result, Suppress => All_Checks); return Result; end Make_DT; - --------------------------- - -- Make_DT_Access_Action -- - --------------------------- - - function Make_DT_Access_Action - (Typ : Entity_Id; - Action : DT_Access_Action; - Args : List_Id) return Node_Id - is - Action_Name : constant Entity_Id := RTE (Ada_Actions (Action)); - Loc : Source_Ptr; - - begin - if No (Args) then - - -- This is a constant - - return New_Reference_To (Action_Name, Sloc (Typ)); - end if; - - pragma Assert (List_Length (Args) = Action_Nb_Arg (Action)); - - Loc := Sloc (First (Args)); - - if Action_Is_Proc (Action) then - return - Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (Action_Name, Loc), - Parameter_Associations => Args); - - else - return - Make_Function_Call (Loc, - Name => New_Reference_To (Action_Name, Loc), - Parameter_Associations => Args); - end if; - end Make_DT_Access_Action; - - ----------------------- - -- Make_Secondary_DT -- - ----------------------- - - procedure Make_Secondary_DT - (Typ : Entity_Id; - Ancestor_Typ : Entity_Id; - Suffix_Index : Nat; - Iface : Entity_Id; - AI_Tag : Entity_Id; - Acc_Disp_Tables : in out Elist_Id; - Result : out List_Id) - is - Loc : constant Source_Ptr := Sloc (AI_Tag); - Generalized_Tag : constant Entity_Id := RTE (RE_Interface_Tag); - Name_DT : constant Name_Id := New_Internal_Name ('T'); - Empty_DT : Boolean := False; - Iface_DT : Node_Id; - Iface_DT_Ptr : Node_Id; - Name_DT_Ptr : Name_Id; - Nb_Prim : Nat; - OSD : Entity_Id; - Size_Expr_Node : Node_Id; - Tname : Name_Id; - - begin - Result := New_List; - - -- Generate a unique external name associated with the secondary - -- dispatch table. This external name will be used to declare an - -- access to this secondary dispatch table, value that will be used - -- for the elaboration of Typ's objects and also for the elaboration - -- of objects of any derivation of Typ that do not override any - -- primitive operation of Typ. - - Get_Secondary_DT_External_Name (Typ, Ancestor_Typ, Suffix_Index); - - Tname := Name_Find; - Name_DT_Ptr := New_External_Name (Tname, "P"); - Iface_DT := Make_Defining_Identifier (Loc, Name_DT); - Iface_DT_Ptr := Make_Defining_Identifier (Loc, Name_DT_Ptr); - - -- Dispatch table and related entities are allocated statically - - Set_Ekind (Iface_DT, E_Variable); - Set_Is_Statically_Allocated (Iface_DT); - - Set_Ekind (Iface_DT_Ptr, E_Variable); - Set_Is_Statically_Allocated (Iface_DT_Ptr); - - -- Generate code to create the storage for the Dispatch_Table object. - -- If the number of primitives of Typ is 0 we reserve a dummy single - -- entry for its DT because at run-time the pointer to this dummy entry - -- will be used as the tag. - - Nb_Prim := UI_To_Int (DT_Entry_Count (AI_Tag)); - - if Nb_Prim = 0 then - Empty_DT := True; - Nb_Prim := 1; - end if; - - -- DT : Storage_Array (1..DT_Prologue_Size+nb_prim*DT_Entry_Size); - -- for DT'Alignment use Address'Alignment - - Size_Expr_Node := - Make_Op_Add (Loc, - Left_Opnd => - New_Reference_To (RTE (RE_DT_Prologue_Size), Loc), - Right_Opnd => - Make_Op_Multiply (Loc, - Left_Opnd => - New_Reference_To (RTE (RE_DT_Entry_Size), Loc), - Right_Opnd => - Make_Integer_Literal (Loc, Nb_Prim))); - - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => Iface_DT, - Aliased_Present => True, - Object_Definition => - Make_Subtype_Indication (Loc, - Subtype_Mark => New_Reference_To (RTE (RE_Storage_Array), Loc), - Constraint => Make_Index_Or_Discriminant_Constraint (Loc, - Constraints => New_List ( - Make_Range (Loc, - Low_Bound => Make_Integer_Literal (Loc, 1), - High_Bound => Size_Expr_Node)))))); - - Append_To (Result, - Make_Attribute_Definition_Clause (Loc, - Name => New_Reference_To (Iface_DT, Loc), - Chars => Name_Alignment, - Expression => - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc), - Attribute_Name => Name_Alignment))); - - -- Generate code to create the pointer to the dispatch table - - -- Iface_DT_Ptr : Tag := Tag!(DT'Address); - - -- According to the C++ ABI, the base of the vtable is located - -- after the following prologue: Offset_To_Top, and Typeinfo_Ptr. - -- Hence, move the pointer down to the real base of the vtable. - - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => Iface_DT_Ptr, - Constant_Present => True, - Object_Definition => New_Reference_To (Generalized_Tag, Loc), - Expression => - Unchecked_Convert_To (Generalized_Tag, - Make_Op_Add (Loc, - Left_Opnd => - Unchecked_Convert_To (RTE (RE_Storage_Offset), - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Iface_DT, Loc), - Attribute_Name => Name_Address)), - Right_Opnd => - New_Reference_To (RTE (RE_DT_Prologue_Size), Loc))))); - - -- Note: Offset_To_Top will be initialized by the init subprogram - - -- Set Access_Disp_Table field to be the dispatch table pointer - - if not (Present (Acc_Disp_Tables)) then - Acc_Disp_Tables := New_Elmt_List; - end if; - - Append_Elmt (Iface_DT_Ptr, Acc_Disp_Tables); - - -- Step 1: Generate an Object Specific Data (OSD) table - - OSD := Make_Defining_Identifier (Loc, New_Internal_Name ('I')); - - -- Nothing to do if configurable run time does not support the - -- Object_Specific_Data entity. - - if not RTE_Available (RE_Object_Specific_Data) then - Error_Msg_CRT ("abstract interface types", Typ); - return; - end if; - - -- Generate: - -- OSD : Ada.Tags.Object_Specific_Data (Nb_Prims); - -- where the constraint is used to allocate space for the - -- non-predefined primitive operations only. - - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => OSD, - Object_Definition => - Make_Subtype_Indication (Loc, - Subtype_Mark => New_Reference_To ( - RTE (RE_Object_Specific_Data), Loc), - Constraint => - Make_Index_Or_Discriminant_Constraint (Loc, - Constraints => New_List ( - Make_Integer_Literal (Loc, Nb_Prim)))))); - - Append_To (Result, - Make_DT_Access_Action (Typ, - Action => Set_Signature, - Args => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (Iface_DT_Ptr, Loc)), - New_Reference_To (RTE (RE_Secondary_DT), Loc)))); - - -- Generate: - -- Ada.Tags.Set_OSD (Iface_DT_Ptr, OSD); - - Append_To (Result, - Make_DT_Access_Action (Typ, - Action => Set_OSD, - Args => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (Iface_DT_Ptr, Loc)), - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (OSD, Loc), - Attribute_Name => Name_Address)))); - - if Ada_Version >= Ada_05 - and then not Is_Interface (Typ) - and then not Is_Abstract_Type (Typ) - and then not Is_Controlled (Typ) - and then RTE_Available (RE_Set_Tagged_Kind) - and then not Restriction_Active (No_Dispatching_Calls) - then - -- Generate: - -- Set_Tagged_Kind (Iface'Tag, Tagged_Kind (Iface)); - - Append_To (Result, - Make_DT_Access_Action (Typ, - Action => Set_Tagged_Kind, - Args => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), -- DTptr - New_Reference_To (Iface_DT_Ptr, Loc)), - Tagged_Kind (Typ)))); -- Value - - if not Empty_DT - and then Is_Concurrent_Record_Type (Typ) - and then Has_Abstract_Interfaces (Typ) - then - declare - Prim : Entity_Id; - Prim_Alias : Entity_Id; - Prim_Elmt : Elmt_Id; - - begin - -- Step 2: Populate the OSD table - - Prim_Alias := Empty; - Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); - while Present (Prim_Elmt) loop - Prim := Node (Prim_Elmt); - - if Present (Abstract_Interface_Alias (Prim)) - and then Find_Dispatching_Type - (Abstract_Interface_Alias (Prim)) = Iface - then - Prim_Alias := Abstract_Interface_Alias (Prim); - - -- Generate: - -- Ada.Tags.Set_Offset_Index (Tag (Iface_DT_Ptr), - -- Secondary_DT_Pos, Primary_DT_pos); - - Append_To (Result, - Make_DT_Access_Action (Iface, - Action => Set_Offset_Index, - Args => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (Iface_DT_Ptr, Loc)), - Make_Integer_Literal (Loc, - DT_Position (Prim_Alias)), - Make_Integer_Literal (Loc, - DT_Position (Alias (Prim)))))); - end if; - - Next_Elmt (Prim_Elmt); - end loop; - end; - end if; - end if; - end Make_Secondary_DT; - ------------------------------------- -- Make_Select_Specific_Data_Table -- ------------------------------------- @@ -3817,12 +4506,12 @@ package body Exp_Disp is -- Ada.Tags.Set_Prim_Op_Kind (DT_Ptr, , ); Append_To (Assignments, - Make_DT_Access_Action (Typ, - Action => Set_Prim_Op_Kind, - Args => New_List ( - New_Reference_To (DT_Ptr, Loc), - Make_Integer_Literal (Loc, Prim_Pos), - Prim_Op_Kind (Alias (Prim), Typ)))); + Make_Procedure_Call_Statement (Loc, + Name => New_Reference_To (RTE (RE_Set_Prim_Op_Kind), Loc), + Parameter_Associations => New_List ( + New_Reference_To (DT_Ptr, Loc), + Make_Integer_Literal (Loc, Prim_Pos), + Prim_Op_Kind (Alias (Prim), Typ)))); -- Retrieve the root of the alias chain @@ -3842,14 +4531,14 @@ package body Exp_Disp is -- (DT_Ptr, , ); Append_To (Assignments, - Make_DT_Access_Action (Typ, - Action => Set_Entry_Index, - Args => New_List ( - New_Reference_To (DT_Ptr, Loc), - Make_Integer_Literal (Loc, Prim_Pos), - Make_Integer_Literal (Loc, - Find_Entry_Index - (Wrapped_Entity (Prim_Als)))))); + Make_Procedure_Call_Statement (Loc, + Name => + New_Reference_To (RTE (RE_Set_Entry_Index), Loc), + Parameter_Associations => New_List ( + New_Reference_To (DT_Ptr, Loc), + Make_Integer_Literal (Loc, Prim_Pos), + Make_Integer_Literal (Loc, + Find_Entry_Index (Wrapped_Entity (Prim_Als)))))); end if; end if; @@ -3973,6 +4662,123 @@ package body Exp_Disp is end if; end Prim_Op_Kind; + ------------------------ + -- Register_Primitive -- + ------------------------ + + procedure Register_Primitive + (Loc : Source_Ptr; + Prim : Entity_Id; + Ins_Nod : Node_Id) + is + DT_Ptr : Entity_Id; + Iface_Prim : Entity_Id; + Iface_Typ : Entity_Id; + Iface_DT_Ptr : Entity_Id; + Pos : Uint; + Tag : Entity_Id; + Thunk_Id : Entity_Id; + Thunk_Code : Node_Id; + Typ : Entity_Id; + + begin + pragma Assert (not Restriction_Active (No_Dispatching_Calls)); + + if not RTE_Available (RE_Tag) then + return; + end if; + + if not Present (Abstract_Interface_Alias (Prim)) then + Typ := Scope (DTC_Entity (Prim)); + DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); + Pos := DT_Position (Prim); + Tag := First_Tag_Component (Typ); + + if Is_Predefined_Dispatching_Operation (Prim) + or else Is_Predefined_Dispatching_Alias (Prim) + then + Insert_After (Ins_Nod, + Build_Set_Predefined_Prim_Op_Address (Loc, + Tag_Node => New_Reference_To (DT_Ptr, Loc), + Position => Pos, + Address_Node => Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Prim, Loc), + Attribute_Name => Name_Address))); + + else + pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag)); + + Insert_After (Ins_Nod, + Build_Set_Prim_Op_Address (Loc, + Typ => Typ, + Tag_Node => New_Reference_To (DT_Ptr, Loc), + Position => Pos, + Address_Node => Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Prim, Loc), + Attribute_Name => Name_Address))); + end if; + + -- Ada 2005 (AI-251): Primitive associated with an interface type + -- Generate the code of the thunk only if the interface type is not an + -- immediate ancestor of Typ; otherwise the dispatch table associated + -- with the interface is the primary dispatch table and we have nothing + -- else to do here. + + else + Typ := Find_Dispatching_Type (Alias (Prim)); + Iface_Typ := Find_Dispatching_Type (Abstract_Interface_Alias (Prim)); + + pragma Assert (Is_Interface (Iface_Typ)); + + Expand_Interface_Thunk + (N => Prim, + Thunk_Alias => Alias (Prim), + Thunk_Id => Thunk_Id, + Thunk_Code => Thunk_Code); + + if not Is_Parent (Iface_Typ, Typ) + and then Present (Thunk_Code) + then + Insert_Action (Ins_Nod, Thunk_Code, Suppress => All_Checks); + + -- Generate the code necessary to fill the appropriate entry of + -- the secondary dispatch table of Prim's controlling type with + -- Thunk_Id's address. + + Iface_DT_Ptr := Find_Interface_ADT (Typ, Iface_Typ); + Iface_Prim := Abstract_Interface_Alias (Prim); + Pos := DT_Position (Iface_Prim); + Tag := First_Tag_Component (Iface_Typ); + + if Is_Predefined_Dispatching_Operation (Prim) + or else Is_Predefined_Dispatching_Alias (Prim) + then + Insert_Action (Ins_Nod, + Build_Set_Predefined_Prim_Op_Address (Loc, + Tag_Node => New_Reference_To (Iface_DT_Ptr, Loc), + Position => Pos, + Address_Node => + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (Thunk_Id, Loc), + Attribute_Name => Name_Address))); + else + pragma Assert (Pos /= Uint_0 + and then Pos <= DT_Entry_Count (Tag)); + + Insert_Action (Ins_Nod, + Build_Set_Prim_Op_Address (Loc, + Typ => Iface_Typ, + Tag_Node => New_Reference_To (Iface_DT_Ptr, Loc), + Position => Pos, + Address_Node => Make_Attribute_Reference (Loc, + Prefix => + New_Reference_To (Thunk_Id, Loc), + Attribute_Name => Name_Address))); + end if; + end if; + end if; + end Register_Primitive; + ------------------------- -- Set_All_DT_Position -- ------------------------- @@ -4112,21 +4918,7 @@ package body Exp_Disp is Count_Prim := Count_Prim + 1; end if; - -- Ada 2005 (AI-251) - - if Present (Abstract_Interface_Alias (Prim)) - and then Is_Interface - (Find_Dispatching_Type - (Abstract_Interface_Alias (Prim))) - then - Set_DTC_Entity (Prim, - Find_Interface_Tag - (T => Typ, - Iface => Find_Dispatching_Type - (Abstract_Interface_Alias (Prim)))); - else - Set_DTC_Entity (Prim, The_Tag); - end if; + Set_DTC_Entity_Value (Typ, Prim); -- Clear any previous value of the DT_Position attribute. In this -- way we ensure that the final position of all the primitives is @@ -4142,10 +4934,70 @@ package body Exp_Disp is := (others => False); E : Entity_Id; + procedure Handle_Inherited_Private_Subprograms (Typ : Entity_Id); + -- Called if Typ is declared in a nested package or a public child + -- package to handle inherited primitives that were inherited by Typ + -- in the visible part, but whose declaration was deferred because + -- the parent operation was private and not visible at that point. + procedure Set_Fixed_Prim (Pos : Nat); -- Sets to true an element of the Fixed_Prim table to indicate -- that this entry of the dispatch table of Typ is occupied. + ------------------------------------------ + -- Handle_Inherited_Private_Subprograms -- + ------------------------------------------ + + procedure Handle_Inherited_Private_Subprograms (Typ : Entity_Id) is + Op_List : Elist_Id; + Op_Elmt : Elmt_Id; + Op_Elmt_2 : Elmt_Id; + Prim_Op : Entity_Id; + Parent_Subp : Entity_Id; + + begin + Op_List := Primitive_Operations (Typ); + + Op_Elmt := First_Elmt (Op_List); + while Present (Op_Elmt) loop + Prim_Op := Node (Op_Elmt); + + -- Search primitives that are implicit operations with an + -- internal name whose parent operation has a normal name. + + if Present (Alias (Prim_Op)) + and then Find_Dispatching_Type (Alias (Prim_Op)) /= Typ + and then not Comes_From_Source (Prim_Op) + and then Is_Internal_Name (Chars (Prim_Op)) + and then not Is_Internal_Name (Chars (Alias (Prim_Op))) + then + Parent_Subp := Alias (Prim_Op); + + -- Check if the type has an explicit overriding for this + -- primitive. + + Op_Elmt_2 := Next_Elmt (Op_Elmt); + while Present (Op_Elmt_2) loop + if Chars (Node (Op_Elmt_2)) = Chars (Parent_Subp) + and then Type_Conformant (Prim_Op, Node (Op_Elmt_2)) + then + Set_DT_Position (Prim_Op, DT_Position (Parent_Subp)); + Set_DT_Position (Node (Op_Elmt_2), + DT_Position (Parent_Subp)); + Set_Fixed_Prim (UI_To_Int (DT_Position (Prim_Op))); + + goto Next_Primitive; + end if; + + Next_Elmt (Op_Elmt_2); + end loop; + end if; + + <> + Next_Elmt (Op_Elmt); + end loop; + end Handle_Inherited_Private_Subprograms; + -------------------- -- Set_Fixed_Prim -- -------------------- @@ -4160,6 +5012,22 @@ package body Exp_Disp is end Set_Fixed_Prim; begin + -- In case of nested packages and public child package it may be + -- necessary a special management on inherited subprograms so that + -- the dispatch table is properly filled. + + if Ekind (Scope (Scope (Typ))) = E_Package + and then Scope (Scope (Typ)) /= Standard_Standard + and then ((Is_Derived_Type (Typ) and then not Is_Private_Type (Typ)) + or else + (Nkind (Parent (Typ)) = N_Private_Extension_Declaration + and then Is_Generic_Type (Typ))) + and then In_Open_Scopes (Scope (Etype (Typ))) + and then Typ = Base_Type (Typ) + then + Handle_Inherited_Private_Subprograms (Typ); + end if; + -- Second stage: Register fixed entries Nb_Prim := 0; @@ -4203,7 +5071,7 @@ package body Exp_Disp is Set_Fixed_Prim (UI_To_Int (DT_Position (Prim))); -- Overriding primitives must use the same entry as the - -- overriden primitive + -- overriden primitive. elsif not Present (Abstract_Interface_Alias (Prim)) and then Present (Alias (Prim)) @@ -4402,19 +5270,14 @@ package body Exp_Disp is Set_DT_Entry_Count (The_Tag, UI_From_Int (DT_Length)); - -- The derived type must have at least as many components as its - -- parent (for root types, the Etype points back to itself - -- and the test should not fail) - - -- This test fails compiling the partial view of a tagged type - -- derived from an interface which defines the overriding subprogram - -- in the private part. This needs further investigation??? + -- The derived type must have at least as many components as its parent + -- (for root types, the Etype points back to itself and the test cannot + -- fail) - if not Has_Private_Declaration (Typ) then - pragma Assert ( - DT_Entry_Count (The_Tag) >= - DT_Entry_Count (First_Tag_Component (Parent_Typ))); - null; + if DT_Entry_Count (The_Tag) < + DT_Entry_Count (First_Tag_Component (Parent_Typ)) + then + raise Program_Error; end if; end Set_All_DT_Position; @@ -4470,6 +5333,31 @@ package body Exp_Disp is end if; end Set_Default_Constructor; + -------------------------- + -- Set_DTC_Entity_Value -- + -------------------------- + + procedure Set_DTC_Entity_Value + (Tagged_Type : Entity_Id; + Prim : Entity_Id) + is + begin + if Present (Abstract_Interface_Alias (Prim)) + and then Is_Interface + (Find_Dispatching_Type + (Abstract_Interface_Alias (Prim))) + then + Set_DTC_Entity (Prim, + Find_Interface_Tag + (T => Tagged_Type, + Iface => Find_Dispatching_Type + (Abstract_Interface_Alias (Prim)))); + else + Set_DTC_Entity (Prim, + First_Tag_Component (Tagged_Type)); + end if; + end Set_DTC_Entity_Value; + ----------------- -- Tagged_Kind -- ----------------- diff --git a/gcc/ada/exp_disp.ads b/gcc/ada/exp_disp.ads index 7314ae255e3..32cde2f6302 100644 --- a/gcc/ada/exp_disp.ads +++ b/gcc/ada/exp_disp.ads @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2006, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2007, 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- -- @@ -111,7 +111,7 @@ package Exp_Disp is -- interfaces, not generated for the rest of the cases. See Expand_N_ -- Timed_Entry_Call for more information. - -- Lifecycle of predefined primitive operations + -- Life cycle of predefined primitive operations -- The specifications and bodies of the PPOs are created by -- Make_Predefined_Primitive_Specs and Predefined_Primitive_Bodies @@ -122,16 +122,14 @@ package Exp_Disp is -- PPOs are collected and added to the Primitive_Operations list of -- a type by the regular analysis mechanism. - -- PPOs are frozen in Predefined_Primitive_Freeze in Exp_Ch3. + -- PPOs are frozen by Exp_Ch3.Predefined_Primitive_Freeze. - -- Thunks for PPOs are created in Freeze_Subprogram in Exp_Ch6, by a - -- call to Register_Predefined_DT_Entry, also in Exp_Ch6. + -- Thunks for PPOs are created by Make_DT. - -- Dispatch table positions of PPOs are set in Set_All_DT_Position in - -- Exp_Disp. + -- Dispatch table positions of PPOs are set by Set_All_DT_Position. - -- Calls to PPOs procede as regular dispatching calls. If the PPO - -- has a thunk, a call procedes as a regular dispatching call with + -- Calls to PPOs proceed as regular dispatching calls. If the PPO + -- has a thunk, a call proceeds as a regular dispatching call with -- a thunk. -- Guidelines for addition of new predefined primitive operations @@ -167,21 +165,6 @@ package Exp_Disp is -- Exp_Disp.Default_Prim_Op_Position - indirect use -- Exp_Disp.Set_All_DT_Position - direct use - type DT_Access_Action is - (IW_Membership, - Get_Entry_Index, - Get_Prim_Op_Kind, - Get_Tagged_Kind, - Register_Interface_Tag, - Register_Tag, - Set_Entry_Index, - Set_Offset_Index, - Set_OSD, - Set_Prim_Op_Kind, - Set_Signature, - Set_SSD, - Set_Tagged_Kind); - procedure Expand_Dispatching_Call (Call_Node : Node_Id); -- Expand the call to the operation through the dispatch table and perform -- the required tag checks when appropriate. For CPP types tag checks are @@ -198,41 +181,22 @@ package Exp_Disp is -- the object to give access to the interface tag associated with the -- secondary dispatch table. - function Expand_Interface_Thunk + procedure Expand_Interface_Thunk (N : Node_Id; Thunk_Alias : Node_Id; - Thunk_Id : Entity_Id) return Node_Id; + Thunk_Id : out Entity_Id; + Thunk_Code : out Node_Id); -- Ada 2005 (AI-251): When a tagged type implements abstract interfaces we -- generate additional subprograms (thunks) to have a layout compatible -- with the C++ ABI. The thunk modifies the value of the first actual of -- the call (that is, the pointer to the object) before transferring -- control to the target function. - - function Fill_DT_Entry - (Loc : Source_Ptr; - Prim : Entity_Id) return Node_Id; - -- Generate the code necessary to fill the appropriate entry of the - -- dispatch table of Prim's controlling type with Prim's address. - - function Fill_Secondary_DT_Entry - (Loc : Source_Ptr; - Prim : Entity_Id; - Thunk_Id : Entity_Id; - Iface_DT_Ptr : Entity_Id) return Node_Id; - -- (Ada 2005): Generate the code necessary to fill the appropriate entry of - -- the secondary dispatch table of Prim's controlling type with Thunk_Id's - -- address. - - function Make_DT_Access_Action - (Typ : Entity_Id; - Action : DT_Access_Action; - Args : List_Id) return Node_Id; - -- Generate a call to one of the Dispatch Table Access Subprograms defined - -- in Ada.Tags or in Interfaces.Cpp + -- + -- Required in 3.4 case, why ??? giant comment needed for any gcc + -- specific code ??? function Make_DT (Typ : Entity_Id) return List_Id; - -- Expand the declarations for the Dispatch Table (or the Vtable in - -- the case of type whose ancestor is a CPP_Class) + -- Expand the declarations for the Dispatch Table. function Make_Disp_Asynchronous_Select_Body (Typ : Entity_Id) return Node_Id; @@ -284,8 +248,8 @@ package Exp_Disp is function Make_Disp_Timed_Select_Body (Typ : Entity_Id) return Node_Id; -- Ada 2005 (AI-345): Generate the body of the primitive operation of type - -- Typ used for dispatching in timed selects. Generate a null body if Nul - -- is an interface type. + -- Typ used for dispatching in timed selects. Generates a body containing + -- a single null-statement if Typ is an interface type. function Make_Disp_Timed_Select_Spec (Typ : Entity_Id) return Node_Id; @@ -299,20 +263,19 @@ package Exp_Disp is -- selects. Generate code to set the primitive operation kinds and entry -- indices of primitive operations and primitive wrappers. - procedure Make_Secondary_DT - (Typ : Entity_Id; - Ancestor_Typ : Entity_Id; - Suffix_Index : Nat; - Iface : Entity_Id; - AI_Tag : Entity_Id; - Acc_Disp_Tables : in out Elist_Id; - Result : out List_Id); - -- Ada 2005 (AI-251): Expand the declarations for the Secondary Dispatch - -- Table of Typ associated with Iface (each abstract interface implemented - -- by Typ has a secondary dispatch table). The arguments Typ, Ancestor_Typ - -- and Suffix_Index are used to generate an unique external name which - -- is added at the end of Acc_Disp_Tables; this external name will be - -- used later by the subprogram Exp_Ch3.Build_Init_Procedure. + procedure Register_Primitive + (Loc : Source_Ptr; + Prim : Entity_Id; + Ins_Nod : Node_Id); + -- Register Prim in the corresponding primary or secondary dispatch table. + -- If Prim is associated with a secondary dispatch table then generate also + -- its thunk and register it in the associated secondary dispatch table. + -- In general the dispatch tables are always generated by Make_DT and + -- Make_Secondary_DT; this routine is only used in two corner cases: + -- 1) To construct the dispatch table of a tagged type whose parent + -- is a CPP_Class (see Build_Init_Procedure). + -- 2) To handle late overriding of dispatching operations (see + -- Check_Dispatching_Operation). procedure Set_All_DT_Position (Typ : Entity_Id); -- Set the DT_Position field for each primitive operation. In the CPP @@ -324,6 +287,12 @@ package Exp_Disp is -- be the default constructor (i.e. the function returning this type, -- having a pragma CPP_Constructor and no parameter) + procedure Set_DTC_Entity_Value + (Tagged_Type : Entity_Id; + Prim : Entity_Id); + -- Set the definite value of the DTC_Entity value associated with a given + -- primitive of a tagged type. + procedure Write_DT (Typ : Entity_Id); pragma Export (Ada, Write_DT); -- Debugging procedure (to be called within gdb) diff --git a/gcc/ada/rtsfind.adb b/gcc/ada/rtsfind.adb index 9f8993b2961..af2163d3ff6 100644 --- a/gcc/ada/rtsfind.adb +++ b/gcc/ada/rtsfind.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2006, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2007, 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- -- @@ -541,7 +541,15 @@ package body Rtsfind is Output_Entity_Name (Id, "not available"); end if; - raise RE_Not_Available; + -- In configurable run time mode, we raise RE_Not_Available, and we hope + -- the caller deals gracefully with this. If we are in normal full run + -- time mode, a load failure is considered fatal and unrecoverable. + + if Configurable_Run_Time_Mode then + raise RE_Not_Available; + else + raise Unrecoverable_Error; + end if; end Load_Fail; -------------- @@ -683,12 +691,24 @@ package body Rtsfind is Set_Analyzed (Cunit (Current_Sem_Unit), True); if not Analyzed (Cunit (U.Unum)) then - Save_Private_Visibility; - Semantics (Cunit (U.Unum)); - Restore_Private_Visibility; - if Fatal_Error (U.Unum) then - Load_Fail ("had semantic errors", U_Id, Id); + -- If the unit is already loaded through a limited_with clauses, + -- the relevant entities must already be available. We do not + -- want to load and analyze the unit because this would create + -- a real semantic dependence when the purpose of the limited_with + -- is precisely to avoid such. + + if From_With_Type (Cunit_Entity (U.Unum)) then + null; + + else + Save_Private_Visibility; + Semantics (Cunit (U.Unum)); + Restore_Private_Visibility; + + if Fatal_Error (U.Unum) then + Load_Fail ("had semantic errors", U_Id, Id); + end if; end if; end if; @@ -891,7 +911,8 @@ package body Rtsfind is ----------------------- function Find_Local_Entity (E : RE_Id) return Entity_Id is - RE_Str : String renames RE_Id'Image (E); + RE_Str : constant String := RE_Id'Image (E); + Nam : Name_Id; Ent : Entity_Id; Save_Nam : constant String := Name_Buffer (1 .. Name_Len); @@ -902,7 +923,8 @@ package body Rtsfind is Name_Buffer (1 .. Name_Len) := RE_Str (RE_Str'First + 3 .. RE_Str'Last); - Ent := Entity_Id (Get_Name_Table_Info (Name_Find)); + Nam := Name_Find; + Ent := Entity_Id (Get_Name_Table_Info (Nam)); Name_Len := Save_Nam'Length; Name_Buffer (1 .. Name_Len) := Save_Nam; @@ -956,9 +978,16 @@ package body Rtsfind is pragma Assert (Nkind (Lib_Unit) = N_Package_Declaration); Ename := RE_Chars (E); - -- First we search the package entity chain + -- First we search the package entity chain. If the package + -- only has a limited view, scan the corresponding list of + -- incomplete types. + + if From_With_Type (U.Entity) then + Pkg_Ent := First_Entity (Limited_View (U.Entity)); + else + Pkg_Ent := First_Entity (U.Entity); + end if; - Pkg_Ent := First_Entity (U.Entity); while Present (Pkg_Ent) loop if Ename = Chars (Pkg_Ent) then RE_Table (E) := Pkg_Ent; @@ -1067,6 +1096,7 @@ package body Rtsfind is U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id); E1 : Entity_Id; Ename : Name_Id; + Found_E : Entity_Id; Lib_Unit : Node_Id; Pkg_Ent : Entity_Id; @@ -1103,13 +1133,15 @@ package body Rtsfind is -- Search the entity in the components of record type declarations -- found in the package entity chain. + Found_E := Empty; Pkg_Ent := First_Entity (U.Entity); Search : while Present (Pkg_Ent) loop if Is_Record_Type (Pkg_Ent) then E1 := First_Entity (Pkg_Ent); while Present (E1) loop if Ename = Chars (E1) then - exit Search; + pragma Assert (not Present (Found_E)); + Found_E := E1; end if; Next_Entity (E1); @@ -1157,7 +1189,7 @@ package body Rtsfind is end if; Front_End_Inlining := Save_Front_End_Inlining; - return Check_CRT (E, E1); + return Check_CRT (E, Found_E); end RTE_Record_Component; ------------------------------------ @@ -1366,6 +1398,12 @@ package body Rtsfind is end if; end loop; end if; + + exception + -- Generate error message if run-time unit not available + + when RE_Not_Available => + Error_Msg_N ("& not available", Nam); end Text_IO_Kludge; end Rtsfind; diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads index 81a8f34ead0..cb59e71cc87 100644 --- a/gcc/ada/rtsfind.ads +++ b/gcc/ada/rtsfind.ads @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2006, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2007, 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- -- @@ -184,6 +184,7 @@ package Rtsfind is -- Children of System + System_Address_Image, System_Arith_64, System_AST_Handling, System_Assertions, @@ -201,6 +202,7 @@ package Rtsfind is System_Compare_Array_Unsigned_8, System_DSA_Services, System_Exception_Table, + System_Exceptions, System_Exn_Int, System_Exn_LLF, System_Exn_LLI, @@ -399,7 +401,7 @@ package Rtsfind is -- Range of values for children of Interfaces subtype System_Child is RTU_Id - range System_Arith_64 .. System_Tasking_Stages; + range System_Address_Image .. System_Tasking_Stages; -- Range of values for children or grandchildren of System subtype System_Tasking_Child is System_Child @@ -456,11 +458,11 @@ package Rtsfind is RE_Exception_Message, -- Ada.Exceptions RE_Exception_Name_Simple, -- Ada.Exceptions RE_Exception_Occurrence, -- Ada.Exceptions - RE_Local_Raise, -- Ada.Exceptions RE_Null_Occurrence, -- Ada.Exceptions RE_Poll, -- Ada.Exceptions RE_Raise_Exception, -- Ada.Exceptions RE_Raise_Exception_Always, -- Ada.Exceptions + RE_Raise_From_Controlled_Operation, -- Ada.Exceptions RE_Reraise_Occurrence, -- Ada.Exceptions RE_Reraise_Occurrence_Always, -- Ada.Exceptions RE_Reraise_Occurrence_No_Defer, -- Ada.Exceptions @@ -485,42 +487,45 @@ package Rtsfind is RE_Stream_Access, -- Ada.Streams.Stream_IO - RE_Abstract_Interface, -- Ada.Tags RE_Access_Level, -- Ada.Tags + RE_Address_Array, -- Ada.Tags RE_Addr_Ptr, -- Ada.Tags RE_Base_Address, -- Ada.Tags RE_Cstring_Ptr, -- Ada.Tags RE_Default_Prim_Op_Count, -- Ada.Tags RE_Descendant_Tag, -- Ada.Tags RE_Dispatch_Table, -- Ada.Tags + RE_Dispatch_Table_Wrapper, -- Ada.Tags RE_Displace, -- Ada.Tags - RE_DT_Entry_Size, -- Ada.Tags - RE_DT_Min_Prologue_Size, -- Ada.Tags - RE_DT_Prologue_Size, -- Ada.Tags + RE_DT, -- Ada.Tags + RE_DT_Predef_Prims_Offset, -- Ada.Tags RE_DT_Typeinfo_Ptr_Size, -- Ada.Tags RE_Expanded_Name, -- Ada.Tags RE_External_Tag, -- Ada.Tags + RE_HT_Link, -- Ada.Tags RO_TA_External_Tag, -- Ada.Tags RE_Get_Access_Level, -- Ada.Tags RE_Get_Entry_Index, -- Ada.Tags RE_Get_Offset_Index, -- Ada.Tags - RE_Get_Predefined_Prim_Op_Address, -- Ada.Tags - RE_Get_Prim_Op_Address, -- Ada.Tags RE_Get_Prim_Op_Kind, -- Ada.Tags - RE_Get_RC_Offset, -- Ada.Tags - RE_Get_Remotely_Callable, -- Ada.Tags RE_Get_Tagged_Kind, -- Ada.Tags RE_Idepth, -- Ada.Tags + RE_Iface_Tag, -- Ada.Tags RE_Ifaces_Table, -- Ada.Tags - RE_Ifaces_Table_Ptr, -- Ada.Tags + RE_Interfaces_Table, -- Ada.Tags RE_Interface_Data, -- Ada.Tags - RE_Interface_Data_Ptr, -- Ada.Tags RE_Interface_Tag, -- Ada.Tags RE_IW_Membership, -- Ada.Tags RE_Nb_Ifaces, -- Ada.Tags + RE_No_Dispatch_Table_Wrapper, -- Ada.Tags + RE_NDT_Prims_Ptr, -- Ada.Tags + RE_NDT_TSD, -- Ada.Tags + RE_Num_Prims, -- Ada.Tags RE_Object_Specific_Data, -- Ada.Tags RE_Offset_To_Top, -- Ada.Tags - RE_Type_Specific_Data, -- Ada.Tags + RE_Offset_To_Top_Function_Ptr, -- Ada.Tags + RE_OSD_Table, -- Ada.Tags + RE_OSD_Num_Prims, -- Ada.Tags RE_POK_Function, -- Ada.Tags RE_POK_Procedure, -- Ada.Tags RE_POK_Protected_Entry, -- Ada.Tags @@ -529,34 +534,29 @@ package Rtsfind is RE_POK_Task_Entry, -- Ada.Tags RE_POK_Task_Function, -- Ada.Tags RE_POK_Task_Procedure, -- Ada.Tags + RE_Predef_Prims, -- Ada.Tags + RE_Predef_Prims_Table_Ptr, -- Ada.Tags RE_Prim_Op_Kind, -- Ada.Tags - RE_Primary_DT, -- Ada.Tags RE_Prims_Ptr, -- Ada.Tags - RE_Register_Interface_Tag, -- Ada.Tags + RE_Primary_DT, -- Ada.Tags + RE_Signature, -- Ada.Tags + RE_SSD, -- Ada.Tags + RE_TSD, -- Ada.Tags + RE_Type_Specific_Data, -- Ada.Tags RE_Register_Tag, -- Ada.Tags - RE_Remotely_Callable, -- Ada.Tags + RE_Transportable, -- Ada.Tags RE_RC_Offset, -- Ada.Tags RE_Secondary_DT, -- Ada.Tags RE_Select_Specific_Data, -- Ada.Tags - RE_Set_Access_Level, -- Ada.Tags RE_Set_Entry_Index, -- Ada.Tags - RE_Set_Expanded_Name, -- Ada.Tags - RE_Set_Num_Prim_Ops, -- Ada.Tags - RE_Set_Offset_Index, -- Ada.Tags RE_Set_Offset_To_Top, -- Ada.Tags - RE_Set_OSD, -- Ada.Tags - RE_Set_Predefined_Prim_Op_Address, -- Ada.Tags - RE_Set_Prim_Op_Address, -- Ada.Tags RE_Set_Prim_Op_Kind, -- Ada.Tags - RE_Set_RC_Offset, -- Ada.Tags - RE_Set_Remotely_Callable, -- Ada.Tags - RE_Set_SSD, -- Ada.Tags - RE_Set_Signature, -- Ada.Tags - RE_Set_Tagged_Kind, -- Ada.Tags - RE_Set_TSD, -- Ada.Tags + RE_Static_Offset_To_Top, -- Ada.Tags RE_Tag, -- Ada.Tags RE_Tag_Error, -- Ada.Tags + RE_Tag_Kind, -- Ada.Tags RE_Tag_Ptr, -- Ada.Tags + RE_Tag_Table, -- Ada.Tags RE_Tags_Table, -- Ada.Tags RE_Tagged_Kind, -- Ada.Tags RE_Type_Specific_Data_Ptr, -- Ada.Tags @@ -599,6 +599,8 @@ package Rtsfind is RE_Null_Address, -- System RE_Priority, -- System + RE_Address_Image, -- System.Address_Image + RE_Add_With_Ovflo_Check, -- System.Arith_64 RE_Double_Divide, -- System.Arith_64 RE_Multiply_With_Ovflo_Check, -- System.Arith_64 @@ -607,6 +609,7 @@ package Rtsfind is RE_Create_AST_Handler, -- System.AST_Handling + RE_Assert_Failure, -- System.Assertions RE_Raise_Assert_Failure, -- System.Assertions RE_AST_Handler, -- System.Aux_DEC @@ -663,6 +666,8 @@ package Rtsfind is RE_Register_Exception, -- System.Exception_Table + RE_Local_Raise, -- System.Exceptions + RE_Exn_Integer, -- System.Exn_Int RE_Exn_Long_Long_Float, -- System.Exn_LLF @@ -1231,6 +1236,7 @@ package Rtsfind is RE_Storage_Offset, -- System.Storage_Elements RE_Storage_Array, -- System.Storage_Elements RE_To_Address, -- System.Storage_Elements + RE_Dummy_Communication_Block, -- System.Storage_Elements RE_Root_Storage_Pool, -- System.Storage_Pools RE_Allocate_Any, -- System_Storage_Pools, @@ -1333,11 +1339,6 @@ package Rtsfind is RE_Get_GNAT_Exception, -- System.Soft_Links RE_Update_Exception, -- System.Soft_Links - RE_ATSD, -- System.Threads - RE_Thread_Body_Enter, -- System.Threads - RE_Thread_Body_Exceptional_Exit, -- System.Threads - RE_Thread_Body_Leave, -- System.Threads - RE_Bits_1, -- System.Unsigned_Types RE_Bits_2, -- System.Unsigned_Types RE_Bits_4, -- System.Unsigned_Types @@ -1563,11 +1564,11 @@ package Rtsfind is RE_Exception_Message => Ada_Exceptions, RE_Exception_Name_Simple => Ada_Exceptions, RE_Exception_Occurrence => Ada_Exceptions, - RE_Local_Raise => Ada_Exceptions, RE_Null_Occurrence => Ada_Exceptions, RE_Poll => Ada_Exceptions, RE_Raise_Exception => Ada_Exceptions, RE_Raise_Exception_Always => Ada_Exceptions, + RE_Raise_From_Controlled_Operation => Ada_Exceptions, RE_Reraise_Occurrence => Ada_Exceptions, RE_Reraise_Occurrence_Always => Ada_Exceptions, RE_Reraise_Occurrence_No_Defer => Ada_Exceptions, @@ -1592,42 +1593,45 @@ package Rtsfind is RE_Stream_Access => Ada_Streams_Stream_IO, - RE_Abstract_Interface => Ada_Tags, RE_Access_Level => Ada_Tags, + RE_Address_Array => Ada_Tags, RE_Addr_Ptr => Ada_Tags, RE_Base_Address => Ada_Tags, RE_Cstring_Ptr => Ada_Tags, RE_Default_Prim_Op_Count => Ada_Tags, RE_Descendant_Tag => Ada_Tags, RE_Dispatch_Table => Ada_Tags, + RE_Dispatch_Table_Wrapper => Ada_Tags, RE_Displace => Ada_Tags, - RE_DT_Entry_Size => Ada_Tags, - RE_DT_Min_Prologue_Size => Ada_Tags, - RE_DT_Prologue_Size => Ada_Tags, + RE_DT => Ada_Tags, + RE_DT_Predef_Prims_Offset => Ada_Tags, RE_DT_Typeinfo_Ptr_Size => Ada_Tags, RE_Expanded_Name => Ada_Tags, RE_External_Tag => Ada_Tags, + RE_HT_Link => Ada_Tags, RO_TA_External_Tag => Ada_Tags, RE_Get_Access_Level => Ada_Tags, RE_Get_Entry_Index => Ada_Tags, RE_Get_Offset_Index => Ada_Tags, - RE_Get_Predefined_Prim_Op_Address => Ada_Tags, - RE_Get_Prim_Op_Address => Ada_Tags, RE_Get_Prim_Op_Kind => Ada_Tags, - RE_Get_RC_Offset => Ada_Tags, - RE_Get_Remotely_Callable => Ada_Tags, RE_Get_Tagged_Kind => Ada_Tags, RE_Idepth => Ada_Tags, + RE_Iface_Tag => Ada_Tags, RE_Ifaces_Table => Ada_Tags, - RE_Ifaces_Table_Ptr => Ada_Tags, + RE_Interfaces_Table => Ada_Tags, RE_Interface_Data => Ada_Tags, - RE_Interface_Data_Ptr => Ada_Tags, RE_Interface_Tag => Ada_Tags, RE_IW_Membership => Ada_Tags, RE_Nb_Ifaces => Ada_Tags, + RE_No_Dispatch_Table_Wrapper => Ada_Tags, + RE_NDT_Prims_Ptr => Ada_Tags, + RE_NDT_TSD => Ada_Tags, + RE_Num_Prims => Ada_Tags, RE_Object_Specific_Data => Ada_Tags, RE_Offset_To_Top => Ada_Tags, - RE_Type_Specific_Data => Ada_Tags, + RE_Offset_To_Top_Function_Ptr => Ada_Tags, + RE_OSD_Table => Ada_Tags, + RE_OSD_Num_Prims => Ada_Tags, RE_POK_Function => Ada_Tags, RE_POK_Procedure => Ada_Tags, RE_POK_Protected_Entry => Ada_Tags, @@ -1636,34 +1640,29 @@ package Rtsfind is RE_POK_Task_Entry => Ada_Tags, RE_POK_Task_Function => Ada_Tags, RE_POK_Task_Procedure => Ada_Tags, + RE_Predef_Prims => Ada_Tags, + RE_Predef_Prims_Table_Ptr => Ada_Tags, RE_Prim_Op_Kind => Ada_Tags, - RE_Primary_DT => Ada_Tags, RE_Prims_Ptr => Ada_Tags, - RE_Register_Interface_Tag => Ada_Tags, + RE_Primary_DT => Ada_Tags, + RE_Signature => Ada_Tags, + RE_SSD => Ada_Tags, + RE_TSD => Ada_Tags, + RE_Type_Specific_Data => Ada_Tags, RE_Register_Tag => Ada_Tags, - RE_Remotely_Callable => Ada_Tags, + RE_Transportable => Ada_Tags, RE_RC_Offset => Ada_Tags, RE_Secondary_DT => Ada_Tags, RE_Select_Specific_Data => Ada_Tags, - RE_Set_Access_Level => Ada_Tags, RE_Set_Entry_Index => Ada_Tags, - RE_Set_Expanded_Name => Ada_Tags, - RE_Set_Num_Prim_Ops => Ada_Tags, - RE_Set_Offset_Index => Ada_Tags, RE_Set_Offset_To_Top => Ada_Tags, - RE_Set_OSD => Ada_Tags, - RE_Set_Predefined_Prim_Op_Address => Ada_Tags, - RE_Set_Prim_Op_Address => Ada_Tags, RE_Set_Prim_Op_Kind => Ada_Tags, - RE_Set_RC_Offset => Ada_Tags, - RE_Set_Remotely_Callable => Ada_Tags, - RE_Set_SSD => Ada_Tags, - RE_Set_Signature => Ada_Tags, - RE_Set_Tagged_Kind => Ada_Tags, - RE_Set_TSD => Ada_Tags, + RE_Static_Offset_To_Top => Ada_Tags, RE_Tag => Ada_Tags, RE_Tag_Error => Ada_Tags, + RE_Tag_Kind => Ada_Tags, RE_Tag_Ptr => Ada_Tags, + RE_Tag_Table => Ada_Tags, RE_Tags_Table => Ada_Tags, RE_Tagged_Kind => Ada_Tags, RE_Type_Specific_Data_Ptr => Ada_Tags, @@ -1704,6 +1703,8 @@ package Rtsfind is RE_Null_Address => System, RE_Priority => System, + RE_Address_Image => System_Address_Image, + RE_Add_With_Ovflo_Check => System_Arith_64, RE_Double_Divide => System_Arith_64, RE_Multiply_With_Ovflo_Check => System_Arith_64, @@ -1712,6 +1713,7 @@ package Rtsfind is RE_Create_AST_Handler => System_AST_Handling, + RE_Assert_Failure => System_Assertions, RE_Raise_Assert_Failure => System_Assertions, RE_AST_Handler => System_Aux_DEC, @@ -1768,6 +1770,8 @@ package Rtsfind is RE_Register_Exception => System_Exception_Table, + RE_Local_Raise => System_Exceptions, + RE_Exn_Integer => System_Exn_Int, RE_Exn_Long_Long_Float => System_Exn_LLF, @@ -2336,6 +2340,7 @@ package Rtsfind is RE_Storage_Offset => System_Storage_Elements, RE_Storage_Array => System_Storage_Elements, RE_To_Address => System_Storage_Elements, + RE_Dummy_Communication_Block => System_Storage_Elements, RE_Root_Storage_Pool => System_Storage_Pools, RE_Allocate_Any => System_Storage_Pools, @@ -2438,11 +2443,6 @@ package Rtsfind is RE_Get_GNAT_Exception => System_Soft_Links, RE_Update_Exception => System_Soft_Links, - RE_ATSD => System_Threads, - RE_Thread_Body_Enter => System_Threads, - RE_Thread_Body_Exceptional_Exit => System_Threads, - RE_Thread_Body_Leave => System_Threads, - RE_Bits_1 => System_Unsigned_Types, RE_Bits_2 => System_Unsigned_Types, RE_Bits_4 => System_Unsigned_Types, @@ -2808,9 +2808,9 @@ package Rtsfind is -- construct. function RTE_Available (E : RE_Id) return Boolean; - -- Returns true if a call to RTE will succeed without raising an - -- exception and without generating an error message, i.e. if the - -- call will obtain the desired entity without any problems. + -- Returns true if a call to RTE will succeed without raising an exception + -- and without generating an error message, i.e. if the call will obtain + -- the desired entity without any problems. function RTE_Record_Component (E : RE_Id) return Entity_Id; -- Given the entity defined in the above tables, as identified by the