diff options
Diffstat (limited to 'gcc/ada/exp_disp.adb')
-rw-r--r-- | gcc/ada/exp_disp.adb | 682 |
1 files changed, 447 insertions, 235 deletions
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index 20e769e1804..e3daf07bfc4 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -309,11 +309,11 @@ package body Exp_Disp is Get_Access_Level => RE_Get_Access_Level, Get_Entry_Index => RE_Get_Entry_Index, Get_External_Tag => RE_Get_External_Tag, - Get_Offset_Index => RE_Get_Offset_Index, Get_Prim_Op_Address => RE_Get_Prim_Op_Address, Get_Prim_Op_Kind => RE_Get_Prim_Op_Kind, Get_RC_Offset => RE_Get_RC_Offset, Get_Remotely_Callable => RE_Get_Remotely_Callable, + Get_Tagged_Kind => RE_Get_Tagged_Kind, Inherit_DT => RE_Inherit_DT, Inherit_TSD => RE_Inherit_TSD, Register_Interface_Tag => RE_Register_Interface_Tag, @@ -322,6 +322,7 @@ package body Exp_Disp is Set_Entry_Index => RE_Set_Entry_Index, Set_Expanded_Name => RE_Set_Expanded_Name, Set_External_Tag => RE_Set_External_Tag, + Set_Interface_Table => RE_Set_Interface_Table, Set_Offset_Index => RE_Set_Offset_Index, Set_OSD => RE_Set_OSD, Set_Prim_Op_Address => RE_Set_Prim_Op_Address, @@ -330,6 +331,7 @@ package body Exp_Disp is Set_Remotely_Callable => RE_Set_Remotely_Callable, Set_SSD => RE_Set_SSD, Set_TSD => RE_Set_TSD, + Set_Tagged_Kind => RE_Set_Tagged_Kind, TSD_Entry_Size => RE_TSD_Entry_Size, TSD_Prologue_Size => RE_TSD_Prologue_Size); @@ -341,11 +343,11 @@ package body Exp_Disp is Get_Access_Level => False, Get_Entry_Index => False, Get_External_Tag => False, - Get_Offset_Index => False, Get_Prim_Op_Address => False, Get_Prim_Op_Kind => False, - Get_Remotely_Callable => False, Get_RC_Offset => False, + Get_Remotely_Callable => False, + Get_Tagged_Kind => False, Inherit_DT => True, Inherit_TSD => True, Register_Interface_Tag => True, @@ -354,6 +356,7 @@ package body Exp_Disp is Set_Entry_Index => True, Set_Expanded_Name => True, Set_External_Tag => True, + Set_Interface_Table => True, Set_Offset_Index => True, Set_OSD => True, Set_Prim_Op_Address => True, @@ -362,6 +365,7 @@ package body Exp_Disp is Set_Remotely_Callable => True, Set_SSD => True, Set_TSD => True, + Set_Tagged_Kind => True, TSD_Entry_Size => False, TSD_Prologue_Size => False); @@ -373,19 +377,20 @@ package body Exp_Disp is Get_Access_Level => 1, Get_Entry_Index => 2, Get_External_Tag => 1, - Get_Offset_Index => 2, Get_Prim_Op_Address => 2, Get_Prim_Op_Kind => 2, Get_RC_Offset => 1, Get_Remotely_Callable => 1, + Get_Tagged_Kind => 1, Inherit_DT => 3, Inherit_TSD => 2, - Register_Interface_Tag => 2, + Register_Interface_Tag => 3, Register_Tag => 1, Set_Access_Level => 2, Set_Entry_Index => 3, Set_Expanded_Name => 2, Set_External_Tag => 2, + Set_Interface_Table => 2, Set_Offset_Index => 3, Set_OSD => 2, Set_Prim_Op_Address => 3, @@ -394,6 +399,7 @@ package body Exp_Disp is Set_Remotely_Callable => 2, Set_SSD => 2, Set_TSD => 2, + Set_Tagged_Kind => 2, TSD_Entry_Size => 0, TSD_Prologue_Size => 0); @@ -414,9 +420,13 @@ package body Exp_Disp is (Prim : Entity_Id; Typ : Entity_Id) return Node_Id; -- Ada 2005 (AI-345): Determine the primitive operation kind of Prim - -- according to its type Typ. Return a reference to an RTE Prim_Op_Kind + -- according to its type Typ. Return a reference to an RE_Prim_Op_Kind -- enumeration value. + function Tagged_Kind (T : Entity_Id) return Node_Id; + -- Ada 2005 (AI-345): Determine the tagged kind of T and return a reference + -- to an RE_Tagged_Kind enumeration value. + ---------------------------- -- Collect_All_Interfaces -- ---------------------------- @@ -426,7 +436,7 @@ package body Exp_Disp is procedure Add_Interface (Iface : Entity_Id); -- Add the interface it if is not already in the list - procedure Collect (Typ : Entity_Id); + procedure Collect (Typ : Entity_Id); -- Subsidiary subprogram used to traverse the whole list -- of directly and indirectly implemented interfaces @@ -453,34 +463,34 @@ package body Exp_Disp is ------------- procedure Collect (Typ : Entity_Id) is - Nod : constant Node_Id := Type_Definition (Parent (Typ)); + Ancestor : Entity_Id; Id : Node_Id; Iface : Entity_Id; - Ancestor : Entity_Id; + Nod : Node_Id; begin + if Ekind (Typ) = E_Record_Type_With_Private then + Nod := Type_Definition (Parent (Full_View (Typ))); + else + Nod := Type_Definition (Parent (Typ)); + end if; + pragma Assert (False or else Nkind (Nod) = N_Derived_Type_Definition or else Nkind (Nod) = N_Record_Definition); - if Nkind (Nod) = N_Record_Definition then - return; - end if; - -- Include the ancestor if we are generating the whole list -- of interfaces. This is used to know the size of the table -- that stores the tag of all the ancestor interfaces. Ancestor := Etype (Typ); - if Is_Interface (Ancestor) then - Add_Interface (Ancestor); + if Ancestor /= Typ then + Collect (Ancestor); end if; - if Ancestor /= Typ - and then Ekind (Ancestor) /= E_Record_Type_With_Private - then - Collect (Ancestor); + if Is_Interface (Ancestor) then + Add_Interface (Ancestor); end if; -- Traverse the graph of ancestor interfaces @@ -1008,7 +1018,10 @@ package body Exp_Disp is -- Expand_Interface_Conversion -- --------------------------------- - procedure Expand_Interface_Conversion (N : Node_Id) is + procedure Expand_Interface_Conversion + (N : Node_Id; + Is_Static : Boolean := True) + is Loc : constant Source_Ptr := Sloc (N); Operand : constant Node_Id := Expression (N); Operand_Typ : Entity_Id := Etype (Operand); @@ -1046,6 +1059,40 @@ package body Exp_Disp is pragma Assert (not Is_Class_Wide_Type (Iface_Typ) and then Is_Interface (Iface_Typ)); + if not Is_Static then + Rewrite (N, + Make_Function_Call (Loc, + Name => New_Reference_To (RTE (RE_Displace), Loc), + Parameter_Associations => New_List ( + Make_Attribute_Reference (Loc, + Prefix => Relocate_Node (Expression (N)), + Attribute_Name => Name_Address), + New_Occurrence_Of + (Node (First_Elmt (Access_Disp_Table (Iface_Typ))), + Loc)))); + + Analyze (N); + + -- Change the type of the data returned by IW_Convert to + -- indicate that this is a dispatching call. + + declare + New_Itype : Entity_Id; + + begin + New_Itype := Create_Itype (E_Anonymous_Access_Type, N); + Set_Etype (New_Itype, New_Itype); + Init_Size_Align (New_Itype); + Set_Directly_Designated_Type (New_Itype, + Class_Wide_Type (Iface_Typ)); + + Rewrite (N, Unchecked_Convert_To (New_Itype, + Relocate_Node (N))); + end; + + return; + end if; + Iface_Tag := Find_Interface_Tag (Operand_Typ, Iface_Typ); pragma Assert (Iface_Tag /= Empty); @@ -1359,8 +1406,7 @@ package body Exp_Disp is function Expand_Interface_Thunk (N : Node_Id; Thunk_Alias : Entity_Id; - Thunk_Id : Entity_Id; - Thunk_Tag : Entity_Id) return Node_Id + Thunk_Id : Entity_Id) return Node_Id is Loc : constant Source_Ptr := Sloc (N); Actuals : constant List_Id := New_List; @@ -1417,7 +1463,7 @@ package body Exp_Disp is -- type T is access all <<type of the first formal>> -- S1 := Storage_Offset!(First_formal) - -- - Storage_Offset!(First_Formal.Thunk_Tag'Position) + -- - Offset_To_Top (First_Formal.Tag) -- ... and the first actual of the call is generated as T!(S1) @@ -1452,17 +1498,15 @@ package body Exp_Disp is New_Reference_To (Defining_Identifier (First (Formals)), Loc)), Right_Opnd => - Unchecked_Convert_To - (RTE (RE_Storage_Offset), - Make_Attribute_Reference (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => - New_Reference_To - (Defining_Identifier (First (Formals)), Loc), - Selector_Name => - New_Occurrence_Of (Thunk_Tag, Loc)), - Attribute_Name => Name_Position)))); + Make_Function_Call (Loc, + Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc), + Parameter_Associations => New_List ( + Make_Selected_Component (Loc, + Prefix => New_Reference_To + (Defining_Identifier (First (Formals)), + Loc), + Selector_Name => Make_Identifier (Loc, + Name_uTag)))))); Append_To (Decl, Decl_2); Append_To (Decl, Decl_1); @@ -1474,14 +1518,11 @@ package body Exp_Disp is (Defining_Identifier (Decl_2), New_Reference_To (Defining_Identifier (Decl_1), Loc))); - -- Side note: The reverse order of declarations is just to ensure - -- that the call to RE_Print is correct. - else -- Generate: - -- + -- S1 := Storage_Offset!(First_formal'Address) - -- - Storage_Offset!(First_Formal.Thunk_Tag'Position) + -- - Offset_To_Top (First_Formal.Tag) -- S2 := Tag_Ptr!(S3) Decl_1 := @@ -1502,17 +1543,15 @@ package body Exp_Disp is (Defining_Identifier (First (Formals)), Loc), Attribute_Name => Name_Address)), Right_Opnd => - Unchecked_Convert_To - (RTE (RE_Storage_Offset), - Make_Attribute_Reference (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => - New_Reference_To - (Defining_Identifier (First (Formals)), Loc), - Selector_Name => - New_Occurrence_Of (Thunk_Tag, Loc)), - Attribute_Name => Name_Position)))); + Make_Function_Call (Loc, + Name => New_Reference_To (RTE (RE_Offset_To_Top), Loc), + Parameter_Associations => New_List ( + Make_Selected_Component (Loc, + Prefix => New_Reference_To + (Defining_Identifier (First (Formals)), + Loc), + Selector_Name => Make_Identifier (Loc, + Name_uTag)))))); Decl_2 := Make_Object_Declaration (Loc, @@ -1726,6 +1765,8 @@ package body Exp_Disp is Stmts : constant List_Id := New_List; begin + -- Null body is generated for interface types + if Is_Interface (Typ) then return Make_Subprogram_Body (Loc, @@ -1738,16 +1779,13 @@ package body Exp_Disp is New_List (Make_Null_Statement (Loc)))); end if; - if Is_Concurrent_Record_Type (Typ) then - Conc_Typ := Corresponding_Concurrent_Type (Typ); - end if; - DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); - if Present (Conc_Typ) then + if Is_Concurrent_Record_Type (Typ) then + Conc_Typ := Corresponding_Concurrent_Type (Typ); -- Generate: - -- I : Integer := get_entry_index (tag! (<type>VP), S); + -- I : Integer := Get_Entry_Index (tag! (<type>VP), S); -- where I will be used to capture the entry index of the primitive -- wrapper at position S. @@ -1847,12 +1885,6 @@ package body Exp_Disp is RTE (RE_Asynchronous_Call), Loc), Make_Identifier (Loc, Name_uF)))); -- status flag end if; - - -- Implementation for limited tagged types - - else - Append_To (Stmts, - Make_Raise_Program_Error (Loc, Reason => PE_Explicit_Raise)); end if; return @@ -1914,6 +1946,8 @@ package body Exp_Disp is Stmts : constant List_Id := New_List; begin + -- Null body is generated for interface types + if Is_Interface (Typ) then return Make_Subprogram_Body (Loc, @@ -1926,13 +1960,10 @@ package body Exp_Disp is New_List (Make_Null_Statement (Loc)))); end if; - if Is_Concurrent_Record_Type (Typ) then - Conc_Typ := Corresponding_Concurrent_Type (Typ); - end if; - DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); - if Present (Conc_Typ) then + if Is_Concurrent_Record_Type (Typ) then + Conc_Typ := Corresponding_Concurrent_Type (Typ); -- Generate: -- I : Integer; @@ -1946,22 +1977,20 @@ package body Exp_Disp is Make_Defining_Identifier (Loc, Name_uI), Object_Definition => New_Reference_To (Standard_Integer, Loc))); - end if; - -- Generate: - -- C := get_prim_op_kind (tag! (<type>VP), S); - - -- if C = POK_Procedure - -- or else C = POK_Protected_Procedure - -- or else C = POK_Task_Procedure; - -- then - -- F := True; - -- return; - -- end if; + -- Generate: + -- C := Get_Prim_Op_Kind (tag! (<type>VP), S); - SEU.Build_Common_Dispatching_Select_Statements (Loc, Typ, DT_Ptr, Stmts); + -- if C = POK_Procedure + -- or else C = POK_Protected_Procedure + -- or else C = POK_Task_Procedure; + -- then + -- F := True; + -- return; + -- end if; - if Present (Conc_Typ) then + SEU.Build_Common_Dispatching_Select_Statements + (Loc, Typ, DT_Ptr, Stmts); -- Generate: -- Bnn : Communication_Block; @@ -1979,7 +2008,7 @@ package body Exp_Disp is New_Reference_To (RTE (RE_Communication_Block), Loc))); -- Generate: - -- I := get_entry_index (tag! (<type>VP), S); + -- I := Get_Entry_Index (tag! (<type>VP), S); -- I is the entry index and S is the dispatch table slot @@ -2097,12 +2126,6 @@ package body Exp_Disp is RTE (RE_Conditional_Call), Loc), Make_Identifier (Loc, Name_uF)))); -- status flag end if; - - -- Implementation for limited tagged types - - else - Append_To (Stmts, - Make_Raise_Program_Error (Loc, Reason => PE_Explicit_Raise)); end if; return @@ -2318,6 +2341,8 @@ package body Exp_Disp is Stmts : constant List_Id := New_List; begin + -- Null body is generated for interface types + if Is_Interface (Typ) then return Make_Subprogram_Body (Loc, @@ -2330,13 +2355,10 @@ package body Exp_Disp is New_List (Make_Null_Statement (Loc)))); end if; - if Is_Concurrent_Record_Type (Typ) then - Conc_Typ := Corresponding_Concurrent_Type (Typ); - end if; - DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); - if Present (Conc_Typ) then + if Is_Concurrent_Record_Type (Typ) then + Conc_Typ := Corresponding_Concurrent_Type (Typ); -- Generate: -- I : Integer; @@ -2350,25 +2372,23 @@ package body Exp_Disp is Make_Defining_Identifier (Loc, Name_uI), Object_Definition => New_Reference_To (Standard_Integer, Loc))); - end if; - - -- Generate: - -- C := get_prim_op_kind (tag! (<type>VP), S); - -- if C = POK_Procedure - -- or else C = POK_Protected_Procedure - -- or else C = POK_Task_Procedure; - -- then - -- F := True; - -- return; - -- end if; + -- Generate: + -- C := Get_Prim_Op_Kind (tag! (<type>VP), S); - SEU.Build_Common_Dispatching_Select_Statements (Loc, Typ, DT_Ptr, Stmts); + -- if C = POK_Procedure + -- or else C = POK_Protected_Procedure + -- or else C = POK_Task_Procedure; + -- then + -- F := True; + -- return; + -- end if; - if Present (Conc_Typ) then + SEU.Build_Common_Dispatching_Select_Statements + (Loc, Typ, DT_Ptr, Stmts); -- Generate: - -- I := get_entry_index (tag! (<type>VP), S); + -- I := Get_Entry_Index (tag! (<type>VP), S); -- I is the entry index and S is the dispatch table slot @@ -2469,12 +2489,6 @@ package body Exp_Disp is Make_Identifier (Loc, Name_uM), -- delay mode Make_Identifier (Loc, Name_uF)))); -- status flag end if; - - -- Implementation for limited tagged types - - else - Append_To (Stmts, - Make_Raise_Program_Error (Loc, Reason => PE_Explicit_Raise)); end if; return @@ -2554,6 +2568,7 @@ package body Exp_Disp is 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'); + 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); @@ -2561,17 +2576,21 @@ package body Exp_Disp is 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); - - Generalized_Tag : constant Entity_Id := RTE (RE_Tag); - I_Depth : Int; - Size_Expr_Node : Node_Id; - Old_Tag1 : Node_Id; - Old_Tag2 : Node_Id; - Num_Ifaces : Int; - Nb_Prim : Int; - TSD_Num_Entries : Int; - Typ_Copy : constant Entity_Id := New_Copy (Typ); - AI : Elmt_Id; + ITable : Node_Id; + + Generalized_Tag : constant Entity_Id := RTE (RE_Tag); + AI : Elmt_Id; + I_Depth : Int; + Nb_Prim : Int; + Num_Ifaces : Int; + Old_Tag1 : Node_Id; + Old_Tag2 : Node_Id; + Parent_Num_Ifaces : Int; + Size_Expr_Node : Node_Id; + TSD_Num_Entries : Int; + + Ancestor_Copy : Entity_Id; + Typ_Copy : Entity_Id; begin if not RTE_Available (RE_Tag) then @@ -2579,27 +2598,44 @@ package body Exp_Disp is return New_List; end if; - -- Collect full list of directly and indirectly implemented interfaces - - Set_Parent (Typ_Copy, Parent (Typ)); - Set_Abstract_Interfaces (Typ_Copy, New_Elmt_List); - Collect_All_Interfaces (Typ_Copy); - -- Calculate the size of the DT and the TSD if Is_Interface (Typ) then -- Abstract interfaces need neither the DT nor the ancestors table. -- We reserve a single entry for its DT because at run-time the - -- pointer to this dummy DT is the tag of this abstract interface - -- type. + -- pointer to this dummy DT will be used as the tag of this abstract + -- interface type. Nb_Prim := 1; TSD_Num_Entries := 0; + Num_Ifaces := 0; else - -- Calculate the number of entries for the table of interfaces + -- Count the number of interfaces implemented by the ancestors + + Parent_Num_Ifaces := 0; + Num_Ifaces := 0; + + if Typ /= Etype (Typ) then + Ancestor_Copy := New_Copy (Etype (Typ)); + Set_Parent (Ancestor_Copy, Parent (Etype (Typ))); + Set_Abstract_Interfaces (Ancestor_Copy, New_Elmt_List); + Collect_All_Interfaces (Ancestor_Copy); + + AI := First_Elmt (Abstract_Interfaces (Ancestor_Copy)); + while Present (AI) loop + Parent_Num_Ifaces := Parent_Num_Ifaces + 1; + Next_Elmt (AI); + end loop; + end if; + + -- Count the number of additional interfaces implemented by Typ + + Typ_Copy := New_Copy (Typ); + Set_Parent (Typ_Copy, Parent (Typ)); + Set_Abstract_Interfaces (Typ_Copy, New_Elmt_List); + Collect_All_Interfaces (Typ_Copy); - Num_Ifaces := 0; AI := First_Elmt (Abstract_Interfaces (Typ_Copy)); while Present (AI) loop Num_Ifaces := Num_Ifaces + 1; @@ -2630,7 +2666,7 @@ package body Exp_Disp is end loop; end; - TSD_Num_Entries := I_Depth + Num_Ifaces + 1; + TSD_Num_Entries := I_Depth + 1; Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ))); -- If the number of primitives of Typ is less that the number of @@ -2650,6 +2686,16 @@ package body Exp_Disp is Set_Ekind (DT_Ptr, E_Variable); Set_Is_Statically_Allocated (DT_Ptr); + if not Is_Interface (Typ) + and then Num_Ifaces > 0 + then + Name_ITable := New_External_Name (Tname, 'I'); + ITable := Make_Defining_Identifier (Loc, Name_ITable); + + Set_Ekind (ITable, E_Variable); + Set_Is_Statically_Allocated (ITable); + end if; + Set_Ekind (SSD, E_Variable); Set_Is_Statically_Allocated (SSD); @@ -2842,6 +2888,47 @@ package body Exp_Disp is Prefix => New_Reference_To (TSD, Loc), Attribute_Name => Name_Address)))); + -- Set the pointer to the Interfaces_Table (if any). Otherwise the + -- corresponding access component is set to null. + + if Is_Interface (Typ) then + null; + + elsif Num_Ifaces = 0 then + Append_To (Elab_Code, + Make_DT_Access_Action (Typ, + Action => Set_Interface_Table, + Args => New_List ( + New_Reference_To (DT_Ptr, Loc), -- DTptr + New_Reference_To (RTE (RE_Null_Address), Loc)))); -- null + + -- Generate the Interface_Table object and set the access + -- component if the TSD to it. + + else + 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)))))); + + Append_To (Elab_Code, + Make_DT_Access_Action (Typ, + Action => Set_Interface_Table, + Args => New_List ( + New_Reference_To (DT_Ptr, Loc), -- DTptr + Make_Attribute_Reference (Loc, -- Value + Prefix => New_Reference_To (ITable, Loc), + Attribute_Name => Name_Address)))); + end if; + -- Generate: -- Set_Num_Prim_Ops (T'Tag, Nb_Prim) @@ -2858,39 +2945,53 @@ package body Exp_Disp is and then not Is_Interface (Typ) and then not Is_Abstract (Typ) and then not Is_Controlled (Typ) - and then Implements_Interface ( - Typ => Typ, - Kind => Any_Limited_Interface, - Check_Parent => True) - and then (Nb_Prim - Default_Prim_Op_Count) > 0 then - -- Generate the Select Specific Data table for tagged types that - -- implement a synchronized interface. The size of the table is - -- constrained by the number of non-predefined primitive operations. - - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => SSD, - Aliased_Present => True, - 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 - Default_Prim_Op_Count)))))); - - -- Set the pointer to the Select Specific Data table in the TSD + -- Generate: + -- Set_Type_Kind (T'Tag, Type_Kind (Typ)); Append_To (Elab_Code, Make_DT_Access_Action (Typ, - Action => Set_SSD, + Action => Set_Tagged_Kind, 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)))); + 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 Is_Concurrent_Record_Type (Typ) + and then Implements_Interface ( + Typ => Typ, + Kind => Any_Limited_Interface, + Check_Parent => True) + and then (Nb_Prim - Default_Prim_Op_Count) > 0 + then + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => SSD, + Aliased_Present => True, + 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 - Default_Prim_Op_Count)))))); + + -- 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; end if; -- Generate: Exname : constant String := full_qualified_name (typ); @@ -3158,12 +3259,13 @@ package body Exp_Disp is end; -- Generate: - -- Set_Offset_To_Top (DT_Ptr, 0); + -- Set_Offset_To_Top (0, DT_Ptr, 0); 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), Make_Integer_Literal (Loc, Uint_0)))); end if; @@ -3222,31 +3324,82 @@ package body Exp_Disp is Then_Statements => Elab_Code)); -- Ada 2005 (AI-251): Register the tag of the interfaces into - -- the table of implemented interfaces and ... + -- the table of implemented interfaces. if not Is_Interface (Typ) - and then Present (Abstract_Interfaces (Typ_Copy)) - and then not Is_Empty_Elmt_List (Abstract_Interfaces (Typ_Copy)) + and then Num_Ifaces > 0 then - AI := First_Elmt (Abstract_Interfaces (Typ_Copy)); - while Present (AI) loop + declare + Position : Int; - -- Generate: - -- Register_Interface (DT_Ptr, Interface'Tag); + 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. - 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)))); + if Is_Interface (Etype (Typ)) then + Position := 1; - Next_Elmt (AI); - end loop; + AI := First_Elmt (Abstract_Interfaces (Ancestor_Copy)); + 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 + + if Present (Abstract_Interfaces (Typ_Copy)) then + AI := First_Elmt (Abstract_Interfaces (Typ_Copy)); + + -- 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); + + 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; + + pragma Assert (Position = Num_Ifaces + 1); + end; end if; return Result; @@ -3471,7 +3624,7 @@ package body Exp_Disp is Make_Index_Or_Discriminant_Constraint (Loc, Constraints => New_List ( Make_Integer_Literal (Loc, - Nb_Prim - Default_Prim_Op_Count)))))); + Nb_Prim - Default_Prim_Op_Count + 1)))))); -- Generate: -- Ada.Tags.Set_OSD (Iface_DT_Ptr, OSD); @@ -3480,63 +3633,12 @@ package body Exp_Disp is Make_DT_Access_Action (Typ, Action => Set_OSD, Args => New_List ( - New_Reference_To (Iface_DT_Ptr, Loc), + 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)))); - -- Offset table creation - - if not Is_Interface (Typ) - and then not Is_Abstract (Typ) - and then not Is_Controlled (Typ) - and then Implements_Interface - (Typ => Typ, - Kind => Any_Limited_Interface, - Check_Parent => True) - and then (Nb_Prim - Default_Prim_Op_Count) > 0 - 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)) then - Prim_Alias := Abstract_Interface_Alias (Prim); - end if; - - if Present (Prim_Alias) - and then Present (First_Entity (Prim_Alias)) - and then Etype (First_Entity (Prim_Alias)) = Iface - then - -- Generate: - -- Ada.Tags.Set_Offset_Index ( - -- Iface_DT_Ptr, secondary_DT_Pos, primary_DT_pos); - - Append_To (Result, - Make_DT_Access_Action (Iface, - Action => Set_Offset_Index, - Args => New_List ( - New_Reference_To (Iface_DT_Ptr, Loc), - Make_Integer_Literal (Loc, DT_Position (Prim_Alias)), - Make_Integer_Literal (Loc, DT_Position (Prim))))); - - Prim_Alias := Empty; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - end; - end if; - -- Generate: -- Set_Num_Prim_Ops (T'Tag, Nb_Prim) @@ -3548,6 +3650,73 @@ package body Exp_Disp is New_Reference_To (Iface_DT_Ptr, Loc)), Make_Integer_Literal (Loc, Nb_Prim)))); + if Ada_Version >= Ada_05 + and then not Is_Interface (Typ) + and then not Is_Abstract (Typ) + and then not Is_Controlled (Typ) + 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 Is_Concurrent_Record_Type (Typ) + and then Implements_Interface ( + Typ => Typ, + Kind => Any_Limited_Interface, + Check_Parent => True) + and then (Nb_Prim - Default_Prim_Op_Count) > 0 + 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)) then + Prim_Alias := Abstract_Interface_Alias (Prim); + end if; + + if Present (Prim_Alias) + and then Present (First_Entity (Prim_Alias)) + and then Etype (First_Entity (Prim_Alias)) = Iface + then + -- 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 (Prim))))); + + Prim_Alias := Empty; + end if; + + Next_Elmt (Prim_Elmt); + end loop; + end; + end if; + end if; end Make_Secondary_DT; ------------------------------------- @@ -4413,6 +4582,49 @@ package body Exp_Disp is end if; end Set_Default_Constructor; + ----------------- + -- Tagged_Kind -- + ----------------- + + function Tagged_Kind (T : Entity_Id) return Node_Id is + Conc_Typ : Entity_Id; + Loc : constant Source_Ptr := Sloc (T); + + begin + pragma Assert (Is_Tagged_Type (T)); + + -- Abstract kinds + + if Is_Abstract (T) then + if Is_Limited_Record (T) then + return New_Reference_To (RTE (RE_TK_Abstract_Limited_Tagged), Loc); + else + return New_Reference_To (RTE (RE_TK_Abstract_Tagged), Loc); + end if; + + -- Concurrent kinds + + elsif Is_Concurrent_Record_Type (T) then + Conc_Typ := Corresponding_Concurrent_Type (T); + + if Ekind (Conc_Typ) = E_Protected_Type then + return New_Reference_To (RTE (RE_TK_Protected), Loc); + else + pragma Assert (Ekind (Conc_Typ) = E_Task_Type); + return New_Reference_To (RTE (RE_TK_Task), Loc); + end if; + + -- Regular tagged kinds + + else + if Is_Limited_Record (T) then + return New_Reference_To (RTE (RE_TK_Limited_Tagged), Loc); + else + return New_Reference_To (RTE (RE_TK_Tagged), Loc); + end if; + end if; + end Tagged_Kind; + -------------- -- Write_DT -- -------------- |