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
...@@ -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;
......
...@@ -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