Commit 3ca505dc by Javier Miranda Committed by Arnaud Charlet

exp_ch3.adb (Build_Record_Init_Proc/Freeze_Record_Type): Reimplementation of the…

exp_ch3.adb (Build_Record_Init_Proc/Freeze_Record_Type): Reimplementation of the support for abstract interface types in order to leave...

2005-07-07  Javier Miranda  <miranda@adacore.com>

	* exp_ch3.adb (Build_Record_Init_Proc/Freeze_Record_Type):
	Reimplementation of the support for abstract interface types in order
	to leave the code more clear and easy to maintain.

	* exp_ch6.adb (Freeze_Subprogram): Reimplementation of the support for
	abstract interface types in order to leave the code clearer and easier
	to maintain.

	* exp_disp.ads, exp_disp.adb (Fill_DT_Entry): Part of its functionality
	is now implemented by the new subprogram Fill_Secondary_DT_Entry.
	(Fill_Secondary_DT_Entry): Generate the code necessary to fill the
	appropriate entry of the secondary dispatch table.
	(Make_DT): Add code to inherit the secondary dispatch tables of
	the ancestors.

	* exp_util.adb (Find_Interface_Tag/Find_Interface_ADT): Instead of
	implementing both functionalities by means of a common routine, each
	routine has its own code.

