diff options
Diffstat (limited to 'gcc-4.2.1/gcc/ada/exp_disp.adb')
-rw-r--r-- | gcc-4.2.1/gcc/ada/exp_disp.adb | 4858 |
1 files changed, 0 insertions, 4858 deletions
diff --git a/gcc-4.2.1/gcc/ada/exp_disp.adb b/gcc-4.2.1/gcc/ada/exp_disp.adb deleted file mode 100644 index a29714e97..000000000 --- a/gcc-4.2.1/gcc/ada/exp_disp.adb +++ /dev/null @@ -1,4858 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- E X P _ D I S P -- --- -- --- B o d y -- --- -- --- Copyright (C) 1992-2006, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- --- for more details. You should have received a copy of the GNU General -- --- Public License distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Atree; use Atree; -with Checks; use Checks; -with Debug; use Debug; -with Einfo; use Einfo; -with Elists; use Elists; -with Errout; use Errout; -with Exp_Ch7; use Exp_Ch7; -with Exp_Dbug; use Exp_Dbug; -with Exp_Tss; use Exp_Tss; -with Exp_Util; use Exp_Util; -with Itypes; use Itypes; -with Nlists; use Nlists; -with Nmake; use Nmake; -with Namet; use Namet; -with Opt; use Opt; -with Output; use Output; -with Restrict; use Restrict; -with Rident; use Rident; -with Rtsfind; use Rtsfind; -with Sem; use Sem; -with Sem_Disp; use Sem_Disp; -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 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! (<type>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 := - (CW_Membership => RE_CW_Membership, - IW_Membership => RE_IW_Membership, - DT_Entry_Size => RE_DT_Entry_Size, - DT_Prologue_Size => RE_DT_Prologue_Size, - Get_Access_Level => RE_Get_Access_Level, - Get_Entry_Index => RE_Get_Entry_Index, - Get_External_Tag => RE_Get_External_Tag, - Get_Predefined_Prim_Op_Address => RE_Get_Predefined_Prim_Op_Address, - 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, - Register_Tag => RE_Register_Tag, - Set_Access_Level => RE_Set_Access_Level, - 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_Predefined_Prim_Op_Address => RE_Set_Predefined_Prim_Op_Address, - Set_Prim_Op_Address => RE_Set_Prim_Op_Address, - Set_Prim_Op_Kind => RE_Set_Prim_Op_Kind, - Set_RC_Offset => RE_Set_RC_Offset, - Set_Remotely_Callable => RE_Set_Remotely_Callable, - Set_Signature => RE_Set_Signature, - 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); - - Action_Is_Proc : constant array (DT_Access_Action) of Boolean := - (CW_Membership => False, - IW_Membership => False, - DT_Entry_Size => False, - DT_Prologue_Size => False, - Get_Access_Level => False, - Get_Entry_Index => False, - Get_External_Tag => False, - Get_Predefined_Prim_Op_Address => False, - Get_Prim_Op_Address => False, - Get_Prim_Op_Kind => False, - Get_RC_Offset => False, - Get_Remotely_Callable => False, - Get_Tagged_Kind => False, - Inherit_DT => True, - Inherit_TSD => True, - Register_Interface_Tag => True, - Register_Tag => True, - Set_Access_Level => True, - Set_Entry_Index => True, - Set_Expanded_Name => True, - Set_External_Tag => True, - Set_Interface_Table => True, - Set_Offset_Index => True, - Set_OSD => True, - Set_Predefined_Prim_Op_Address => True, - Set_Prim_Op_Address => True, - Set_Prim_Op_Kind => True, - Set_RC_Offset => True, - Set_Remotely_Callable => True, - Set_Signature => True, - Set_SSD => True, - Set_TSD => True, - Set_Tagged_Kind => True, - TSD_Entry_Size => False, - TSD_Prologue_Size => False); - - Action_Nb_Arg : constant array (DT_Access_Action) of Int := - (CW_Membership => 2, - IW_Membership => 2, - DT_Entry_Size => 0, - DT_Prologue_Size => 0, - Get_Access_Level => 1, - Get_Entry_Index => 2, - Get_External_Tag => 1, - Get_Predefined_Prim_Op_Address => 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 => 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_Predefined_Prim_Op_Address => 3, - Set_Prim_Op_Address => 3, - Set_Prim_Op_Kind => 3, - Set_RC_Offset => 2, - Set_Remotely_Callable => 2, - Set_Signature => 2, - Set_SSD => 2, - Set_TSD => 2, - Set_Tagged_Kind => 2, - TSD_Entry_Size => 0, - TSD_Prologue_Size => 0); - - procedure Collect_All_Interfaces (T : Entity_Id); - -- Ada 2005 (AI-251): Collect the whole list of interfaces that are - -- directly or indirectly implemented by T. Used to compute the size - -- of the table of interfaces. - - function Default_Prim_Op_Position (E : Entity_Id) return Uint; - -- Ada 2005 (AI-251): Returns the fixed position in the dispatch table - -- of the default primitive operations. - - function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean; - -- Check if the type has a private view or if the public view appears - -- in the visible part of a package spec. - - function Prim_Op_Kind - (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 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 -- - ---------------------------- - - procedure Collect_All_Interfaces (T : Entity_Id) is - - procedure Add_Interface (Iface : Entity_Id); - -- Add the interface it if is not already in the list - - procedure Collect (Typ : Entity_Id); - -- Subsidiary subprogram used to traverse the whole list - -- of directly and indirectly implemented interfaces - - ------------------- - -- Add_Interface -- - ------------------- - - procedure Add_Interface (Iface : Entity_Id) is - Elmt : Elmt_Id; - - begin - Elmt := First_Elmt (Abstract_Interfaces (T)); - while Present (Elmt) and then Node (Elmt) /= Iface loop - Next_Elmt (Elmt); - end loop; - - if No (Elmt) then - Append_Elmt (Iface, Abstract_Interfaces (T)); - end if; - end Add_Interface; - - ------------- - -- Collect -- - ------------- - - procedure Collect (Typ : Entity_Id) is - Ancestor : Entity_Id; - Id : Node_Id; - Iface : 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); - - -- 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 Ancestor /= Typ then - Collect (Ancestor); - end if; - - if Is_Interface (Ancestor) then - Add_Interface (Ancestor); - end if; - - -- Traverse the graph of ancestor interfaces - - if Is_Non_Empty_List (Interface_List (Nod)) then - Id := First (Interface_List (Nod)); - while Present (Id) loop - Iface := Etype (Id); - - if Is_Interface (Iface) then - Add_Interface (Iface); - Collect (Iface); - end if; - - Next (Id); - end loop; - end if; - end Collect; - - -- Start of processing for Collect_All_Interfaces - - begin - Collect (T); - end Collect_All_Interfaces; - - ------------------------------ - -- Default_Prim_Op_Position -- - ------------------------------ - - function Default_Prim_Op_Position (E : Entity_Id) return Uint is - TSS_Name : TSS_Name_Type; - - begin - Get_Name_String (Chars (E)); - TSS_Name := - TSS_Name_Type - (Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len)); - - if Chars (E) = Name_uSize then - return Uint_1; - - elsif Chars (E) = Name_uAlignment then - return Uint_2; - - elsif TSS_Name = TSS_Stream_Read then - return Uint_3; - - elsif TSS_Name = TSS_Stream_Write then - return Uint_4; - - elsif TSS_Name = TSS_Stream_Input then - return Uint_5; - - elsif TSS_Name = TSS_Stream_Output then - return Uint_6; - - elsif Chars (E) = Name_Op_Eq then - return Uint_7; - - elsif Chars (E) = Name_uAssign then - return Uint_8; - - elsif TSS_Name = TSS_Deep_Adjust then - return Uint_9; - - elsif TSS_Name = TSS_Deep_Finalize then - return Uint_10; - - elsif Ada_Version >= Ada_05 then - if Chars (E) = Name_uDisp_Asynchronous_Select then - return Uint_11; - - elsif Chars (E) = Name_uDisp_Conditional_Select then - return Uint_12; - - elsif Chars (E) = Name_uDisp_Get_Prim_Op_Kind then - return Uint_13; - - elsif Chars (E) = Name_uDisp_Get_Task_Id then - return Uint_14; - - elsif Chars (E) = Name_uDisp_Timed_Select then - return Uint_15; - end if; - end if; - - raise Program_Error; - end Default_Prim_Op_Position; - - ----------------------------- - -- Expand_Dispatching_Call -- - ----------------------------- - - procedure Expand_Dispatching_Call (Call_Node : Node_Id) is - Loc : constant Source_Ptr := Sloc (Call_Node); - Call_Typ : constant Entity_Id := Etype (Call_Node); - - Ctrl_Arg : constant Node_Id := Controlling_Argument (Call_Node); - Param_List : constant List_Id := Parameter_Associations (Call_Node); - Subp : Entity_Id := Entity (Name (Call_Node)); - - CW_Typ : Entity_Id; - New_Call : Node_Id; - New_Call_Name : Node_Id; - New_Params : List_Id := No_List; - Param : Node_Id; - Res_Typ : Entity_Id; - Subp_Ptr_Typ : Entity_Id; - Subp_Typ : Entity_Id; - Typ : Entity_Id; - Eq_Prim_Op : Entity_Id := Empty; - Controlling_Tag : Node_Id; - - function New_Value (From : Node_Id) return Node_Id; - -- From is the original Expression. New_Value is equivalent to a call - -- to Duplicate_Subexpr with an explicit dereference when From is an - -- access parameter. - - function Controlling_Type (Subp : Entity_Id) return Entity_Id; - -- Returns the tagged type for which Subp is a primitive subprogram - - --------------- - -- New_Value -- - --------------- - - function New_Value (From : Node_Id) return Node_Id is - Res : constant Node_Id := Duplicate_Subexpr (From); - begin - if Is_Access_Type (Etype (From)) then - return Make_Explicit_Dereference (Sloc (From), Res); - else - return Res; - end if; - end New_Value; - - ---------------------- - -- Controlling_Type -- - ---------------------- - - function Controlling_Type (Subp : Entity_Id) return Entity_Id is - begin - if Ekind (Subp) = E_Function - and then Has_Controlling_Result (Subp) - then - return Base_Type (Etype (Subp)); - - else - declare - Formal : Entity_Id; - - begin - Formal := First_Formal (Subp); - while Present (Formal) loop - if Is_Controlling_Formal (Formal) then - if Is_Access_Type (Etype (Formal)) then - return Base_Type (Designated_Type (Etype (Formal))); - else - return Base_Type (Etype (Formal)); - end if; - end if; - - Next_Formal (Formal); - end loop; - end; - end if; - - -- Controlling type not found (should never happen) - - return Empty; - end Controlling_Type; - - -- Start of processing for Expand_Dispatching_Call - - begin - Check_Restriction (No_Dispatching_Calls, Call_Node); - - -- If this is an inherited operation that was overridden, the body - -- that is being called is its alias. - - if Present (Alias (Subp)) - and then Is_Inherited_Operation (Subp) - and then No (DTC_Entity (Subp)) - then - Subp := Alias (Subp); - end if; - - -- Expand_Dispatching_Call is called directly from the semantics, - -- so we need a check to see whether expansion is active before - -- proceeding. - - if not Expander_Active then - return; - end if; - - -- Definition of the class-wide type and the tagged type - - -- If the controlling argument is itself a tag rather than a tagged - -- object, then use the class-wide type associated with the subprogram's - -- controlling type. This case can occur when a call to an inherited - -- primitive has an actual that originated from a default parameter - -- given by a tag-indeterminate call and when there is no other - -- controlling argument providing the tag (AI-239 requires dispatching). - -- This capability of dispatching directly by tag is also needed by the - -- implementation of AI-260 (for the generic dispatching constructors). - - if Etype (Ctrl_Arg) = RTE (RE_Tag) - or else (RTE_Available (RE_Interface_Tag) - and then Etype (Ctrl_Arg) = RTE (RE_Interface_Tag)) - then - CW_Typ := Class_Wide_Type (Controlling_Type (Subp)); - - elsif Is_Access_Type (Etype (Ctrl_Arg)) then - CW_Typ := Designated_Type (Etype (Ctrl_Arg)); - - else - CW_Typ := Etype (Ctrl_Arg); - end if; - - Typ := Root_Type (CW_Typ); - - if Ekind (Typ) = E_Incomplete_Type then - Typ := Non_Limited_View (Typ); - end if; - - if not Is_Limited_Type (Typ) then - Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq); - end if; - - if Is_CPP_Class (Root_Type (Typ)) then - - -- Create a new parameter list with the displaced 'this' - - New_Params := New_List; - Param := First_Actual (Call_Node); - while Present (Param) loop - Append_To (New_Params, Relocate_Node (Param)); - Next_Actual (Param); - end loop; - - elsif Present (Param_List) then - - -- Generate the Tag checks when appropriate - - New_Params := New_List; - Param := First_Actual (Call_Node); - while Present (Param) loop - - -- No tag check with itself - - if Param = Ctrl_Arg then - Append_To (New_Params, - Duplicate_Subexpr_Move_Checks (Param)); - - -- No tag check for parameter whose type is neither tagged nor - -- access to tagged (for access parameters) - - elsif No (Find_Controlling_Arg (Param)) then - Append_To (New_Params, Relocate_Node (Param)); - - -- No tag check for function dispatching on result if the - -- Tag given by the context is this one - - elsif Find_Controlling_Arg (Param) = Ctrl_Arg then - Append_To (New_Params, Relocate_Node (Param)); - - -- "=" is the only dispatching operation allowed to get - -- operands with incompatible tags (it just returns false). - -- We use Duplicate_Subexpr_Move_Checks instead of calling - -- Relocate_Node because the value will be duplicated to - -- check the tags. - - elsif Subp = Eq_Prim_Op then - Append_To (New_Params, - Duplicate_Subexpr_Move_Checks (Param)); - - -- No check in presence of suppress flags - - elsif Tag_Checks_Suppressed (Etype (Param)) - or else (Is_Access_Type (Etype (Param)) - and then Tag_Checks_Suppressed - (Designated_Type (Etype (Param)))) - then - Append_To (New_Params, Relocate_Node (Param)); - - -- Optimization: no tag checks if the parameters are identical - - elsif Is_Entity_Name (Param) - and then Is_Entity_Name (Ctrl_Arg) - and then Entity (Param) = Entity (Ctrl_Arg) - then - Append_To (New_Params, Relocate_Node (Param)); - - -- Now we need to generate the Tag check - - else - -- Generate code for tag equality check - -- Perhaps should have Checks.Apply_Tag_Equality_Check??? - - Insert_Action (Ctrl_Arg, - Make_Implicit_If_Statement (Call_Node, - Condition => - Make_Op_Ne (Loc, - Left_Opnd => - Make_Selected_Component (Loc, - Prefix => New_Value (Ctrl_Arg), - Selector_Name => - New_Reference_To - (First_Tag_Component (Typ), Loc)), - - Right_Opnd => - Make_Selected_Component (Loc, - Prefix => - Unchecked_Convert_To (Typ, New_Value (Param)), - Selector_Name => - New_Reference_To - (First_Tag_Component (Typ), Loc))), - - Then_Statements => - New_List (New_Constraint_Error (Loc)))); - - Append_To (New_Params, Relocate_Node (Param)); - end if; - - Next_Actual (Param); - end loop; - end if; - - -- Generate the appropriate subprogram pointer type - - if Etype (Subp) = Typ then - Res_Typ := CW_Typ; - else - Res_Typ := Etype (Subp); - end if; - - Subp_Typ := Create_Itype (E_Subprogram_Type, Call_Node); - Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node); - Set_Etype (Subp_Typ, Res_Typ); - Init_Size_Align (Subp_Ptr_Typ); - Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp)); - - -- Create a new list of parameters which is a copy of the old formal - -- list including the creation of a new set of matching entities. - - declare - Old_Formal : Entity_Id := First_Formal (Subp); - New_Formal : Entity_Id; - Extra : Entity_Id; - - begin - if Present (Old_Formal) then - New_Formal := New_Copy (Old_Formal); - Set_First_Entity (Subp_Typ, New_Formal); - Param := First_Actual (Call_Node); - - loop - Set_Scope (New_Formal, Subp_Typ); - - -- Change all the controlling argument types to be class-wide - -- to avoid a recursion in dispatching. - - if Is_Controlling_Formal (New_Formal) then - Set_Etype (New_Formal, Etype (Param)); - end if; - - if Is_Itype (Etype (New_Formal)) then - Extra := New_Copy (Etype (New_Formal)); - - if Ekind (Extra) = E_Record_Subtype - or else Ekind (Extra) = E_Class_Wide_Subtype - then - Set_Cloned_Subtype (Extra, Etype (New_Formal)); - end if; - - Set_Etype (New_Formal, Extra); - Set_Scope (Etype (New_Formal), Subp_Typ); - end if; - - Extra := New_Formal; - Next_Formal (Old_Formal); - exit when No (Old_Formal); - - Set_Next_Entity (New_Formal, New_Copy (Old_Formal)); - Next_Entity (New_Formal); - Next_Actual (Param); - end loop; - Set_Last_Entity (Subp_Typ, Extra); - - -- 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; - - Next_Formal (New_Formal); - end loop; - end if; - end; - - Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ); - Set_Directly_Designated_Type (Subp_Ptr_Typ, Subp_Typ); - - -- If the controlling argument is a value of type Ada.Tag or an abstract - -- interface class-wide type then use it directly. Otherwise, the tag - -- must be extracted from the controlling object. - - if Etype (Ctrl_Arg) = RTE (RE_Tag) - or else (RTE_Available (RE_Interface_Tag) - and then Etype (Ctrl_Arg) = RTE (RE_Interface_Tag)) - then - Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg); - - -- Ada 2005 (AI-251): Abstract interface class-wide type - - elsif Is_Interface (Etype (Ctrl_Arg)) - and then Is_Class_Wide_Type (Etype (Ctrl_Arg)) - then - Controlling_Tag := Duplicate_Subexpr (Ctrl_Arg); - - else - Controlling_Tag := - Make_Selected_Component (Loc, - Prefix => Duplicate_Subexpr_Move_Checks (Ctrl_Arg), - Selector_Name => New_Reference_To (DTC_Entity (Subp), Loc)); - end if; - - -- Generate: - -- Subp_Ptr_Typ!(Get_Prim_Op_Address (Ctrl._Tag, pos)); - - if Is_Predefined_Dispatching_Operation (Subp) then - New_Call_Name := - Unchecked_Convert_To (Subp_Ptr_Typ, - Make_DT_Access_Action (Typ, - Action => Get_Predefined_Prim_Op_Address, - Args => New_List ( - - -- Vptr - - Unchecked_Convert_To (RTE (RE_Tag), - Controlling_Tag), - - -- Position - - Make_Integer_Literal (Loc, DT_Position (Subp))))); - - else - New_Call_Name := - Unchecked_Convert_To (Subp_Ptr_Typ, - Make_DT_Access_Action (Typ, - Action => Get_Prim_Op_Address, - Args => New_List ( - - -- Vptr - - Unchecked_Convert_To (RTE (RE_Tag), - Controlling_Tag), - - -- Position - - Make_Integer_Literal (Loc, 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. - - 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); - - 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))); - - 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; - end if; - - else - New_Call := - Make_Procedure_Call_Statement (Loc, - Name => New_Call_Name, - Parameter_Associations => New_Params); - end if; - - Rewrite (Call_Node, New_Call); - Analyze_And_Resolve (Call_Node, Call_Typ); - end Expand_Dispatching_Call; - - --------------------------------- - -- Expand_Interface_Conversion -- - --------------------------------- - - 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); - Iface_Typ : Entity_Id := Etype (N); - Iface_Tag : Entity_Id; - Fent : Entity_Id; - Func : Node_Id; - P : Node_Id; - Null_Op_Nod : Node_Id; - - begin - pragma Assert (Nkind (Operand) /= N_Attribute_Reference); - - -- Ada 2005 (AI-345): Handle task interfaces - - if Ekind (Operand_Typ) = E_Task_Type - or else Ekind (Operand_Typ) = E_Protected_Type - then - Operand_Typ := Corresponding_Record_Type (Operand_Typ); - end if; - - -- Handle access types to interfaces - - if Is_Access_Type (Iface_Typ) then - Iface_Typ := Etype (Directly_Designated_Type (Iface_Typ)); - end if; - - -- Handle class-wide interface types. This conversion can appear - -- explicitly in the source code. Example: I'Class (Obj) - - if Is_Class_Wide_Type (Iface_Typ) then - Iface_Typ := Etype (Iface_Typ); - end if; - - pragma Assert (not Is_Class_Wide_Type (Iface_Typ) - and then Is_Interface (Iface_Typ)); - - if not Is_Static then - - -- Give error if configurable run time and Displace not available - - if not RTE_Available (RE_Displace) then - Error_Msg_CRT ("abstract interface types", N); - return; - end if; - - 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, Make_Explicit_Dereference (Loc, - Unchecked_Convert_To (New_Itype, - Relocate_Node (N)))); - Analyze (N); - end; - - return; - end if; - - Iface_Tag := Find_Interface_Tag (Operand_Typ, Iface_Typ); - pragma Assert (Iface_Tag /= Empty); - - -- Keep separate access types to interfaces because one internal - -- function is used to handle the null value (see following comment) - - if not Is_Access_Type (Etype (N)) then - Rewrite (N, - Unchecked_Convert_To (Etype (N), - Make_Selected_Component (Loc, - Prefix => Relocate_Node (Expression (N)), - Selector_Name => - New_Occurrence_Of (Iface_Tag, Loc)))); - - else - -- Build internal function to handle the case in which the - -- actual is null. If the actual is null returns null because - -- no displacement is required; otherwise performs a type - -- conversion that will be expanded in the code that returns - -- the value of the displaced actual. That is: - - -- function Func (O : Operand_Typ) return Iface_Typ is - -- begin - -- if O = null then - -- return null; - -- else - -- return Iface_Typ!(O); - -- end if; - -- end Func; - - Fent := - Make_Defining_Identifier (Loc, New_Internal_Name ('F')); - - -- Decorate the "null" in the if-statement condition - - Null_Op_Nod := Make_Null (Loc); - Set_Etype (Null_Op_Nod, Etype (Operand)); - Set_Analyzed (Null_Op_Nod); - - Func := - Make_Subprogram_Body (Loc, - Specification => - Make_Function_Specification (Loc, - Defining_Unit_Name => Fent, - - Parameter_Specifications => New_List ( - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uO), - Parameter_Type => - New_Reference_To (Etype (Operand), Loc))), - Result_Definition => - New_Reference_To (Etype (N), Loc)), - - 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 => Null_Op_Nod), - 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 => Make_Identifier (Loc, Name_uO), - Selector_Name => - New_Occurrence_Of (Iface_Tag, Loc)), - Attribute_Name => Name_Address)))))))); - - -- Insert the new declaration in the nearest enclosing scope - -- that has declarations. - - P := N; - while not Has_Declarations (Parent (P)) loop - P := Parent (P); - end loop; - - if Is_List_Member (P) then - Insert_Before (P, Func); - - elsif Nkind (Parent (P)) = N_Package_Specification then - Append_To (Visible_Declarations (Parent (P)), Func); - - else - Append_To (Declarations (Parent (P)), Func); - end if; - - Analyze (Func); - - Rewrite (N, - Make_Function_Call (Loc, - Name => New_Reference_To (Fent, Loc), - Parameter_Associations => New_List ( - Relocate_Node (Expression (N))))); - end if; - - Analyze (N); - end Expand_Interface_Conversion; - - ------------------------------ - -- Expand_Interface_Actuals -- - ------------------------------ - - procedure Expand_Interface_Actuals (Call_Node : Node_Id) is - Loc : constant Source_Ptr := Sloc (Call_Node); - Actual : Node_Id; - Actual_Dup : Node_Id; - Actual_Typ : Entity_Id; - Anon : Entity_Id; - Conversion : Node_Id; - Formal : Entity_Id; - Formal_Typ : Entity_Id; - Subp : Entity_Id; - Nam : Name_Id; - Formal_DDT : Entity_Id; - Actual_DDT : Entity_Id; - - begin - -- This subprogram is called directly from the semantics, so we need a - -- check to see whether expansion is active before proceeding. - - if not Expander_Active then - return; - end if; - - -- Call using access to subprogram with explicit dereference - - if Nkind (Name (Call_Node)) = N_Explicit_Dereference then - Subp := Etype (Name (Call_Node)); - - -- Normal case - - else - Subp := Entity (Name (Call_Node)); - end if; - - 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)); - - if Ekind (Formal_Typ) = E_Record_Type_With_Private then - Formal_Typ := Full_View (Formal_Typ); - end if; - - if Is_Access_Type (Formal_Typ) then - Formal_DDT := Directly_Designated_Type (Formal_Typ); - end if; - - Actual_Typ := Etype (Actual); - - if Is_Access_Type (Actual_Typ) then - Actual_DDT := Directly_Designated_Type (Actual_Typ); - end if; - - if Is_Interface (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: - - -- 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 - 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. - - elsif Is_Ancestor (Formal_Typ, Actual_Typ) then - null; - - else - Conversion := Convert_To (Formal_Typ, Relocate_Node (Actual)); - Rewrite (Actual, Conversion); - Analyze_And_Resolve (Actual, Formal_Typ); - end if; - - -- Anonymous access type - - elsif Is_Access_Type (Formal_Typ) - and then Is_Interface (Etype (Formal_DDT)) - and then Interface_Present_In_Ancestor - (Typ => Actual_DDT, - Iface => Etype (Formal_DDT)) - then - if Nkind (Actual) = N_Attribute_Reference - and then - (Attribute_Name (Actual) = Name_Access - or else Attribute_Name (Actual) = Name_Unchecked_Access) - then - Nam := Attribute_Name (Actual); - - Conversion := Convert_To (Etype (Formal_DDT), Prefix (Actual)); - - Rewrite (Actual, Conversion); - Analyze_And_Resolve (Actual, Etype (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) - - elsif Is_Class_Wide_Type (Actual_DDT) - and then Etype (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) - - elsif Is_Ancestor (Formal_DDT, Actual_DDT) then - null; - - else - Actual_Dup := Relocate_Node (Actual); - - if From_With_Type (Actual_Typ) then - - -- If the type of the actual parameter comes from a limited - -- with-clause and the non-limited view is already available - -- we replace the anonymous access type by a duplicate decla - -- ration whose designated type is the non-limited view - - if Ekind (Actual_DDT) = E_Incomplete_Type - and then Present (Non_Limited_View (Actual_DDT)) - then - Anon := New_Copy (Actual_Typ); - - if Is_Itype (Anon) then - Set_Scope (Anon, Current_Scope); - end if; - - Set_Directly_Designated_Type (Anon, - Non_Limited_View (Actual_DDT)); - Set_Etype (Actual_Dup, Anon); - - elsif Is_Class_Wide_Type (Actual_DDT) - and then Ekind (Etype (Actual_DDT)) = E_Incomplete_Type - and then Present (Non_Limited_View (Etype (Actual_DDT))) - then - Anon := New_Copy (Actual_Typ); - - if Is_Itype (Anon) then - Set_Scope (Anon, Current_Scope); - end if; - - Set_Directly_Designated_Type (Anon, - New_Copy (Actual_DDT)); - Set_Class_Wide_Type (Directly_Designated_Type (Anon), - New_Copy (Class_Wide_Type (Actual_DDT))); - Set_Etype (Directly_Designated_Type (Anon), - Non_Limited_View (Etype (Actual_DDT))); - Set_Etype ( - Class_Wide_Type (Directly_Designated_Type (Anon)), - Non_Limited_View (Etype (Actual_DDT))); - Set_Etype (Actual_Dup, Anon); - end if; - end if; - - Conversion := Convert_To (Formal_Typ, Actual_Dup); - Rewrite (Actual, Conversion); - Analyze_And_Resolve (Actual, Formal_Typ); - end if; - end if; - - Next_Actual (Actual); - Next_Formal (Formal); - end loop; - end Expand_Interface_Actuals; - - ---------------------------- - -- Expand_Interface_Thunk -- - ---------------------------- - - function Expand_Interface_Thunk - (N : Node_Id; - Thunk_Alias : Entity_Id; - Thunk_Id : Entity_Id) return 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; - - begin - -- Traverse the list of alias to find the final target - - Target := Thunk_Alias; - while Present (Alias (Target)) loop - Target := Alias (Target); - end loop; - - -- 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 : in 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); - - 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 <<type of the first formal>> - -- S1 := Storage_Offset!(First_formal) - -- - Offset_To_Top (First_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 - (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), - 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)))))); - - 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))); - - else - -- Generate: - - -- S1 := Storage_Offset!(First_formal'Address) - -- - Offset_To_Top (First_Formal.Tag) - -- S2 := Tag_Ptr!(S3) - - 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))))); - - 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; - - Formal := Next (First (Formals)); - while Present (Formal) loop - Append_To (Actuals, - New_Reference_To (Defining_Identifier (Formal), Loc)); - Next (Formal); - end loop; - - if Ekind (Target) = E_Procedure then - New_Code := - Make_Subprogram_Body (Loc, - Specification => - Make_Procedure_Specification (Loc, - Defining_Unit_Name => Thunk_Id, - Parameter_Specifications => Formals), - Declarations => Decl, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Make_Procedure_Call_Statement (Loc, - Name => New_Occurrence_Of (Target, Loc), - Parameter_Associations => Actuals)))); - - else pragma Assert (Ekind (Target) = E_Function); - - New_Code := - Make_Subprogram_Body (Loc, - Specification => - Make_Function_Specification (Loc, - Defining_Unit_Name => Thunk_Id, - Parameter_Specifications => Formals, - Result_Definition => - New_Copy (Result_Definition (Parent (Target)))), - Declarations => Decl, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Make_Return_Statement (Loc, - Make_Function_Call (Loc, - Name => New_Occurrence_Of (Target, Loc), - Parameter_Associations => Actuals))))); - end if; - - Analyze (New_Code); - 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) then - return - Make_DT_Access_Action (Typ, - Action => Set_Predefined_Prim_Op_Address, - Args => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (DT_Ptr, Loc)), -- DTptr - - Make_Integer_Literal (Loc, Pos), -- Position - - Make_Attribute_Reference (Loc, -- Value - Prefix => New_Reference_To (Prim, Loc), - Attribute_Name => Name_Address))); - else - pragma Assert (Pos /= Uint_0 and then Pos <= DT_Entry_Count (Tag)); - - return - Make_DT_Access_Action (Typ, - Action => Set_Prim_Op_Address, - Args => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (DT_Ptr, Loc)), -- DTptr - - Make_Integer_Literal (Loc, Pos), -- Position - - Make_Attribute_Reference (Loc, -- Value - 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 - Typ : constant Entity_Id := Scope (DTC_Entity (Alias (Prim))); - 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) then - return - Make_DT_Access_Action (Typ, - Action => Set_Predefined_Prim_Op_Address, - Args => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (Iface_DT_Ptr, Loc)), -- DTptr - - Make_Integer_Literal (Loc, Pos), -- Position - - Make_Attribute_Reference (Loc, -- Value - 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 - Make_DT_Access_Action (Typ, - Action => Set_Prim_Op_Address, - Args => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (Iface_DT_Ptr, Loc)), -- DTptr - - Make_Integer_Literal (Loc, Pos), -- Position - - Make_Attribute_Reference (Loc, -- Value - Prefix => New_Reference_To (Thunk_Id, Loc), - Attribute_Name => Name_Address))); - end if; - end Fill_Secondary_DT_Entry; - - --------------------------- - -- Get_Remotely_Callable -- - --------------------------- - - function Get_Remotely_Callable (Obj : Node_Id) return Node_Id is - Loc : constant Source_Ptr := Sloc (Obj); - begin - return Make_DT_Access_Action - (Typ => Etype (Obj), - Action => Get_Remotely_Callable, - Args => New_List ( - Make_Selected_Component (Loc, - Prefix => Obj, - Selector_Name => Make_Identifier (Loc, Name_uTag)))); - end Get_Remotely_Callable; - - ------------------------------------------ - -- Init_Predefined_Interface_Primitives -- - ------------------------------------------ - - function Init_Predefined_Interface_Primitives - (Typ : Entity_Id) return List_Id - is - Loc : constant Source_Ptr := Sloc (Typ); - DT_Ptr : constant Node_Id := - Node (First_Elmt (Access_Disp_Table (Typ))); - Result : constant List_Id := New_List; - AI : Elmt_Id; - - begin - -- No need to inherit primitives if we have an abstract interface - -- type or a concurrent type. - - if Is_Interface (Typ) - or else Is_Concurrent_Record_Type (Typ) - or else Restriction_Active (No_Dispatching_Calls) - then - return Result; - end if; - - AI := Next_Elmt (First_Elmt (Access_Disp_Table (Typ))); - while Present (AI) loop - - -- All the secondary tables inherit the dispatch table entries - -- associated with predefined primitives. - - -- Generate: - -- Inherit_DT (T'Tag, Iface'Tag, 0); - - Append_To (Result, - Make_DT_Access_Action (Typ, - Action => Inherit_DT, - Args => New_List ( - Node1 => New_Reference_To (DT_Ptr, Loc), - Node2 => Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (Node (AI), Loc)), - Node3 => Make_Integer_Literal (Loc, Uint_0)))); - - Next_Elmt (AI); - end loop; - - return Result; - end Init_Predefined_Interface_Primitives; - - ---------------------------------------- - -- Make_Disp_Asynchronous_Select_Body -- - ---------------------------------------- - - 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; - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - -- Null body is generated for interface types - - if Is_Interface (Typ) then - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Asynchronous_Select_Spec (Typ), - Declarations => - New_List, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - New_List (Make_Null_Statement (Loc)))); - end if; - - DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); - - if Is_Concurrent_Record_Type (Typ) then - Conc_Typ := Corresponding_Concurrent_Type (Typ); - - -- Generate: - -- 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. - - Append_To (Decls, - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uI), - 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))))); - - if Ekind (Conc_Typ) = E_Protected_Type then - - -- Generate: - -- Protected_Entry_Call ( - -- T._object'access, - -- protected_entry_index! (I), - -- P, - -- Asynchronous_Call, - -- B); - - -- where T is the protected object, I is the entry index, P are - -- the wrapped parameters and B is the name of the communication - -- block. - - Append_To (Stmts, - Make_Procedure_Call_Statement (Loc, - Name => - New_Reference_To (RTE (RE_Protected_Entry_Call), Loc), - Parameter_Associations => - New_List ( - - Make_Attribute_Reference (Loc, -- T._object'access - Attribute_Name => - Name_Unchecked_Access, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Make_Identifier (Loc, Name_uT), - Selector_Name => - Make_Identifier (Loc, Name_uObject))), - - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Reference_To (RTE (RE_Protected_Entry_Index), Loc), - Expression => - Make_Identifier (Loc, Name_uI)), - - Make_Identifier (Loc, Name_uP), -- parameter block - New_Reference_To ( -- Asynchronous_Call - RTE (RE_Asynchronous_Call), Loc), - Make_Identifier (Loc, Name_uB)))); -- comm block - else - pragma Assert (Ekind (Conc_Typ) = E_Task_Type); - - -- Generate: - -- Protected_Entry_Call ( - -- T._task_id, - -- task_entry_index! (I), - -- P, - -- Conditional_Call, - -- F); - - -- where T is the task object, I is the entry index, P are the - -- wrapped parameters and F is the status flag. - - Append_To (Stmts, - Make_Procedure_Call_Statement (Loc, - Name => - New_Reference_To (RTE (RE_Task_Entry_Call), Loc), - Parameter_Associations => - New_List ( - - Make_Selected_Component (Loc, -- T._task_id - Prefix => - Make_Identifier (Loc, Name_uT), - Selector_Name => - Make_Identifier (Loc, Name_uTask_Id)), - - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Reference_To (RTE (RE_Task_Entry_Index), Loc), - Expression => - Make_Identifier (Loc, Name_uI)), - - Make_Identifier (Loc, Name_uP), -- parameter block - New_Reference_To ( -- Asynchronous_Call - RTE (RE_Asynchronous_Call), Loc), - Make_Identifier (Loc, Name_uF)))); -- status flag - end if; - end if; - - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Asynchronous_Select_Spec (Typ), - Declarations => - Decls, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, Stmts)); - end Make_Disp_Asynchronous_Select_Body; - - ---------------------------------------- - -- Make_Disp_Asynchronous_Select_Spec -- - ---------------------------------------- - - function Make_Disp_Asynchronous_Select_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_Asynchronous_Select); - Params : constant List_Id := New_List; - - 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 - - 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); - - Set_Is_Internal (Def_Id); - - return - Make_Procedure_Specification (Loc, - Defining_Unit_Name => Def_Id, - Parameter_Specifications => Params); - end Make_Disp_Asynchronous_Select_Spec; - - --------------------------------------- - -- Make_Disp_Conditional_Select_Body -- - --------------------------------------- - - function Make_Disp_Conditional_Select_Body - (Typ : Entity_Id) return Node_Id - is - Loc : constant Source_Ptr := Sloc (Typ); - Blk_Nam : Entity_Id; - Conc_Typ : Entity_Id := Empty; - Decls : constant List_Id := New_List; - DT_Ptr : Entity_Id; - Stmts : constant List_Id := New_List; - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - -- Null body is generated for interface types - - if Is_Interface (Typ) then - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Conditional_Select_Spec (Typ), - Declarations => - No_List, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - New_List (Make_Null_Statement (Loc)))); - end if; - - DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); - - if Is_Concurrent_Record_Type (Typ) then - Conc_Typ := Corresponding_Concurrent_Type (Typ); - - -- Generate: - -- I : Integer; - - -- where I will be used to capture the entry index of the primitive - -- wrapper at position S. - - Append_To (Decls, - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uI), - Object_Definition => - New_Reference_To (Standard_Integer, Loc))); - - -- 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; - - SEU.Build_Common_Dispatching_Select_Statements - (Loc, Typ, DT_Ptr, Stmts); - - -- Generate: - -- Bnn : Communication_Block; - - -- where Bnn is the name of the communication block used in - -- the call to Protected_Entry_Call. - - Blk_Nam := Make_Defining_Identifier (Loc, New_Internal_Name ('B')); - - Append_To (Decls, - Make_Object_Declaration (Loc, - Defining_Identifier => - Blk_Nam, - Object_Definition => - New_Reference_To (RTE (RE_Communication_Block), Loc))); - - -- Generate: - -- I := Get_Entry_Index (tag! (<type>VP), S); - - -- I is the entry index and S is the dispatch table slot - - Append_To (Stmts, - Make_Assignment_Statement (Loc, - 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))))); - - if Ekind (Conc_Typ) = E_Protected_Type then - - -- Generate: - -- Protected_Entry_Call ( - -- T._object'access, - -- protected_entry_index! (I), - -- P, - -- Conditional_Call, - -- Bnn); - - -- where T is the protected object, I is the entry index, P are - -- the wrapped parameters and Bnn is the name of the communication - -- block. - - Append_To (Stmts, - Make_Procedure_Call_Statement (Loc, - Name => - New_Reference_To (RTE (RE_Protected_Entry_Call), Loc), - Parameter_Associations => - New_List ( - - Make_Attribute_Reference (Loc, -- T._object'access - Attribute_Name => - Name_Unchecked_Access, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Make_Identifier (Loc, Name_uT), - Selector_Name => - Make_Identifier (Loc, Name_uObject))), - - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Reference_To (RTE (RE_Protected_Entry_Index), Loc), - Expression => - Make_Identifier (Loc, Name_uI)), - - Make_Identifier (Loc, Name_uP), -- parameter block - New_Reference_To ( -- Conditional_Call - RTE (RE_Conditional_Call), Loc), - New_Reference_To ( -- Bnn - Blk_Nam, Loc)))); - - -- Generate: - -- F := not Cancelled (Bnn); - - -- where F is the success flag. The status of Cancelled is negated - -- in order to match the behaviour of the version for task types. - - Append_To (Stmts, - Make_Assignment_Statement (Loc, - Name => - Make_Identifier (Loc, Name_uF), - Expression => - Make_Op_Not (Loc, - Right_Opnd => - Make_Function_Call (Loc, - Name => - New_Reference_To (RTE (RE_Cancelled), Loc), - Parameter_Associations => - New_List ( - New_Reference_To (Blk_Nam, Loc)))))); - else - pragma Assert (Ekind (Conc_Typ) = E_Task_Type); - - -- Generate: - -- Protected_Entry_Call ( - -- T._task_id, - -- task_entry_index! (I), - -- P, - -- Conditional_Call, - -- F); - - -- where T is the task object, I is the entry index, P are the - -- wrapped parameters and F is the status flag. - - Append_To (Stmts, - Make_Procedure_Call_Statement (Loc, - Name => - New_Reference_To (RTE (RE_Task_Entry_Call), Loc), - Parameter_Associations => - New_List ( - - Make_Selected_Component (Loc, -- T._task_id - Prefix => - Make_Identifier (Loc, Name_uT), - Selector_Name => - Make_Identifier (Loc, Name_uTask_Id)), - - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Reference_To (RTE (RE_Task_Entry_Index), Loc), - Expression => - Make_Identifier (Loc, Name_uI)), - - Make_Identifier (Loc, Name_uP), -- parameter block - New_Reference_To ( -- Conditional_Call - RTE (RE_Conditional_Call), Loc), - Make_Identifier (Loc, Name_uF)))); -- status flag - end if; - end if; - - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Conditional_Select_Spec (Typ), - Declarations => - Decls, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, Stmts)); - end Make_Disp_Conditional_Select_Body; - - --------------------------------------- - -- Make_Disp_Conditional_Select_Spec -- - --------------------------------------- - - function Make_Disp_Conditional_Select_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_Conditional_Select); - Params : constant List_Id := New_List; - - 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 - - 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); - - Set_Is_Internal (Def_Id); - - return - Make_Procedure_Specification (Loc, - Defining_Unit_Name => Def_Id, - Parameter_Specifications => Params); - end Make_Disp_Conditional_Select_Spec; - - ------------------------------------- - -- Make_Disp_Get_Prim_Op_Kind_Body -- - ------------------------------------- - - function Make_Disp_Get_Prim_Op_Kind_Body - (Typ : Entity_Id) return Node_Id - is - Loc : constant Source_Ptr := Sloc (Typ); - DT_Ptr : Entity_Id; - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - if Is_Interface (Typ) then - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Get_Prim_Op_Kind_Spec (Typ), - Declarations => - New_List, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - New_List (Make_Null_Statement (Loc)))); - end if; - - DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); - - -- Generate: - -- C := get_prim_op_kind (tag! (<type>VP), S); - - -- where C is the out parameter capturing the call kind and S is the - -- dispatch table slot number. - - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Get_Prim_Op_Kind_Spec (Typ), - Declarations => - New_List, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - New_List ( - 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))))))); - end Make_Disp_Get_Prim_Op_Kind_Body; - - ------------------------------------- - -- Make_Disp_Get_Prim_Op_Kind_Spec -- - ------------------------------------- - - function Make_Disp_Get_Prim_Op_Kind_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_Prim_Op_Kind); - Params : constant List_Id := New_List; - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - -- "T" - Object parameter - -- "S" - Primitive operation slot - -- "C" - Call kind - - SEU.Build_T (Loc, Typ, Params); - SEU.Build_S (Loc, Params); - SEU.Build_C (Loc, Params); - - Set_Is_Internal (Def_Id); - - return - Make_Procedure_Specification (Loc, - Defining_Unit_Name => Def_Id, - Parameter_Specifications => Params); - end Make_Disp_Get_Prim_Op_Kind_Spec; - - -------------------------------- - -- Make_Disp_Get_Task_Id_Body -- - -------------------------------- - - function Make_Disp_Get_Task_Id_Body - (Typ : Entity_Id) return Node_Id - is - Loc : constant Source_Ptr := Sloc (Typ); - Ret : Node_Id; - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - if Is_Concurrent_Record_Type (Typ) - and then Ekind (Corresponding_Concurrent_Type (Typ)) = E_Task_Type - then - Ret := - Make_Return_Statement (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 - Ret := - Make_Return_Statement (Loc, - Expression => - New_Reference_To (RTE (RO_ST_Null_Task), Loc)); - end if; - - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Get_Task_Id_Spec (Typ), - Declarations => - New_List, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - New_List (Ret))); - end Make_Disp_Get_Task_Id_Body; - - -------------------------------- - -- Make_Disp_Get_Task_Id_Spec -- - -------------------------------- - - 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); - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - Set_Is_Internal (Def_Id); - - return - Make_Function_Specification (Loc, - Defining_Unit_Name => Def_Id, - Parameter_Specifications => New_List ( - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uT), - Parameter_Type => - New_Reference_To (Typ, Loc))), - Result_Definition => - New_Reference_To (RTE (RO_ST_Task_Id), Loc)); - end Make_Disp_Get_Task_Id_Spec; - - --------------------------------- - -- Make_Disp_Timed_Select_Body -- - --------------------------------- - - function Make_Disp_Timed_Select_Body - (Typ : Entity_Id) return Node_Id - is - Loc : constant Source_Ptr := Sloc (Typ); - Conc_Typ : Entity_Id := Empty; - Decls : constant List_Id := New_List; - DT_Ptr : Entity_Id; - Stmts : constant List_Id := New_List; - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - -- Null body is generated for interface types - - if Is_Interface (Typ) then - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Timed_Select_Spec (Typ), - Declarations => - New_List, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - New_List (Make_Null_Statement (Loc)))); - end if; - - DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); - - if Is_Concurrent_Record_Type (Typ) then - Conc_Typ := Corresponding_Concurrent_Type (Typ); - - -- Generate: - -- I : Integer; - - -- where I will be used to capture the entry index of the primitive - -- wrapper at position S. - - Append_To (Decls, - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uI), - Object_Definition => - New_Reference_To (Standard_Integer, Loc))); - - -- 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; - - SEU.Build_Common_Dispatching_Select_Statements - (Loc, Typ, DT_Ptr, Stmts); - - -- Generate: - -- I := Get_Entry_Index (tag! (<type>VP), S); - - -- I is the entry index and S is the dispatch table slot - - Append_To (Stmts, - Make_Assignment_Statement (Loc, - 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))))); - - if Ekind (Conc_Typ) = E_Protected_Type then - - -- Generate: - -- Timed_Protected_Entry_Call ( - -- T._object'access, - -- protected_entry_index! (I), - -- P, - -- D, - -- M, - -- F); - - -- where T is the protected object, I is the entry index, P are - -- the wrapped parameters, D is the delay amount, M is the delay - -- mode and F is the status flag. - - Append_To (Stmts, - Make_Procedure_Call_Statement (Loc, - Name => - New_Reference_To (RTE (RE_Timed_Protected_Entry_Call), Loc), - Parameter_Associations => - New_List ( - - Make_Attribute_Reference (Loc, -- T._object'access - Attribute_Name => - Name_Unchecked_Access, - Prefix => - Make_Selected_Component (Loc, - Prefix => - Make_Identifier (Loc, Name_uT), - Selector_Name => - Make_Identifier (Loc, Name_uObject))), - - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Reference_To (RTE (RE_Protected_Entry_Index), Loc), - Expression => - Make_Identifier (Loc, Name_uI)), - - Make_Identifier (Loc, Name_uP), -- parameter block - Make_Identifier (Loc, Name_uD), -- delay - Make_Identifier (Loc, Name_uM), -- delay mode - Make_Identifier (Loc, Name_uF)))); -- status flag - - else - pragma Assert (Ekind (Conc_Typ) = E_Task_Type); - - -- Generate: - -- Timed_Task_Entry_Call ( - -- T._task_id, - -- task_entry_index! (I), - -- P, - -- D, - -- M, - -- F); - - -- where T is the task object, I is the entry index, P are the - -- wrapped parameters, D is the delay amount, M is the delay - -- mode and F is the status flag. - - Append_To (Stmts, - Make_Procedure_Call_Statement (Loc, - Name => - New_Reference_To (RTE (RE_Timed_Task_Entry_Call), Loc), - Parameter_Associations => - New_List ( - - Make_Selected_Component (Loc, -- T._task_id - Prefix => - Make_Identifier (Loc, Name_uT), - Selector_Name => - Make_Identifier (Loc, Name_uTask_Id)), - - Make_Unchecked_Type_Conversion (Loc, -- entry index - Subtype_Mark => - New_Reference_To (RTE (RE_Task_Entry_Index), Loc), - Expression => - Make_Identifier (Loc, Name_uI)), - - Make_Identifier (Loc, Name_uP), -- parameter block - Make_Identifier (Loc, Name_uD), -- delay - Make_Identifier (Loc, Name_uM), -- delay mode - Make_Identifier (Loc, Name_uF)))); -- status flag - end if; - end if; - - return - Make_Subprogram_Body (Loc, - Specification => - Make_Disp_Timed_Select_Spec (Typ), - Declarations => - Decls, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, Stmts)); - end Make_Disp_Timed_Select_Body; - - --------------------------------- - -- Make_Disp_Timed_Select_Spec -- - --------------------------------- - - function Make_Disp_Timed_Select_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_Timed_Select); - Params : constant List_Id := New_List; - - 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 - - SEU.Build_T (Loc, Typ, Params); - SEU.Build_S (Loc, Params); - SEU.Build_P (Loc, Params); - - Append_To (Params, - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Name_uD), - Parameter_Type => - 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))); - - SEU.Build_C (Loc, Params); - SEU.Build_F (Loc, Params); - - Set_Is_Internal (Def_Id); - - return - Make_Procedure_Specification (Loc, - Defining_Unit_Name => Def_Id, - Parameter_Specifications => Params); - end Make_Disp_Timed_Select_Spec; - - ------------- - -- 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'); - 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); - 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; - Empty_DT : Boolean := False; - Typ_Copy : Entity_Id; - - begin - if not RTE_Available (RE_Tag) then - Error_Msg_CRT ("tagged types", Typ); - return New_List; - end if; - - -- 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 will be used as the tag of this abstract - -- interface type. - - Empty_DT := True; - Nb_Prim := 1; - TSD_Num_Entries := 0; - Num_Ifaces := 0; - - else - -- 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); - - AI := First_Elmt (Abstract_Interfaces (Typ_Copy)); - while Present (AI) loop - Num_Ifaces := Num_Ifaces + 1; - Next_Elmt (AI); - end loop; - - -- 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 - Parent_Type : Entity_Id := Typ; - P : Entity_Id; - - begin - I_Depth := 0; - loop - P := Etype (Parent_Type); - - if Is_Private_Type (P) then - P := Full_View (Base_Type (P)); - end if; - - exit when P = Parent_Type; - - I_Depth := I_Depth + 1; - Parent_Type := P; - end loop; - end; - - 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 0 (or we are compiling with - -- the No_Dispatching_Calls restriction) we reserve a dummy single - -- entry for its DT because at run-time the pointer to this dummy DT - -- will be used as the tag of this tagged type. - - if Nb_Prim = 0 or else Restriction_Active (No_Dispatching_Calls) then - Empty_DT := True; - Nb_Prim := 1; - end if; - end if; - - -- Dispatch table and related entities are allocated statically - - Set_Ekind (DT, E_Variable); - Set_Is_Statically_Allocated (DT); - - 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); - - Set_Ekind (TSD, E_Variable); - Set_Is_Statically_Allocated (TSD); - - Set_Ekind (Exname, E_Variable); - Set_Is_Statically_Allocated (Exname); - - Set_Ekind (No_Reg, E_Variable); - Set_Is_Statically_Allocated (No_Reg); - - -- Generate code to create the storage for the Dispatch_Table object: - - -- 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 => Make_DT_Access_Action (Typ, DT_Prologue_Size, No_List), - Right_Opnd => - Make_Op_Multiply (Loc, - Left_Opnd => - Make_DT_Access_Action (Typ, DT_Entry_Size, No_List), - Right_Opnd => - Make_Integer_Literal (Loc, Nb_Prim))); - - 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)))))); - - 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))); - - -- Generate code to create the pointer to the dispatch table - - -- DT_Ptr : Tag := Tag!(DT'Address); - - -- 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 - - 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 => - Make_DT_Access_Action (Typ, - DT_Prologue_Size, No_List))))); - - -- Generate code to define the boolean that controls registration, in - -- order to avoid multiple registrations for tagged types defined in - -- multiple-called scopes. - - 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))); - - -- Set Access_Disp_Table field to be the dispatch table pointer - - if No (Access_Disp_Table (Typ)) then - Set_Access_Disp_Table (Typ, New_Elmt_List); - end if; - - Prepend_Elmt (DT_Ptr, Access_Disp_Table (Typ)); - - -- 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: Storage_Array - -- (1..TSD_Prologue_Size+TSD_Num_Entries*TSD_Entry_Size); - -- for TSD'Alignment use Address'Alignment - - Size_Expr_Node := - Make_Op_Add (Loc, - Left_Opnd => - Make_DT_Access_Action (Typ, TSD_Prologue_Size, No_List), - Right_Opnd => - Make_Op_Multiply (Loc, - Left_Opnd => - Make_DT_Access_Action (Typ, TSD_Entry_Size, No_List), - Right_Opnd => - Make_Integer_Literal (Loc, TSD_Num_Entries))); - - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => TSD, - 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 (TSD, Loc), - Chars => Name_Alignment, - Expression => - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (RTE (RE_Integer_Address), Loc), - Attribute_Name => Name_Alignment))); - - -- Generate: - -- Set_Signature (DT_Ptr, Value); - - 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), -- DTptr - New_Reference_To (RTE (RE_Abstract_Interface), Loc)))); - - elsif RTE_Available (RE_Set_Signature) then - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_Signature, - Args => New_List ( - New_Reference_To (DT_Ptr, Loc), -- DTptr - New_Reference_To (RTE (RE_Primary_DT), Loc)))); - end if; - - -- Generate code to put the Address of the TSD in the dispatch table - -- Set_TSD (DT_Ptr, TSD); - - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_TSD, - Args => New_List ( - New_Reference_To (DT_Ptr, Loc), -- DTptr - Make_Attribute_Reference (Loc, -- Value - 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 - if RTE_Available (RE_Set_Interface_Table) 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 - end if; - - -- Generate the Interface_Table object and set the access - -- component if the TSD to it. - - elsif RTE_Available (RE_Set_Interface_Table) then - 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) - - if RTE_Available (RE_Set_Num_Prim_Ops) then - if not Is_Interface (Typ) then - if Empty_DT then - Append_To (Elab_Code, - Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (RTE (RE_Set_Num_Prim_Ops), Loc), - Parameter_Associations => New_List ( - New_Reference_To (DT_Ptr, Loc), - Make_Integer_Literal (Loc, Uint_0)))); - else - Append_To (Elab_Code, - Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (RTE (RE_Set_Num_Prim_Ops), Loc), - Parameter_Associations => New_List ( - New_Reference_To (DT_Ptr, Loc), - Make_Integer_Literal (Loc, Nb_Prim)))); - end if; - end if; - - if Ada_Version >= Ada_05 - and then not Is_Interface (Typ) - and then not Is_Abstract (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)); - - 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 not Empty_DT - and then Is_Concurrent_Record_Type (Typ) - and then Implements_Interface ( - Typ => Typ, - Kind => Any_Limited_Interface, - Check_Parent => True) - 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)))))); - - -- 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; - 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. - - Append_To (Result, - Make_Object_Declaration (Loc, - Defining_Identifier => Exname, - Constant_Present => True, - Object_Definition => New_Reference_To (Standard_String, Loc), - Expression => - Make_String_Literal (Loc, - Full_Qualified_Name (First_Subtype (Typ))))); - - -- Generate: Set_Expanded_Name (DT_Ptr, exname'Address); - - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_Expanded_Name, - Args => New_List ( - Node1 => New_Reference_To (DT_Ptr, Loc), - Node2 => - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Exname, Loc), - Attribute_Name => Name_Address)))); - - if not Is_Interface (Typ) then - -- Generate: Set_Access_Level (DT_Ptr, <type's accessibility level>); - - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_Access_Level, - Args => New_List ( - Node1 => New_Reference_To (DT_Ptr, Loc), - Node2 => Make_Integer_Literal (Loc, Type_Access_Level (Typ))))); - end if; - - if Typ = Etype (Typ) - or else Is_CPP_Class (Etype (Typ)) - or else Is_Interface (Typ) - then - Old_Tag1 := - Unchecked_Convert_To (Generalized_Tag, - Make_Integer_Literal (Loc, 0)); - Old_Tag2 := - Unchecked_Convert_To (Generalized_Tag, - Make_Integer_Literal (Loc, 0)); - - else - Old_Tag1 := - New_Reference_To - (Node (First_Elmt (Access_Disp_Table (Etype (Typ)))), Loc); - Old_Tag2 := - New_Reference_To - (Node (First_Elmt (Access_Disp_Table (Etype (Typ)))), Loc); - end if; - - if Typ /= Etype (Typ) - and then not Is_Interface (Typ) - and then not Restriction_Active (No_Dispatching_Calls) - then - -- Generate: Inherit_DT (parent'tag, DT_Ptr, nb_prim of parent); - - if not Is_Interface (Etype (Typ)) then - if Restriction_Active (No_Dispatching_Calls) then - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Inherit_DT, - Args => New_List ( - Node1 => Old_Tag1, - Node2 => New_Reference_To (DT_Ptr, Loc), - Node3 => Make_Integer_Literal (Loc, Uint_0)))); - else - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Inherit_DT, - Args => New_List ( - Node1 => Old_Tag1, - Node2 => New_Reference_To (DT_Ptr, Loc), - Node3 => Make_Integer_Literal (Loc, - DT_Entry_Count - (First_Tag_Component (Etype (Typ))))))); - 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 - declare - Sec_DT_Ancestor : Elmt_Id := - Next_Elmt - (First_Elmt - (Access_Disp_Table (Etype (Typ)))); - Sec_DT_Typ : Elmt_Id := - Next_Elmt - (First_Elmt - (Access_Disp_Table (Typ))); - - procedure Copy_Secondary_DTs (Typ : Entity_Id); - -- Local procedure required to climb through the ancestors and - -- copy the contents of all their secondary dispatch tables. - - ------------------------ - -- Copy_Secondary_DTs -- - ------------------------ - - procedure Copy_Secondary_DTs (Typ : Entity_Id) is - E : Entity_Id; - Iface : Elmt_Id; - - begin - -- Climb to the ancestor (if any) handling private types - - if Present (Full_View (Etype (Typ))) then - if Full_View (Etype (Typ)) /= Typ then - Copy_Secondary_DTs (Full_View (Etype (Typ))); - end if; - - elsif Etype (Typ) /= Typ then - Copy_Secondary_DTs (Etype (Typ)); - end if; - - if Present (Abstract_Interfaces (Typ)) - and then not Is_Empty_Elmt_List - (Abstract_Interfaces (Typ)) - then - Iface := First_Elmt (Abstract_Interfaces (Typ)); - E := First_Entity (Typ); - while Present (E) - and then Present (Node (Sec_DT_Ancestor)) - loop - if Is_Tag (E) and then Chars (E) /= Name_uTag then - if not Is_Interface (Etype (Typ)) then - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Inherit_DT, - Args => New_List ( - Node1 => Unchecked_Convert_To - (RTE (RE_Tag), - New_Reference_To - (Node (Sec_DT_Ancestor), - Loc)), - Node2 => Unchecked_Convert_To - (RTE (RE_Tag), - New_Reference_To - (Node (Sec_DT_Typ), Loc)), - Node3 => Make_Integer_Literal (Loc, - DT_Entry_Count (E))))); - end if; - - Next_Elmt (Sec_DT_Ancestor); - Next_Elmt (Sec_DT_Typ); - Next_Elmt (Iface); - end if; - - Next_Entity (E); - end loop; - end if; - end Copy_Secondary_DTs; - - begin - if Present (Node (Sec_DT_Ancestor)) then - - -- Handle private types - - if Present (Full_View (Typ)) then - Copy_Secondary_DTs (Full_View (Typ)); - else - Copy_Secondary_DTs (Typ); - end if; - end if; - end; - end if; - end if; - - -- Generate: - -- Inherit_TSD (parent'tag, DT_Ptr); - - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Inherit_TSD, - Args => New_List ( - Node1 => Old_Tag2, - Node2 => New_Reference_To (DT_Ptr, Loc)))); - - if not Is_Interface (Typ) then - - -- For types with no controlled components, generate: - -- Set_RC_Offset (DT_Ptr, 0); - - -- For simple types with controlled components, generate: - -- Set_RC_Offset (DT_Ptr, type._record_controller'position); - - -- For complex types with controlled components where the position - -- of the record controller is not statically computable, if there - -- are controlled components at this level, generate: - -- Set_RC_Offset (DT_Ptr, -1); - -- to indicate that the _controller field is right after the _parent - - -- Or if there are no controlled components at this level, generate: - -- Set_RC_Offset (DT_Ptr, -2); - -- to indicate that we need to get the position from the parent. - - declare - Position : Node_Id; - - begin - if not Has_Controlled_Component (Typ) then - Position := Make_Integer_Literal (Loc, 0); - - elsif Etype (Typ) /= Typ - and then Has_Discriminants (Etype (Typ)) - then - if Has_New_Controlled_Component (Typ) then - Position := Make_Integer_Literal (Loc, -1); - else - Position := Make_Integer_Literal (Loc, -2); - end if; - else - Position := - Make_Attribute_Reference (Loc, - Prefix => - Make_Selected_Component (Loc, - Prefix => New_Reference_To (Typ, Loc), - Selector_Name => - New_Reference_To (Controller_Component (Typ), Loc)), - Attribute_Name => Name_Position); - - -- This is not proper Ada code to use the attribute 'Position - -- on something else than an object but this is supported by - -- the back end (see comment on the Bit_Component attribute in - -- sem_attr). So we avoid semantic checking here. - - -- Is this documented in sinfo.ads??? it should be! - - Set_Analyzed (Position); - Set_Etype (Prefix (Position), RTE (RE_Record_Controller)); - Set_Etype (Prefix (Prefix (Position)), Typ); - Set_Etype (Selector_Name (Prefix (Position)), - RTE (RE_Record_Controller)); - Set_Etype (Position, RTE (RE_Storage_Offset)); - end if; - - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_RC_Offset, - Args => New_List ( - Node1 => New_Reference_To (DT_Ptr, Loc), - Node2 => Position))); - end; - - -- Generate: Set_Remotely_Callable (DT_Ptr, Status); where Status is - -- described in E.4 (18) - - declare - Status : Entity_Id; - - begin - Status := - 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 (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_Remotely_Callable, - Args => New_List ( - New_Occurrence_Of (DT_Ptr, Loc), - New_Occurrence_Of (Status, Loc)))); - end; - - if 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; - end if; - - -- Generate: Set_External_Tag (DT_Ptr, exname'Address); - -- Should be the external name not the qualified name??? - - if not Has_External_Tag_Rep_Clause (Typ) then - Append_To (Elab_Code, - Make_DT_Access_Action (Typ, - Action => Set_External_Tag, - Args => New_List ( - Node1 => New_Reference_To (DT_Ptr, Loc), - Node2 => - Make_Attribute_Reference (Loc, - Prefix => New_Reference_To (Exname, Loc), - Attribute_Name => Name_Address)))); - - -- Generate code to register the Tag in the External_Tag hash - -- table for the pure Ada type only. - - -- 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 No_Run_Time_Mode - and then RTE_Available (RE_Register_Tag) - and then Is_RTE (Generalized_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; - end if; - - -- Generate: - -- if No_Reg then - -- <elab_code> - -- 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 implemented interfaces. - - if not Is_Interface (Typ) - and then Num_Ifaces > 0 - then - declare - Position : Int; - - 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_Interface (Etype (Typ)) then - Position := 1; - - 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; - 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 : Int; - 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 : Int; - 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 => Make_DT_Access_Action (Etype (AI_Tag), - DT_Prologue_Size, - No_List), - Right_Opnd => - Make_Op_Multiply (Loc, - Left_Opnd => - Make_DT_Access_Action (Etype (AI_Tag), - DT_Entry_Size, - No_List), - 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 => - Make_DT_Access_Action (Etype (AI_Tag), - DT_Prologue_Size, No_List))))); - - -- 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)))); - - -- Generate: - -- Set_Num_Prim_Ops (T'Tag, Nb_Prim) - - if RTE_Available (RE_Set_Num_Prim_Ops) then - if Empty_DT then - Append_To (Result, - Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (RTE (RE_Set_Num_Prim_Ops), Loc), - Parameter_Associations => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (Iface_DT_Ptr, Loc)), - Make_Integer_Literal (Loc, Uint_0)))); - else - Append_To (Result, - Make_Procedure_Call_Statement (Loc, - Name => New_Reference_To (RTE (RE_Set_Num_Prim_Ops), Loc), - Parameter_Associations => New_List ( - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (Iface_DT_Ptr, Loc)), - Make_Integer_Literal (Loc, Nb_Prim)))); - end if; - end if; - - if Ada_Version >= Ada_05 - and then not Is_Interface (Typ) - and then not Is_Abstract (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 Implements_Interface ( - Typ => Typ, - Kind => Any_Limited_Interface, - Check_Parent => True) - 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; - - ------------------------------------- - -- Make_Select_Specific_Data_Table -- - ------------------------------------- - - function Make_Select_Specific_Data_Table - (Typ : Entity_Id) return List_Id - is - Assignments : constant List_Id := New_List; - Loc : constant Source_Ptr := Sloc (Typ); - - Conc_Typ : Entity_Id; - Decls : List_Id; - DT_Ptr : Entity_Id; - Prim : Entity_Id; - Prim_Als : Entity_Id; - Prim_Elmt : Elmt_Id; - Prim_Pos : Uint; - Nb_Prim : Int := 0; - - type Examined_Array is array (Int range <>) of Boolean; - - function Find_Entry_Index (E : Entity_Id) return Uint; - -- Given an entry, find its index in the visible declarations of the - -- corresponding concurrent type of Typ. - - ---------------------- - -- Find_Entry_Index -- - ---------------------- - - function Find_Entry_Index (E : Entity_Id) return Uint is - Index : Uint := Uint_1; - Subp_Decl : Entity_Id; - - begin - if Present (Decls) - and then not Is_Empty_List (Decls) - then - Subp_Decl := First (Decls); - while Present (Subp_Decl) loop - if Nkind (Subp_Decl) = N_Entry_Declaration then - if Defining_Identifier (Subp_Decl) = E then - return Index; - end if; - - Index := Index + 1; - end if; - - Next (Subp_Decl); - end loop; - end if; - - return Uint_0; - end Find_Entry_Index; - - -- Start of processing for Make_Select_Specific_Data_Table - - begin - pragma Assert (not Restriction_Active (No_Dispatching_Calls)); - - DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ))); - - if Present (Corresponding_Concurrent_Type (Typ)) then - Conc_Typ := Corresponding_Concurrent_Type (Typ); - - if Ekind (Conc_Typ) = E_Protected_Type then - Decls := Visible_Declarations (Protected_Definition ( - Parent (Conc_Typ))); - else - pragma Assert (Ekind (Conc_Typ) = E_Task_Type); - Decls := Visible_Declarations (Task_Definition ( - Parent (Conc_Typ))); - end if; - end if; - - -- Count the non-predefined primitive operations - - Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); - while Present (Prim_Elmt) loop - if not Is_Predefined_Dispatching_Operation (Node (Prim_Elmt)) then - Nb_Prim := Nb_Prim + 1; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - - declare - Examined : Examined_Array (1 .. Nb_Prim) := (others => False); - - begin - Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); - while Present (Prim_Elmt) loop - Prim := Node (Prim_Elmt); - Prim_Pos := DT_Position (Prim); - - if not Is_Predefined_Dispatching_Operation (Prim) then - pragma Assert (UI_To_Int (Prim_Pos) <= Nb_Prim); - - if Examined (UI_To_Int (Prim_Pos)) then - goto Continue; - else - Examined (UI_To_Int (Prim_Pos)) := True; - end if; - - -- The current primitive overrides an interface-level - -- subprogram - - if Present (Abstract_Interface_Alias (Prim)) then - - -- Set the primitive operation kind regardless of subprogram - -- type. Generate: - -- Ada.Tags.Set_Prim_Op_Kind (DT_Ptr, <position>, <kind>); - - 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 (Prim, Typ)))); - - -- Retrieve the root of the alias chain if one is present - - if Present (Alias (Prim)) then - Prim_Als := Prim; - while Present (Alias (Prim_Als)) loop - Prim_Als := Alias (Prim_Als); - end loop; - else - Prim_Als := Empty; - end if; - - -- In the case of an entry wrapper, set the entry index - - if Ekind (Prim) = E_Procedure - and then Present (Prim_Als) - and then Is_Primitive_Wrapper (Prim_Als) - and then Ekind (Wrapped_Entity (Prim_Als)) = E_Entry - then - - -- Generate: - -- Ada.Tags.Set_Entry_Index - -- (DT_Ptr, <position>, <index>); - - 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)))))); - end if; - end if; - end if; - - <<Continue>> - - Next_Elmt (Prim_Elmt); - end loop; - end; - - return Assignments; - end Make_Select_Specific_Data_Table; - - ----------------------------------- - -- Original_View_In_Visible_Part -- - ----------------------------------- - - function Original_View_In_Visible_Part (Typ : Entity_Id) return Boolean is - Scop : constant Entity_Id := Scope (Typ); - - begin - -- The scope must be a package - - if Ekind (Scop) /= E_Package - and then Ekind (Scop) /= E_Generic_Package - then - return False; - end if; - - -- A type with a private declaration has a private view declared in - -- the visible part. - - if Has_Private_Declaration (Typ) then - return True; - end if; - - return List_Containing (Parent (Typ)) = - Visible_Declarations (Specification (Unit_Declaration_Node (Scop))); - end Original_View_In_Visible_Part; - - ------------------ - -- Prim_Op_Kind -- - ------------------ - - function Prim_Op_Kind - (Prim : Entity_Id; - Typ : Entity_Id) return Node_Id - is - Full_Typ : Entity_Id := Typ; - Loc : constant Source_Ptr := Sloc (Prim); - Prim_Op : Entity_Id; - - begin - -- Retrieve the original primitive operation - - Prim_Op := Prim; - while Present (Alias (Prim_Op)) loop - Prim_Op := Alias (Prim_Op); - end loop; - - if Ekind (Typ) = E_Record_Type - and then Present (Corresponding_Concurrent_Type (Typ)) - then - Full_Typ := Corresponding_Concurrent_Type (Typ); - end if; - - if Ekind (Prim_Op) = E_Function then - - -- Protected function - - if Ekind (Full_Typ) = E_Protected_Type then - return New_Reference_To (RTE (RE_POK_Protected_Function), Loc); - - -- Task function - - elsif Ekind (Full_Typ) = E_Task_Type then - return New_Reference_To (RTE (RE_POK_Task_Function), Loc); - - -- Regular function - - else - return New_Reference_To (RTE (RE_POK_Function), Loc); - end if; - - else - pragma Assert (Ekind (Prim_Op) = E_Procedure); - - if Ekind (Full_Typ) = E_Protected_Type then - - -- Protected entry - - if Is_Primitive_Wrapper (Prim_Op) - and then Ekind (Wrapped_Entity (Prim_Op)) = E_Entry - then - return New_Reference_To (RTE (RE_POK_Protected_Entry), Loc); - - -- Protected procedure - - else - return New_Reference_To (RTE (RE_POK_Protected_Procedure), Loc); - end if; - - elsif Ekind (Full_Typ) = E_Task_Type then - - -- Task entry - - if Is_Primitive_Wrapper (Prim_Op) - and then Ekind (Wrapped_Entity (Prim_Op)) = E_Entry - then - return New_Reference_To (RTE (RE_POK_Task_Entry), Loc); - - -- Task "procedure". These are the internally Expander-generated - -- procedures (task body for instance). - - else - return New_Reference_To (RTE (RE_POK_Task_Procedure), Loc); - end if; - - -- Regular procedure - - else - return New_Reference_To (RTE (RE_POK_Procedure), Loc); - end if; - end if; - end Prim_Op_Kind; - - ------------------------- - -- Set_All_DT_Position -- - ------------------------- - - procedure Set_All_DT_Position (Typ : Entity_Id) is - Parent_Typ : constant Entity_Id := Etype (Typ); - Root_Typ : constant Entity_Id := Root_Type (Typ); - First_Prim : constant Elmt_Id := First_Elmt (Primitive_Operations (Typ)); - The_Tag : constant Entity_Id := First_Tag_Component (Typ); - - Adjusted : Boolean := False; - Finalized : Boolean := False; - - Count_Prim : Int; - DT_Length : Int; - Nb_Prim : Int; - Parent_EC : Int; - Prim : Entity_Id; - Prim_Elmt : Elmt_Id; - - procedure Validate_Position (Prim : Entity_Id); - -- Check that the position assignated to Prim is completely safe - -- (it has not been assigned to a previously defined primitive - -- operation of Typ) - - ----------------------- - -- Validate_Position -- - ----------------------- - - procedure Validate_Position (Prim : Entity_Id) is - Prim_Elmt : Elmt_Id; - - begin - Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); - while Present (Prim_Elmt) - and then Node (Prim_Elmt) /= Prim - loop - -- Primitive operations covering abstract interfaces are - -- allocated later - - if Present (Abstract_Interface_Alias (Node (Prim_Elmt))) then - null; - - -- Predefined dispatching operations are completely safe. They - -- are allocated at fixed positions in a separate table. - - elsif Is_Predefined_Dispatching_Operation (Node (Prim_Elmt)) then - null; - - -- Aliased subprograms are safe - - elsif Present (Alias (Prim)) then - null; - - elsif DT_Position (Node (Prim_Elmt)) = DT_Position (Prim) then - - -- Handle aliased subprograms - - declare - Op_1 : Entity_Id; - Op_2 : Entity_Id; - - begin - Op_1 := Node (Prim_Elmt); - loop - if Present (Overridden_Operation (Op_1)) then - Op_1 := Overridden_Operation (Op_1); - elsif Present (Alias (Op_1)) then - Op_1 := Alias (Op_1); - else - exit; - end if; - end loop; - - Op_2 := Prim; - loop - if Present (Overridden_Operation (Op_2)) then - Op_2 := Overridden_Operation (Op_2); - elsif Present (Alias (Op_2)) then - Op_2 := Alias (Op_2); - else - exit; - end if; - end loop; - - if Op_1 /= Op_2 then - raise Program_Error; - end if; - end; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - end Validate_Position; - - -- Start of processing for Set_All_DT_Position - - begin - -- Get Entry_Count of the parent - - if Parent_Typ /= Typ - and then DT_Entry_Count (First_Tag_Component (Parent_Typ)) /= No_Uint - then - Parent_EC := UI_To_Int (DT_Entry_Count - (First_Tag_Component (Parent_Typ))); - else - Parent_EC := 0; - end if; - - -- C++ Case, check that pragma CPP_Class, CPP_Virtual and CPP_Vtable - -- give a coherent set of information - - if Is_CPP_Class (Root_Typ) then - - -- Compute the number of primitive operations in the main Vtable - -- Set their position: - -- - where it was set if overriden or inherited - -- - after the end of the parent vtable otherwise - - Prim_Elmt := First_Prim; - Nb_Prim := 0; - while Present (Prim_Elmt) loop - Prim := Node (Prim_Elmt); - - if not Is_CPP_Class (Typ) then - Set_DTC_Entity (Prim, The_Tag); - - elsif Present (Alias (Prim)) then - Set_DTC_Entity (Prim, DTC_Entity (Alias (Prim))); - Set_DT_Position (Prim, DT_Position (Alias (Prim))); - - elsif No (DTC_Entity (Prim)) and then Is_CPP_Class (Typ) then - Error_Msg_NE ("is a primitive operation of&," & - " pragma Cpp_Virtual required", Prim, Typ); - end if; - - if DTC_Entity (Prim) = The_Tag then - - -- Get the slot from the parent subprogram if any - - declare - H : Entity_Id; - - begin - H := Homonym (Prim); - while Present (H) loop - if Present (DTC_Entity (H)) - and then Root_Type (Scope (DTC_Entity (H))) = Root_Typ - then - Set_DT_Position (Prim, DT_Position (H)); - exit; - end if; - - H := Homonym (H); - end loop; - end; - - -- Otherwise take the canonical slot after the end of the - -- parent Vtable - - if DT_Position (Prim) = No_Uint then - Nb_Prim := Nb_Prim + 1; - Set_DT_Position (Prim, UI_From_Int (Parent_EC + Nb_Prim)); - - elsif UI_To_Int (DT_Position (Prim)) > Parent_EC then - Nb_Prim := Nb_Prim + 1; - end if; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - - -- Check that the declared size of the Vtable is bigger or equal - -- than the number of primitive operations (if bigger it means that - -- some of the c++ virtual functions were not imported, that is - -- allowed). - - if DT_Entry_Count (The_Tag) = No_Uint - or else not Is_CPP_Class (Typ) - then - Set_DT_Entry_Count (The_Tag, UI_From_Int (Parent_EC + Nb_Prim)); - - elsif UI_To_Int (DT_Entry_Count (The_Tag)) < Parent_EC + Nb_Prim then - Error_Msg_N ("not enough room in the Vtable for all virtual" - & " functions", The_Tag); - end if; - - -- Check that Positions are not duplicate nor outside the range of - -- the Vtable. - - declare - Size : constant Int := UI_To_Int (DT_Entry_Count (The_Tag)); - Pos : Int; - Prim_Pos_Table : array (1 .. Size) of Entity_Id := - (others => Empty); - - begin - Prim_Elmt := First_Prim; - while Present (Prim_Elmt) loop - Prim := Node (Prim_Elmt); - - if DTC_Entity (Prim) = The_Tag then - Pos := UI_To_Int (DT_Position (Prim)); - - if Pos not in Prim_Pos_Table'Range then - Error_Msg_N - ("position not in range of virtual table", Prim); - - elsif Present (Prim_Pos_Table (Pos)) then - Error_Msg_NE ("cannot be at the same position in the" - & " vtable than&", Prim, Prim_Pos_Table (Pos)); - - else - Prim_Pos_Table (Pos) := Prim; - end if; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - end; - - -- Generate listing showing the contents of the dispatch tables - - if Debug_Flag_ZZ then - Write_DT (Typ); - end if; - - -- For regular Ada tagged types, just set the DT_Position for - -- each primitive operation. Perform some sanity checks to avoid - -- to build completely inconsistant dispatch tables. - - -- Note that the _Size primitive is always set at position 1 in order - -- to comply with the needs of Ada.Tags.Parent_Size (see documentation - -- in Ada.Tags). - - else - -- First stage: Set the DTC entity of all the primitive operations - -- This is required to properly read the DT_Position attribute in - -- the latter stages. - - Prim_Elmt := First_Prim; - Count_Prim := 0; - while Present (Prim_Elmt) loop - Count_Prim := Count_Prim + 1; - Prim := Node (Prim_Elmt); - - -- Ada 2005 (AI-251) - - if Present (Abstract_Interface_Alias (Prim)) - and then Is_Interface (Scope (DTC_Entity - (Abstract_Interface_Alias (Prim)))) - then - Set_DTC_Entity (Prim, - Find_Interface_Tag - (T => Typ, - Iface => Scope (DTC_Entity - (Abstract_Interface_Alias (Prim))))); - - else - Set_DTC_Entity (Prim, The_Tag); - end if; - - -- Clear any previous value of the DT_Position attribute. In this - -- way we ensure that the final position of all the primitives is - -- stablished by the following stages of this algorithm. - - Set_DT_Position (Prim, No_Uint); - - Next_Elmt (Prim_Elmt); - end loop; - - declare - Fixed_Prim : array (Int range 0 .. Parent_EC + Count_Prim) - of Boolean := (others => False); - - E : Entity_Id; - - begin - -- Second stage: Register fixed entries - - Nb_Prim := 0; - Prim_Elmt := First_Prim; - while Present (Prim_Elmt) loop - Prim := Node (Prim_Elmt); - - -- Predefined primitives have a separate table and all its - -- entries are at predefined fixed positions - - if Is_Predefined_Dispatching_Operation (Prim) then - Set_DT_Position (Prim, Default_Prim_Op_Position (Prim)); - - -- Overriding interface primitives of an ancestor - - elsif DT_Position (Prim) = No_Uint - and then Present (Abstract_Interface_Alias (Prim)) - and then Present (DTC_Entity - (Abstract_Interface_Alias (Prim))) - and then DT_Position (Abstract_Interface_Alias (Prim)) - /= No_Uint - and then Is_Inherited_Operation (Prim) - and then Is_Ancestor (Scope - (DTC_Entity - (Abstract_Interface_Alias (Prim))), - Typ) - then - Set_DT_Position (Prim, - DT_Position (Abstract_Interface_Alias (Prim))); - Set_DT_Position (Alias (Prim), - DT_Position (Abstract_Interface_Alias (Prim))); - Fixed_Prim (UI_To_Int (DT_Position (Prim))) := True; - - -- Overriding primitives must use the same entry as the - -- overriden primitive - - elsif DT_Position (Prim) = No_Uint - and then Present (Alias (Prim)) - and then Present (DTC_Entity (Alias (Prim))) - and then DT_Position (Alias (Prim)) /= No_Uint - and then Is_Inherited_Operation (Prim) - and then Is_Ancestor (Scope (DTC_Entity (Alias (Prim))), Typ) - then - E := Alias (Prim); - while not (Present (DTC_Entity (E)) - or else DT_Position (E) = No_Uint) - and then Present (Alias (E)) - loop - E := Alias (E); - end loop; - - pragma Assert (Present (DTC_Entity (E)) - and then - DT_Position (E) /= No_Uint); - - Set_DT_Position (Prim, DT_Position (E)); - Fixed_Prim (UI_To_Int (DT_Position (E))) := True; - - -- If this is not the last element in the chain continue - -- traversing the chain. This is required to properly - -- handling renamed primitives - - while Present (Alias (E)) loop - E := Alias (E); - Fixed_Prim (UI_To_Int (DT_Position (E))) := True; - end loop; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - - -- Third stage: Fix the position of all the new primitives - -- Entries associated with primitives covering interfaces - -- are handled in a latter round. - - Prim_Elmt := First_Prim; - while Present (Prim_Elmt) loop - Prim := Node (Prim_Elmt); - - -- Skip primitives previously set entries - - if Is_Predefined_Dispatching_Operation (Prim) then - null; - - elsif DT_Position (Prim) /= No_Uint then - null; - - elsif Etype (DTC_Entity (Prim)) /= RTE (RE_Tag) then - null; - - -- Primitives covering interface primitives are - -- handled later - - elsif Present (Abstract_Interface_Alias (Prim)) then - null; - - else - -- Take the next available position in the DT - - loop - Nb_Prim := Nb_Prim + 1; - exit when not Fixed_Prim (Nb_Prim); - end loop; - - Set_DT_Position (Prim, UI_From_Int (Nb_Prim)); - Fixed_Prim (Nb_Prim) := True; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - end; - - -- Fourth stage: Complete the decoration of primitives covering - -- interfaces (that is, propagate the DT_Position attribute - -- from the aliased primitive) - - Prim_Elmt := First_Prim; - while Present (Prim_Elmt) loop - Prim := Node (Prim_Elmt); - - if DT_Position (Prim) = No_Uint - and then Present (Abstract_Interface_Alias (Prim)) - then - -- Check if this entry will be placed in the primary DT - - if Etype (DTC_Entity (Abstract_Interface_Alias (Prim))) - = RTE (RE_Tag) - then - pragma Assert (DT_Position (Alias (Prim)) /= No_Uint); - Set_DT_Position (Prim, DT_Position (Alias (Prim))); - - -- Otherwise it will be placed in the secondary DT - - else - pragma Assert - (DT_Position (Abstract_Interface_Alias (Prim)) /= No_Uint); - - Set_DT_Position (Prim, - DT_Position (Abstract_Interface_Alias (Prim))); - end if; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - - -- Generate listing showing the contents of the dispatch tables. - -- This action is done before some further static checks because - -- in case of critical errors caused by a wrong dispatch table - -- we need to see the contents of such table. - - if Debug_Flag_ZZ then - Write_DT (Typ); - end if; - - -- Final stage: Ensure that the table is correct plus some further - -- verifications concerning the primitives. - - Prim_Elmt := First_Prim; - DT_Length := 0; - while Present (Prim_Elmt) loop - Prim := Node (Prim_Elmt); - - -- At this point all the primitives MUST have a position - -- in the dispatch table - - if DT_Position (Prim) = No_Uint then - raise Program_Error; - end if; - - -- Calculate real size of the dispatch table - - if not Is_Predefined_Dispatching_Operation (Prim) - and then UI_To_Int (DT_Position (Prim)) > DT_Length - then - DT_Length := UI_To_Int (DT_Position (Prim)); - end if; - - -- Ensure that the asignated position to non-predefined - -- dispatching operations in the dispatch table is correct. - - if not Is_Predefined_Dispatching_Operation (Prim) then - Validate_Position (Prim); - end if; - - if Chars (Prim) = Name_Finalize then - Finalized := True; - end if; - - if Chars (Prim) = Name_Adjust then - Adjusted := True; - end if; - - -- An abstract operation cannot be declared in the private part - -- for a visible abstract type, because it could never be over- - -- ridden. For explicit declarations this is checked at the - -- point of declaration, but for inherited operations it must - -- be done when building the dispatch table. Input is excluded - -- because - - if Is_Abstract (Typ) - and then Is_Abstract (Prim) - and then Present (Alias (Prim)) - and then Is_Derived_Type (Typ) - and then In_Private_Part (Current_Scope) - and then - List_Containing (Parent (Prim)) = - Private_Declarations - (Specification (Unit_Declaration_Node (Current_Scope))) - and then Original_View_In_Visible_Part (Typ) - then - -- We exclude Input and Output stream operations because - -- Limited_Controlled inherits useless Input and Output - -- stream operations from Root_Controlled, which can - -- never be overridden. - - if not Is_TSS (Prim, TSS_Stream_Input) - and then - not Is_TSS (Prim, TSS_Stream_Output) - then - Error_Msg_NE - ("abstract inherited private operation&" & - " must be overridden ('R'M 3.9.3(10))", - Parent (Typ), Prim); - end if; - end if; - - Next_Elmt (Prim_Elmt); - end loop; - - -- Additional check - - if Is_Controlled (Typ) then - if not Finalized then - Error_Msg_N - ("controlled type has no explicit Finalize method?", Typ); - - elsif not Adjusted then - Error_Msg_N - ("controlled type has no explicit Adjust method?", Typ); - end if; - end if; - - -- Set the final size of the Dispatch Table - - 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??? - - if not Has_Private_Declaration (Typ) then - pragma Assert ( - DT_Entry_Count (The_Tag) >= - DT_Entry_Count (First_Tag_Component (Parent_Typ))); - null; - end if; - end if; - end Set_All_DT_Position; - - ----------------------------- - -- Set_Default_Constructor -- - ----------------------------- - - procedure Set_Default_Constructor (Typ : Entity_Id) is - Loc : Source_Ptr; - Init : Entity_Id; - Param : Entity_Id; - E : Entity_Id; - - begin - -- Look for the default constructor entity. For now only the - -- default constructor has the flag Is_Constructor. - - E := Next_Entity (Typ); - while Present (E) - and then (Ekind (E) /= E_Function or else not Is_Constructor (E)) - loop - Next_Entity (E); - end loop; - - -- Create the init procedure - - if Present (E) then - Loc := Sloc (E); - Init := Make_Defining_Identifier (Loc, Make_Init_Proc_Name (Typ)); - Param := Make_Defining_Identifier (Loc, Name_X); - - Discard_Node ( - Make_Subprogram_Declaration (Loc, - Make_Procedure_Specification (Loc, - Defining_Unit_Name => Init, - Parameter_Specifications => New_List ( - Make_Parameter_Specification (Loc, - Defining_Identifier => Param, - Parameter_Type => New_Reference_To (Typ, Loc)))))); - - Set_Init_Proc (Typ, Init); - Set_Is_Imported (Init); - Set_Interface_Name (Init, Interface_Name (E)); - Set_Convention (Init, Convention_C); - Set_Is_Public (Init); - Set_Has_Completion (Init); - - -- If there are no constructors, mark the type as abstract since we - -- won't be able to declare objects of that type. - - else - Set_Is_Abstract (Typ); - 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) and then RTE_Available (RE_Tagged_Kind)); - - -- 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 -- - -------------- - - procedure Write_DT (Typ : Entity_Id) is - Elmt : Elmt_Id; - Prim : Node_Id; - - begin - -- Protect this procedure against wrong usage. Required because it will - -- be used directly from GDB - - if not (Typ in First_Node_Id .. Last_Node_Id) - or else not Is_Tagged_Type (Typ) - then - Write_Str ("wrong usage: Write_DT must be used with tagged types"); - Write_Eol; - return; - end if; - - Write_Int (Int (Typ)); - Write_Str (": "); - Write_Name (Chars (Typ)); - - if Is_Interface (Typ) then - Write_Str (" is interface"); - end if; - - Write_Eol; - - Elmt := First_Elmt (Primitive_Operations (Typ)); - while Present (Elmt) loop - Prim := Node (Elmt); - Write_Str (" - "); - - -- Indicate if this primitive will be allocated in the primary - -- dispatch table or in a secondary dispatch table associated - -- with an abstract interface type - - if Present (DTC_Entity (Prim)) then - if Etype (DTC_Entity (Prim)) = RTE (RE_Tag) then - Write_Str ("[P] "); - else - Write_Str ("[s] "); - end if; - end if; - - -- Output the node of this primitive operation and its name - - Write_Int (Int (Prim)); - Write_Str (": "); - - if Is_Predefined_Dispatching_Operation (Prim) then - Write_Str ("(predefined) "); - end if; - - Write_Name (Chars (Prim)); - - -- Indicate if this primitive has an aliased primitive - - if Present (Alias (Prim)) then - Write_Str (" (alias = "); - Write_Int (Int (Alias (Prim))); - - -- If the DTC_Entity attribute is already set we can also output - -- the name of the interface covered by this primitive (if any) - - if Present (DTC_Entity (Alias (Prim))) - and then Is_Interface (Scope (DTC_Entity (Alias (Prim)))) - then - Write_Str (" from interface "); - Write_Name (Chars (Scope (DTC_Entity (Alias (Prim))))); - end if; - - if Present (Abstract_Interface_Alias (Prim)) then - Write_Str (", AI_Alias of "); - Write_Name (Chars (Scope (DTC_Entity - (Abstract_Interface_Alias (Prim))))); - Write_Char (':'); - Write_Int (Int (Abstract_Interface_Alias (Prim))); - end if; - - Write_Str (")"); - end if; - - -- Display the final position of this primitive in its associated - -- (primary or secondary) dispatch table - - if Present (DTC_Entity (Prim)) - and then DT_Position (Prim) /= No_Uint - then - Write_Str (" at #"); - Write_Int (UI_To_Int (DT_Position (Prim))); - end if; - - if Is_Abstract (Prim) then - Write_Str (" is abstract;"); - end if; - - Write_Eol; - - Next_Elmt (Elmt); - end loop; - end Write_DT; - -end Exp_Disp; |