From-SVN: r101694
parent 69601f74
...@@ -1361,10 +1361,6 @@ package body Exp_Ch3 is ...@@ -1361,10 +1361,6 @@ package body Exp_Ch3 is
Rec_Type : Entity_Id; Rec_Type : Entity_Id;
Set_Tag : Entity_Id := Empty; Set_Tag : Entity_Id := Empty;
ADT : Elmt_Id;
Aux_N : Node_Id;
Aux_Comp : Node_Id;
function Build_Assignment (Id : Entity_Id; N : Node_Id) return List_Id; function Build_Assignment (Id : Entity_Id; N : Node_Id) return List_Id;
-- Build a assignment statement node which assigns to record -- Build a assignment statement node which assigns to record
-- component its default expression if defined. The left hand side -- component its default expression if defined. The left hand side
...@@ -1735,6 +1731,100 @@ package body Exp_Ch3 is ...@@ -1735,6 +1731,100 @@ package body Exp_Ch3 is
Record_Extension_Node : Node_Id; Record_Extension_Node : Node_Id;
Init_Tag : Node_Id; Init_Tag : Node_Id;
procedure Init_Secondary_Tags (Typ : Entity_Id);
-- Ada 2005 (AI-251): Initialize the tags of all the secondary
-- tables associated with abstract interface types
-------------------------
-- Init_Secondary_Tags --
-------------------------
procedure Init_Secondary_Tags (Typ : Entity_Id) is
ADT : Elmt_Id;
procedure Init_Secondary_Tags_Internal (Typ : Entity_Id);
-- Internal subprogram used to recursively climb to the root type
----------------------------------
-- Init_Secondary_Tags_Internal --
----------------------------------
procedure Init_Secondary_Tags_Internal (Typ : Entity_Id) is
E : Entity_Id;
Aux_N : Node_Id;
begin
if not Is_Interface (Typ)
and then Etype (Typ) /= Typ
then
Init_Secondary_Tags_Internal (Etype (Typ));
end if;
if Present (Abstract_Interfaces (Typ))
and then not Is_Empty_Elmt_List (Abstract_Interfaces (Typ))
then
E := First_Entity (Typ);
while Present (E) loop
if Is_Tag (E)
and then Chars (E) /= Name_uTag
then
Aux_N := Node (ADT);
pragma Assert (Present (Aux_N));
-- Initialize the pointer to the secondary DT
-- associated with the interface
Append_To (Body_Stmts,
Make_Assignment_Statement (Loc,
Name =>
Make_Selected_Component (Loc,
Prefix => Make_Identifier (Loc, Name_uInit),
Selector_Name =>
New_Reference_To (E, Loc)),
Expression =>
New_Reference_To (Aux_N, Loc)));
-- Generate:
-- Set_Offset_To_Top (DT_Ptr, n);
Append_To (Body_Stmts,
Make_Procedure_Call_Statement (Loc,
Name => New_Reference_To
(RTE (RE_Set_Offset_To_Top), Loc),
Parameter_Associations => New_List (
Unchecked_Convert_To (RTE (RE_Tag),
New_Reference_To (Aux_N, Loc)),
Unchecked_Convert_To (RTE (RE_Storage_Offset),
Make_Attribute_Reference (Loc,
Prefix =>
Make_Selected_Component (Loc,
Prefix => Make_Identifier (Loc,
Name_uInit),
Selector_Name => New_Reference_To
(E, Loc)),
Attribute_Name => Name_Position)))));
Next_Elmt (ADT);
end if;
Next_Entity (E);
end loop;
end if;
end Init_Secondary_Tags_Internal;
-- Start of processing for Init_Secondary_Tags
begin
-- Skip the first _Tag, which is the main tag of the
-- tagged type. Following tags correspond with abstract
-- interfaces.
ADT := Next_Elmt (First_Elmt (Access_Disp_Table (Typ)));
Init_Secondary_Tags_Internal (Typ);
end Init_Secondary_Tags;
-- Start of processing for Build_Init_Procedure
begin begin
Body_Stmts := New_List; Body_Stmts := New_List;
Body_Node := New_Node (N_Subprogram_Body, Loc); Body_Node := New_Node (N_Subprogram_Body, Loc);
...@@ -1864,55 +1954,10 @@ package body Exp_Ch3 is ...@@ -1864,55 +1954,10 @@ package body Exp_Ch3 is
-- Ada 2005 (AI-251): Initialization of all the tags -- Ada 2005 (AI-251): Initialization of all the tags
-- corresponding with abstract interfaces -- corresponding with abstract interfaces
if Present (First_Tag_Component (Rec_Type)) then if Ada_Version >= Ada_05
and then not Is_Interface (Rec_Type)
-- Skip the first _Tag, which is the main tag of the then
-- tagged type. Following tags correspond with abstract Init_Secondary_Tags (Rec_Type);
-- interfaces.
Aux_Comp :=
Next_Tag_Component (First_Tag_Component (Rec_Type));
ADT := Next_Elmt (First_Elmt (Access_Disp_Table (Rec_Type)));
while Present (ADT) loop
Aux_N := Node (ADT);
-- Initialize the pointer to the secondary DT associated
-- with the interface
Append_To (Body_Stmts,
Make_Assignment_Statement (Loc,
Name =>
Make_Selected_Component (Loc,
Prefix => Make_Identifier (Loc, Name_uInit),
Selector_Name =>
New_Reference_To (Aux_Comp, Loc)),
Expression =>
New_Reference_To (Aux_N, Loc)));
-- Generate:
-- Set_Offset_To_Top (DT_Ptr, n);
Append_To (Body_Stmts,
Make_Procedure_Call_Statement (Loc,
Name => New_Reference_To (RTE (RE_Set_Offset_To_Top),
Loc),
Parameter_Associations => New_List (
Unchecked_Convert_To (RTE (RE_Tag),
New_Reference_To (Aux_N, Loc)),
Unchecked_Convert_To (RTE (RE_Storage_Offset),
Make_Attribute_Reference (Loc,
Prefix =>
Make_Selected_Component (Loc,
Prefix => Make_Identifier (Loc,
Name_uInit),
Selector_Name => New_Reference_To
(Aux_Comp, Loc)),
Attribute_Name => Name_Position)))));
Aux_Comp := Next_Tag_Component (Aux_Comp);
Next_Elmt (ADT);
end loop;
end if; end if;
else else
...@@ -4480,36 +4525,6 @@ package body Exp_Ch3 is ...@@ -4480,36 +4525,6 @@ package body Exp_Ch3 is
Expand_Tagged_Root (Def_Id); Expand_Tagged_Root (Def_Id);
end if; end if;
-- Build the secondary tables
if not Java_VM
and then Present (Abstract_Interfaces (Def_Id))
and then not Is_Empty_Elmt_List (Abstract_Interfaces (Def_Id))
then
declare
E : Entity_Id;
Result : List_Id;
ADT : Elist_Id := Access_Disp_Table (Def_Id);
begin
E := First_Entity (Def_Id);
while Present (E) loop
if Is_Tag (E) and then Chars (E) /= Name_uTag then
Make_Abstract_Interface_DT
(AI_Tag => E,
Acc_Disp_Tables => ADT,
Result => Result);
Append_Freeze_Actions (Def_Id, Result);
end if;
Next_Entity (E);
end loop;
Set_Access_Disp_Table (Def_Id, ADT);
end;
end if;
-- Unfreeze momentarily the type to add the predefined primitives -- Unfreeze momentarily the type to add the predefined primitives
-- operations. The reason we unfreeze is so that these predefined -- operations. The reason we unfreeze is so that these predefined
-- operations will indeed end up as primitive operations (which -- operations will indeed end up as primitive operations (which
...@@ -4533,7 +4548,55 @@ package body Exp_Ch3 is ...@@ -4533,7 +4548,55 @@ package body Exp_Ch3 is
-- dispatching mechanism is handled internally by the JVM. -- dispatching mechanism is handled internally by the JVM.
if not Java_VM then if not Java_VM then
Append_Freeze_Actions (Def_Id, Make_DT (Def_Id));
-- Ada 2005 (AI-251): Build the secondary dispatch tables
declare
ADT : Elist_Id := Access_Disp_Table (Def_Id);
procedure Add_Secondary_Tables (Typ : Entity_Id);
-- Comment required ???
--------------------------
-- Add_Secondary_Tables --
--------------------------
procedure Add_Secondary_Tables (Typ : Entity_Id) is
E : Entity_Id;
Result : List_Id;
begin
if Etype (Typ) /= Typ then
Add_Secondary_Tables (Etype (Typ));
end if;
if Present (Abstract_Interfaces (Typ))
and then not Is_Empty_Elmt_List
(Abstract_Interfaces (Typ))
then
E := First_Entity (Typ);
while Present (E) loop
if Is_Tag (E) and then Chars (E) /= Name_uTag then
Make_Abstract_Interface_DT
(AI_Tag => E,
Acc_Disp_Tables => ADT,
Result => Result);
Append_Freeze_Actions (Def_Id, Result);
end if;
Next_Entity (E);
end loop;
end if;
end Add_Secondary_Tables;
-- Start of processing to build secondary dispatch tables
begin
Add_Secondary_Tables (Def_Id);
Set_Access_Disp_Table (Def_Id, ADT);
Append_Freeze_Actions (Def_Id, Make_DT (Def_Id));
end;
end if; end if;
-- Make sure that the primitives Initialize, Adjust and Finalize -- Make sure that the primitives Initialize, Adjust and Finalize
...@@ -5681,7 +5744,7 @@ package body Exp_Ch3 is ...@@ -5681,7 +5744,7 @@ package body Exp_Ch3 is
Ret_Type => Standard_Integer)); Ret_Type => Standard_Integer));
-- Specs for dispatching stream attributes. -- Specs for dispatching stream attributes
declare declare
Stream_Op_TSS_Names : Stream_Op_TSS_Names :
......
...@@ -4062,37 +4062,157 @@ package body Exp_Ch6 is ...@@ -4062,37 +4062,157 @@ package body Exp_Ch6 is
procedure Freeze_Subprogram (N : Node_Id) is procedure Freeze_Subprogram (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N); Loc : constant Source_Ptr := Sloc (N);
E : constant Entity_Id := Entity (N); E : constant Entity_Id := Entity (N);
Thunk_Id : Entity_Id;
Iface_Tag : Entity_Id;
New_Thunk : Node_Id;
begin procedure Check_Overriding_Inherited_Interfaces (E : Entity_Id);
-- When a primitive is frozen, enter its name in the corresponding -- (Ada 2005): Check if the primitive E covers some interface already
-- dispatch table. If the DTC_Entity field is not set this is an -- implemented by some ancestor of the tagged-type associated with E
-- overridden primitive that can be ignored. We suppress the
-- initialization of the dispatch table entry when Java_VM because procedure Register_Interface_DT_Entry
-- the dispatching mechanism is handled internally by the JVM. (Prim : Entity_Id;
Ancestor_Iface_Prim : Entity_Id := Empty);
-- (Ada 2005): Register an interface primitive in a secondary dispatch
-- table. If Prim overrides an ancestor primitive of its associated
-- tagged-type then Ancestor_Iface_Prim indicates the entity of that
-- immediate ancestor associated with the interface; otherwise Prim and
-- Ancestor_Iface_Prim have the same info.
-------------------------------------------
-- Check_Overriding_Inherited_Interfaces --
-------------------------------------------
procedure Check_Overriding_Inherited_Interfaces (E : Entity_Id) is
Typ : Entity_Id;
Elmt : Elmt_Id;
Prim_Op : Entity_Id;
Overriden_Op : Entity_Id := Empty;
if Is_Dispatching_Operation (E) begin
and then not Is_Abstract (E) if Ada_Version < Ada_05
and then Present (DTC_Entity (E)) or else not Is_Overriding_Operation (E)
and then not Is_CPP_Class (Scope (DTC_Entity (E))) or else Is_Predefined_Dispatching_Operation (E)
and then not Java_VM or else Present (Alias (E))
then then
Check_Overriding_Operation (E); return;
end if;
-- Get the entity associated with this primitive operation
Typ := Scope (DTC_Entity (E));
while Etype (Typ) /= Typ loop
-- Climb to the immediate ancestor
Typ := Etype (Typ);
-- Common case: Primitive subprogram if Present (Abstract_Interfaces (Typ)) then
if not Present (Abstract_Interface_Alias (E)) then -- Look for the overriden subprogram in the primary dispatch
Insert_After (N, Fill_DT_Entry (Sloc (N), E)); -- table of the ancestor.
-- Ada 2005 (AI-251): Primitive subprogram that covers an interface Overriden_Op := Empty;
Elmt := First_Elmt (Primitive_Operations (Typ));
while Present (Elmt) loop
Prim_Op := Node (Elmt);
if DT_Position (Prim_Op) = DT_Position (E)
and then Etype (DTC_Entity (Prim_Op)) = RTE (RE_Tag)
and then not Present (Abstract_Interface_Alias (Prim_Op))
then
if Overriden_Op /= Empty then
raise Program_Error;
end if;
Overriden_Op := Prim_Op;
end if;
Next_Elmt (Elmt);
end loop;
-- if not found this is the first overriding of some
-- abstract interface
if Overriden_Op /= Empty then
Elmt := First_Elmt (Primitive_Operations (Typ));
-- Find the entries associated with interfaces that are
-- alias of this primitive operation in the ancestor
while Present (Elmt) loop
Prim_Op := Node (Elmt);
if Present (Abstract_Interface_Alias (Prim_Op))
and then Alias (Prim_Op) = Overriden_Op
then
Register_Interface_DT_Entry (E, Prim_Op);
end if;
Next_Elmt (Elmt);
end loop;
end if;
end if;
end loop;
end Check_Overriding_Inherited_Interfaces;
---------------------------------
-- Register_Interface_DT_Entry --
---------------------------------
procedure Register_Interface_DT_Entry
(Prim : Entity_Id;
Ancestor_Iface_Prim : Entity_Id := Empty)
is
Prim_Typ : Entity_Id;
Prim_Op : Entity_Id;
Iface_Typ : Entity_Id;
Iface_DT_Ptr : Entity_Id;
Iface_Tag : Entity_Id;
New_Thunk : Node_Id;
Thunk_Id : Entity_Id;
begin
if not Present (Ancestor_Iface_Prim) then
Prim_Typ := Scope (DTC_Entity (Alias (Prim)));
Iface_Typ := Scope (DTC_Entity (Abstract_Interface_Alias (Prim)));
Iface_Tag := Find_Interface_Tag
(T => Prim_Typ,
Iface => Iface_Typ);
-- Generate the code of the thunk only when this primitive
-- operation is associated with a secondary dispatch table
if Etype (Iface_Tag) = RTE (RE_Interface_Tag) then
Thunk_Id := Make_Defining_Identifier (Loc,
New_Internal_Name ('T'));
New_Thunk :=
Expand_Interface_Thunk
(N => Prim,
Thunk_Alias => Alias (Prim),
Thunk_Id => Thunk_Id,
Iface_Tag => Iface_Tag);
Insert_After (N, New_Thunk);
Iface_DT_Ptr :=
Find_Interface_ADT
(T => Prim_Typ,
Iface => Iface_Typ);
Insert_After (New_Thunk,
Fill_Secondary_DT_Entry (Sloc (Prim),
Prim => Prim,
Iface_DT_Ptr => Iface_DT_Ptr,
Thunk_Id => Thunk_Id));
end if;
else else
Iface_Typ :=
Scope (DTC_Entity (Abstract_Interface_Alias
(Ancestor_Iface_Prim)));
Iface_Tag := Iface_Tag :=
Find_Interface_Tag Find_Interface_Tag
(T => Scope (DTC_Entity (Alias (E))), -- Formal Type (T => Scope (DTC_Entity (Alias (Ancestor_Iface_Prim))),
Iface => Scope (DTC_Entity (Abstract_Interface_Alias (E)))); Iface => Iface_Typ);
-- Generate the thunk only if the associated tag is an interface -- Generate the thunk only if the associated tag is an interface
-- tag. The case in which the associated tag is the primary tag -- tag. The case in which the associated tag is the primary tag
...@@ -4107,12 +4227,69 @@ package body Exp_Ch6 is ...@@ -4107,12 +4227,69 @@ package body Exp_Ch6 is
Thunk_Id := Make_Defining_Identifier (Loc, Thunk_Id := Make_Defining_Identifier (Loc,
New_Internal_Name ('T')); New_Internal_Name ('T'));
New_Thunk := Expand_Interface_Thunk (N, Thunk_Id, Iface_Tag); if Present (Alias (Prim)) then
Prim_Op := Alias (Prim);
else
Prim_Op := Prim;
end if;
New_Thunk :=
Expand_Interface_Thunk
(N => Ancestor_Iface_Prim,
Thunk_Alias => Prim_Op,
Thunk_Id => Thunk_Id,
Iface_Tag => Iface_Tag);
Insert_After (N, New_Thunk);
Iface_DT_Ptr :=
Find_Interface_ADT
(T => Scope (DTC_Entity (Prim_Op)),
Iface => Iface_Typ);
Insert_After (New_Thunk, Insert_After (New_Thunk,
Fill_DT_Entry (Sloc (N), Fill_Secondary_DT_Entry (Sloc (Prim),
Prim => E, Prim => Ancestor_Iface_Prim,
Thunk_Id => Thunk_Id)); Iface_DT_Ptr => Iface_DT_Ptr,
Thunk_Id => Thunk_Id));
end if;
end if;
end Register_Interface_DT_Entry;
-- Start of processing for Freeze_Subprogram
begin
-- When a primitive is frozen, enter its name in the corresponding
-- dispatch table. If the DTC_Entity field is not set this is an
-- overridden primitive that can be ignored. We suppress the
-- initialization of the dispatch table entry when Java_VM because
-- the dispatching mechanism is handled internally by the JVM.
if Is_Dispatching_Operation (E)
and then not Is_Abstract (E)
and then Present (DTC_Entity (E))
and then not Java_VM
and then not Is_CPP_Class (Scope (DTC_Entity (E)))
then
Check_Overriding_Operation (E);
if Ada_Version < Ada_05 then
Insert_After (N,
Fill_DT_Entry (Sloc (N), Prim => E));
else
-- Ada 2005 (AI-251): Check if this entry corresponds with
-- a subprogram that covers an abstract interface type
if Present (Abstract_Interface_Alias (E)) then
Register_Interface_DT_Entry (E);
-- Common case: Primitive subprogram
else
Insert_After (N,
Fill_DT_Entry (Sloc (N), Prim => E));
Check_Overriding_Inherited_Interfaces (E);
end if; end if;
end if; end if;
end if; end if;
......
...@@ -902,6 +902,7 @@ package body Exp_Disp is ...@@ -902,6 +902,7 @@ package body Exp_Disp is
function Expand_Interface_Thunk function Expand_Interface_Thunk
(N : Node_Id; (N : Node_Id;
Thunk_Alias : Entity_Id;
Thunk_Id : Entity_Id; Thunk_Id : Entity_Id;
Iface_Tag : Entity_Id) return Node_Id Iface_Tag : Entity_Id) return Node_Id
is is
...@@ -910,7 +911,6 @@ package body Exp_Disp is ...@@ -910,7 +911,6 @@ package body Exp_Disp is
Decl : constant List_Id := New_List; Decl : constant List_Id := New_List;
Formals : constant List_Id := New_List; Formals : constant List_Id := New_List;
Thunk_Tag : constant Node_Id := Iface_Tag; Thunk_Tag : constant Node_Id := Iface_Tag;
Thunk_Alias : constant Entity_Id := Alias (Entity (N));
Target : Entity_Id; Target : Entity_Id;
New_Code : Node_Id; New_Code : Node_Id;
Formal : Node_Id; Formal : Node_Id;
...@@ -950,11 +950,7 @@ package body Exp_Disp is ...@@ -950,11 +950,7 @@ package body Exp_Disp is
if Is_Controlling_Formal (Formal) then if Is_Controlling_Formal (Formal) then
Set_Parameter_Type (New_Formal, Set_Parameter_Type (New_Formal,
New_Reference_To (Etype (First_Entity (Entity (N))), Loc)); New_Reference_To (Etype (First_Entity (N)), Loc));
-- Why is this line silently commented out ???
-- New_Reference_To (Etype (Formal), Loc));
end if; end if;
Append_To (Formals, New_Formal); Append_To (Formals, New_Formal);
...@@ -1150,66 +1146,76 @@ package body Exp_Disp is ...@@ -1150,66 +1146,76 @@ package body Exp_Disp is
end if; end if;
Analyze (New_Code); Analyze (New_Code);
Insert_After (N, New_Code);
return New_Code; return New_Code;
end Expand_Interface_Thunk; end Expand_Interface_Thunk;
------------- -------------------
-- Fill_DT -- -- Fill_DT_Entry --
------------- -------------------
function Fill_DT_Entry function Fill_DT_Entry
(Loc : Source_Ptr; (Loc : Source_Ptr;
Prim : Entity_Id; Prim : Entity_Id) return Node_Id
Thunk_Id : Entity_Id := Empty) return Node_Id
is is
Typ : constant Entity_Id := Scope (DTC_Entity (Prim)); Typ : constant Entity_Id := Scope (DTC_Entity (Prim));
DT_Ptr : Entity_Id := Node (First_Elmt (Access_Disp_Table (Typ))); DT_Ptr : constant Entity_Id :=
Target : Entity_Id; Node (First_Elmt (Access_Disp_Table (Typ)));
Tag : Entity_Id := First_Tag_Component (Typ); Pos : constant Uint := DT_Position (Prim);
Prim_Op : Entity_Id := Prim; Tag : constant Entity_Id := First_Tag_Component (Typ);
begin begin
-- Ada 2005 (AI-251): If we have a thunk available then generate code if Pos = Uint_0 or else Pos > DT_Entry_Count (Tag) then
-- that saves its address in the secondary dispatch table of its raise Program_Error;
-- abstract interface; otherwise save the address of the primitive
-- subprogram in the main virtual table.
if Thunk_Id /= Empty then
Target := Thunk_Id;
else
Target := Prim;
end if; end if;
-- Ada 2005 (AI-251): If the subprogram is the alias of an abstract return
-- interface subprogram then find the correct dispatch table pointer 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
if Present (Abstract_Interface_Alias (Prim)) then Make_Integer_Literal (Loc, Pos), -- Position
Prim_Op := Abstract_Interface_Alias (Prim);
DT_Ptr := Find_Interface_ADT Make_Attribute_Reference (Loc, -- Value
(T => Typ, Prefix => New_Reference_To (Prim, Loc),
Iface => Scope (DTC_Entity (Prim_Op))); Attribute_Name => Name_Address)));
end Fill_DT_Entry;
Tag := First_Tag_Component (Scope (DTC_Entity (Prim_Op))); -----------------------------
end if; -- Fill_Secondary_DT_Entry --
-----------------------------
pragma Assert (DT_Position (Prim_Op) <= DT_Entry_Count (Tag)); function Fill_Secondary_DT_Entry
pragma Assert (DT_Position (Prim_Op) > Uint_0); (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 Pos = Uint_0 or else Pos > DT_Entry_Count (Tag) then
raise Program_Error;
end if;
return return
Make_DT_Access_Action (Typ, Make_DT_Access_Action (Typ,
Action => Set_Prim_Op_Address, Action => Set_Prim_Op_Address,
Args => New_List ( Args => New_List (
Unchecked_Convert_To (RTE (RE_Tag), Unchecked_Convert_To (RTE (RE_Tag),
New_Reference_To (DT_Ptr, Loc)), -- DTptr New_Reference_To (Iface_DT_Ptr, Loc)), -- DTptr
Make_Integer_Literal (Loc, DT_Position (Prim_Op)), -- Position Make_Integer_Literal (Loc, Pos), -- Position
Make_Attribute_Reference (Loc, -- Value Make_Attribute_Reference (Loc, -- Value
Prefix => New_Reference_To (Target, Loc), Prefix => New_Reference_To (Thunk_Id, Loc),
Attribute_Name => Name_Address))); Attribute_Name => Name_Address)));
end Fill_DT_Entry; end Fill_Secondary_DT_Entry;
--------------------------- ---------------------------
-- Get_Remotely_Callable -- -- Get_Remotely_Callable --
...@@ -1313,7 +1319,6 @@ package body Exp_Disp is ...@@ -1313,7 +1319,6 @@ package body Exp_Disp is
Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ))); Nb_Prim := UI_To_Int (DT_Entry_Count (First_Tag_Component (Typ)));
-- ---------------------------------------------------------------- -- ----------------------------------------------------------------
-- Dispatch table and related entities are allocated statically -- Dispatch table and related entities are allocated statically
Set_Ekind (DT, E_Variable); Set_Ekind (DT, E_Variable);
...@@ -1538,6 +1543,71 @@ package body Exp_Disp is ...@@ -1538,6 +1543,71 @@ package body Exp_Disp is
Node3 => Make_Integer_Literal (Loc, Node3 => Make_Integer_Literal (Loc,
DT_Entry_Count (First_Tag_Component (Etype (Typ))))))); DT_Entry_Count (First_Tag_Component (Etype (Typ)))))));
-- Inherit the secondary dispatch tables of the ancestor
if 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);
-- ??? comment required
------------------------
-- Copy_Secondary_DTs --
------------------------
procedure Copy_Secondary_DTs (Typ : Entity_Id) is
E : Entity_Id;
begin
if 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
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
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)))));
Next_Elmt (Sec_DT_Ancestor);
Next_Elmt (Sec_DT_Typ);
end if;
Next_Entity (E);
end loop;
end if;
end Copy_Secondary_DTs;
begin
if Present (Node (Sec_DT_Ancestor)) then
Copy_Secondary_DTs (Typ);
end if;
end;
end if;
-- Generate: Inherit_TSD (parent'tag, DT_Ptr); -- Generate: Inherit_TSD (parent'tag, DT_Ptr);
Append_To (Elab_Code, Append_To (Elab_Code,
...@@ -1547,17 +1617,20 @@ package body Exp_Disp is ...@@ -1547,17 +1617,20 @@ package body Exp_Disp is
Node1 => Old_Tag2, Node1 => Old_Tag2,
Node2 => New_Reference_To (DT_Ptr, Loc)))); Node2 => New_Reference_To (DT_Ptr, Loc))));
-- for types with no controlled components -- For types with no controlled components, generate:
-- Generate: Set_RC_Offset (DT_Ptr, 0); -- Set_RC_Offset (DT_Ptr, 0);
-- for simple types with controlled components
-- Generate: Set_RC_Offset (DT_Ptr, type._record_controller'position); -- For simple types with controlled components, generate:
-- for complex types with controlled components where the position -- 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 -- of the record controller is not statically computable, if there are
-- controlled components at this level -- controlled components at this level, generate:
-- Generate: Set_RC_Offset (DT_Ptr, -1); -- Set_RC_Offset (DT_Ptr, -1);
-- to indicate that the _controller field is right after the _parent or -- to indicate that the _controller field is right after the _parent
-- if there are no controlled components at this level,
-- Generate: Set_RC_Offset (DT_Ptr, -2); -- 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. -- to indicate that we need to get the position from the parent.
declare declare
...@@ -1588,6 +1661,8 @@ package body Exp_Disp is ...@@ -1588,6 +1661,8 @@ package body Exp_Disp is
-- the back end (see comment on the Bit_Component attribute in -- the back end (see comment on the Bit_Component attribute in
-- sem_attr). So we avoid semantic checking here. -- sem_attr). So we avoid semantic checking here.
-- Is this documented in sinfo.ads??? it should be!
Set_Analyzed (Position); Set_Analyzed (Position);
Set_Etype (Prefix (Position), RTE (RE_Record_Controller)); Set_Etype (Prefix (Position), RTE (RE_Record_Controller));
Set_Etype (Prefix (Prefix (Position)), Typ); Set_Etype (Prefix (Prefix (Position)), Typ);
...@@ -1604,8 +1679,8 @@ package body Exp_Disp is ...@@ -1604,8 +1679,8 @@ package body Exp_Disp is
Node2 => Position))); Node2 => Position)));
end; end;
-- Generate: Set_Remotely_Callable (DT_Ptr, Status); -- Generate: Set_Remotely_Callable (DT_Ptr, Status); where Status is
-- where Status is described in E.4 (18) -- described in E.4 (18)
declare declare
Status : Entity_Id; Status : Entity_Id;
...@@ -1681,8 +1756,8 @@ package body Exp_Disp is ...@@ -1681,8 +1756,8 @@ package body Exp_Disp is
-- Ada 2005 (AI-251): Register the tag of the interfaces into -- Ada 2005 (AI-251): Register the tag of the interfaces into
-- the table of implemented interfaces -- the table of implemented interfaces
if Present (Abstract_Interfaces (Typ)) if Present (Abstract_Interfaces (Typ_Copy))
and then not Is_Empty_Elmt_List (Abstract_Interfaces (Typ)) and then not Is_Empty_Elmt_List (Abstract_Interfaces (Typ_Copy))
then then
AI := First_Elmt (Abstract_Interfaces (Typ_Copy)); AI := First_Elmt (Abstract_Interfaces (Typ_Copy));
while Present (AI) loop while Present (AI) loop
...@@ -1718,9 +1793,8 @@ package body Exp_Disp is ...@@ -1718,9 +1793,8 @@ package body Exp_Disp is
Result : out List_Id) Result : out List_Id)
is is
Loc : constant Source_Ptr := Sloc (AI_Tag); Loc : constant Source_Ptr := Sloc (AI_Tag);
Tname : constant Name_Id := Chars (AI_Tag); Name_DT : constant Name_Id := New_Internal_Name ('T');
Name_DT : constant Name_Id := New_External_Name (Tname, 'T'); Name_DT_Ptr : constant Name_Id := New_Internal_Name ('P');
Name_DT_Ptr : constant Name_Id := New_External_Name (Tname, 'P');
Iface_DT : constant Node_Id := Iface_DT : constant Node_Id :=
Make_Defining_Identifier (Loc, Name_DT); Make_Defining_Identifier (Loc, Name_DT);
...@@ -1848,7 +1922,6 @@ package body Exp_Disp is ...@@ -1848,7 +1922,6 @@ package body Exp_Disp is
end if; end if;
Append_Elmt (Iface_DT_Ptr, Acc_Disp_Tables); Append_Elmt (Iface_DT_Ptr, Acc_Disp_Tables);
end Make_Abstract_Interface_DT; end Make_Abstract_Interface_DT;
--------------------------- ---------------------------
...@@ -2117,6 +2190,7 @@ package body Exp_Disp is ...@@ -2117,6 +2190,7 @@ package body Exp_Disp is
Prim_Elmt := First_Prim; Prim_Elmt := First_Prim;
Count_Prim := 0; Count_Prim := 0;
while Present (Prim_Elmt) loop while Present (Prim_Elmt) loop
Count_Prim := Count_Prim + 1; Count_Prim := Count_Prim + 1;
Prim := Node (Prim_Elmt); Prim := Node (Prim_Elmt);
......
...@@ -55,12 +55,20 @@ package Exp_Disp is ...@@ -55,12 +55,20 @@ package Exp_Disp is
TSD_Prologue_Size); TSD_Prologue_Size);
function Fill_DT_Entry function Fill_DT_Entry
(Loc : Source_Ptr; (Loc : Source_Ptr;
Prim : Entity_Id; Prim : Entity_Id) return Node_Id;
Thunk_Id : Entity_Id := Empty) return Node_Id;
-- Generate the code necessary to fill the appropriate entry of the -- Generate the code necessary to fill the appropriate entry of the
-- dispatch table of Prim's controlling type with Prim's address. -- dispatch table of Prim's controlling type with Prim's address.
function Fill_Secondary_DT_Entry
(Loc : Source_Ptr;
Prim : Entity_Id;
Thunk_Id : Entity_Id;
Iface_DT_Ptr : Entity_Id) return Node_Id;
-- (Ada 2005): Generate the code necessary to fill the appropriate entry of
-- the secondary dispatch table of Prim's controlling type with Thunk_Id's
-- address.
procedure Make_Abstract_Interface_DT procedure Make_Abstract_Interface_DT
(AI_Tag : Entity_Id; (AI_Tag : Entity_Id;
Acc_Disp_Tables : in out Elist_Id; Acc_Disp_Tables : in out Elist_Id;
...@@ -102,9 +110,10 @@ package Exp_Disp is ...@@ -102,9 +110,10 @@ package Exp_Disp is
-- secondary dispatch table -- secondary dispatch table
function Expand_Interface_Thunk function Expand_Interface_Thunk
(N : Node_Id; (N : Node_Id;
Thunk_Id : Entity_Id; Thunk_Alias : Node_Id;
Iface_Tag : Entity_Id) return Node_Id; Thunk_Id : Entity_Id;
Iface_Tag : Entity_Id) return Node_Id;
-- Ada 2005 (AI-251): When a tagged type implements abstract interfaces we -- Ada 2005 (AI-251): When a tagged type implements abstract interfaces we
-- generate additional subprograms (thunks) to have a layout compatible -- generate additional subprograms (thunks) to have a layout compatible
-- with the C++ ABI. The thunk modifies the value of the first actual of -- with the C++ ABI. The thunk modifies the value of the first actual of
......
...@@ -108,15 +108,6 @@ package body Exp_Util is ...@@ -108,15 +108,6 @@ package body Exp_Util is
-- procedure of record with task components, or for a dynamically -- procedure of record with task components, or for a dynamically
-- created task that is assigned to a selected component. -- created task that is assigned to a selected component.
procedure Find_Interface_Tag
(T : Entity_Id;
Iface : Entity_Id;
Iface_Tag : out Entity_Id;
Iface_ADT : out Entity_Id);
-- Ada 2005 (AI-251): Subsidiary procedure to Find_Interface_ADT and
-- Find_Interface_Tag. Given a type T implementing the interface,
-- returns the corresponding Tag and Access_Disp_Table entities.
function Make_CW_Equivalent_Type function Make_CW_Equivalent_Type
(T : Entity_Id; (T : Entity_Id;
E : Node_Id) return Entity_Id; E : Node_Id) return Entity_Id;
...@@ -1298,26 +1289,100 @@ package body Exp_Util is ...@@ -1298,26 +1289,100 @@ package body Exp_Util is
-- Find_Interface_Tag -- -- Find_Interface_Tag --
------------------------ ------------------------
procedure Find_Interface_Tag function Find_Interface_ADT
(T : Entity_Id; (T : Entity_Id;
Iface : Entity_Id; Iface : Entity_Id) return Entity_Id
Iface_Tag : out Entity_Id; is
Iface_ADT : out Entity_Id) ADT : Elmt_Id;
Found : Boolean := False;
Typ : Entity_Id := T;
procedure Find_Secondary_Table (Typ : Entity_Id);
-- Comment required ???
--------------------------
-- Find_Secondary_Table --
--------------------------
procedure Find_Secondary_Table (Typ : Entity_Id) is
AI_Elmt : Elmt_Id;
AI : Node_Id;
begin
if Etype (Typ) /= Typ then
Find_Secondary_Table (Etype (Typ));
end if;
if Present (Abstract_Interfaces (Typ))
and then not Is_Empty_Elmt_List (Abstract_Interfaces (Typ))
then
AI_Elmt := First_Elmt (Abstract_Interfaces (Typ));
while Present (AI_Elmt) loop
AI := Node (AI_Elmt);
if AI = Iface or else Is_Ancestor (Iface, AI) then
Found := True;
return;
end if;
Next_Elmt (ADT);
Next_Elmt (AI_Elmt);
end loop;
end if;
end Find_Secondary_Table;
-- Start of processing for Find_Interface_Tag
begin
-- Handle private types
if Has_Private_Declaration (Typ)
and then Present (Full_View (Typ))
then
Typ := Full_View (Typ);
end if;
-- Handle access types
if Is_Access_Type (Typ) then
Typ := Directly_Designated_Type (Typ);
end if;
-- Handle task and protected types implementing interfaces
if Ekind (Typ) = E_Protected_Type
or else Ekind (Typ) = E_Task_Type
then
Typ := Corresponding_Record_Type (Typ);
end if;
ADT := Next_Elmt (First_Elmt (Access_Disp_Table (Typ)));
pragma Assert (Present (Node (ADT)));
Find_Secondary_Table (Typ);
pragma Assert (Found);
return Node (ADT);
end Find_Interface_ADT;
------------------------
-- Find_Interface_Tag --
------------------------
function Find_Interface_Tag
(T : Entity_Id;
Iface : Entity_Id) return Entity_Id
is is
AI_Tag : Entity_Id; AI_Tag : Entity_Id;
ADT_Elmt : Elmt_Id; Found : Boolean := False;
Found : Boolean := False; Typ : Entity_Id := T;
procedure Find_AI_Tag (Typ : in Entity_Id; Found : in out Boolean); procedure Find_Tag (Typ : in Entity_Id);
-- This must be commented ??? -- Internal subprogram used to recursively climb to the ancestors
----------------- -----------------
-- Find_AI_Tag -- -- Find_AI_Tag --
----------------- -----------------
procedure Find_AI_Tag (Typ : in Entity_Id; Found : in out Boolean) is procedure Find_Tag (Typ : in Entity_Id) is
T : Entity_Id := Typ;
Etyp : Entity_Id; -- := Etype (Typ); -- why is this commented ???
AI_Elmt : Elmt_Id; AI_Elmt : Elmt_Id;
AI : Node_Id; AI : Node_Id;
...@@ -1326,60 +1391,31 @@ package body Exp_Util is ...@@ -1326,60 +1391,31 @@ package body Exp_Util is
-- therefore shares the main tag. -- therefore shares the main tag.
if Typ = Iface then if Typ = Iface then
AI_Tag := First_Tag_Component (Typ); pragma Assert (Etype (First_Tag_Component (Typ)) = RTE (RE_Tag));
ADT_Elmt := First_Elmt (Access_Disp_Table (Typ)); AI_Tag := First_Tag_Component (Typ);
Found := True; Found := True;
return; return;
end if; end if;
-- Handle private types
if Has_Private_Declaration (T)
and then Present (Full_View (T))
then
T := Full_View (T);
end if;
if Is_Access_Type (Typ) then
T := Directly_Designated_Type (T);
elsif Ekind (T) = E_Protected_Type
or else Ekind (T) = E_Task_Type
then
T := Corresponding_Record_Type (T);
end if;
Etyp := Etype (T);
-- Climb to the root type -- Climb to the root type
if Etyp /= Typ then if Etype (Typ) /= Typ then
Find_AI_Tag (Etyp, Found); Find_Tag (Etype (Typ));
end if; end if;
-- Traverse the list of interfaces implemented by the type -- Traverse the list of interfaces implemented by the type
if not Found if not Found
and then Present (Abstract_Interfaces (T)) and then Present (Abstract_Interfaces (Typ))
and then not Is_Empty_Elmt_List (Abstract_Interfaces (T)) and then not (Is_Empty_Elmt_List (Abstract_Interfaces (Typ)))
then then
-- Skip the tag associated with the primary table (if -- Skip the tag associated with the primary table.
-- already placed in the record)
if Etype (Node (First_Elmt
(Access_Disp_Table (T)))) = RTE (RE_Tag)
then
AI_Tag := Next_Tag_Component (First_Tag_Component (T));
ADT_Elmt := Next_Elmt (First_Elmt (Access_Disp_Table (T)));
else
AI_Tag := First_Tag_Component (T);
ADT_Elmt := First_Elmt (Access_Disp_Table (T));
end if;
pragma Assert (Etype (First_Tag_Component (Typ)) = RTE (RE_Tag));
AI_Tag := Next_Tag_Component (First_Tag_Component (Typ));
pragma Assert (Present (AI_Tag)); pragma Assert (Present (AI_Tag));
pragma Assert (Present (Node (ADT_Elmt)));
AI_Elmt := First_Elmt (Abstract_Interfaces (T)); AI_Elmt := First_Elmt (Abstract_Interfaces (Typ));
while Present (AI_Elmt) loop while Present (AI_Elmt) loop
AI := Node (AI_Elmt); AI := Node (AI_Elmt);
...@@ -1390,47 +1426,38 @@ package body Exp_Util is ...@@ -1390,47 +1426,38 @@ package body Exp_Util is
AI_Tag := Next_Tag_Component (AI_Tag); AI_Tag := Next_Tag_Component (AI_Tag);
Next_Elmt (AI_Elmt); Next_Elmt (AI_Elmt);
Next_Elmt (ADT_Elmt);
end loop; end loop;
end if; end if;
end Find_AI_Tag; end Find_Tag;
-- Start of processing for Find_Interface_Tag
begin begin
Find_AI_Tag (T, Found); -- Handle private types
pragma Assert (Found);
Iface_Tag := AI_Tag; if Has_Private_Declaration (Typ)
Iface_ADT := Node (ADT_Elmt); and then Present (Full_View (Typ))
end Find_Interface_Tag; then
Typ := Full_View (Typ);
end if;
------------------------ -- Handle access types
-- Find_Interface_Tag --
------------------------
function Find_Interface_ADT if Is_Access_Type (Typ) then
(T : Entity_Id; Typ := Directly_Designated_Type (Typ);
Iface : Entity_Id) return Entity_Id end if;
is
Iface_Tag : Entity_Id := Empty;
Iface_ADT : Entity_Id := Empty;
begin
Find_Interface_Tag (T, Iface, Iface_Tag, Iface_ADT);
return Iface_ADT;
end Find_Interface_ADT;
------------------------ -- Handle task and protected types implementing interfaces
-- Find_Interface_Tag --
------------------------
function Find_Interface_Tag if Ekind (Typ) = E_Protected_Type
(T : Entity_Id; or else Ekind (Typ) = E_Task_Type
Iface : Entity_Id) return Entity_Id then
is Typ := Corresponding_Record_Type (Typ);
Iface_Tag : Entity_Id := Empty; end if;
Iface_ADT : Entity_Id := Empty;
begin Find_Tag (Typ);
Find_Interface_Tag (T, Iface, Iface_Tag, Iface_ADT); pragma Assert (Found);
return Iface_Tag; return AI_Tag;
end Find_Interface_Tag; end Find_Interface_Tag;
------------------ ------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment