summaryrefslogtreecommitdiff
path: root/gcc/ada/s-finimp.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/s-finimp.adb')
-rw-r--r--gcc/ada/s-finimp.adb191
1 files changed, 102 insertions, 89 deletions
diff --git a/gcc/ada/s-finimp.adb b/gcc/ada/s-finimp.adb
index bc1a2f18e65..5d06b3a551d 100644
--- a/gcc/ada/s-finimp.adb
+++ b/gcc/ada/s-finimp.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2002 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- --
@@ -84,13 +84,16 @@ package body System.Finalization_Implementation is
function RC_Offset (T : Ada.Tags.Tag) return SSE.Storage_Offset;
pragma Import (Ada, RC_Offset, "ada__tags__get_rc_offset");
- function Parent_Size (Obj : Address) return SSE.Storage_Count;
+ function Parent_Size (Obj : Address; T : Ada.Tags.Tag)
+ return SSE.Storage_Count;
pragma Import (Ada, Parent_Size, "ada__tags__parent_size");
- function Get_RC_Dynamically (Obj : Address) return Address;
- -- Given an the address of an object (obj) of a tagged extension with
- -- controlled component, computes the address of the record controller
- -- located just after the _parent field
+ function Parent_Tag (T : Ada.Tags.Tag) return Ada.Tags.Tag;
+ pragma Import (Ada, Parent_Tag, "ada__tags__parent_tag");
+
+ function Get_Deep_Controller (Obj : System.Address) return RC_Ptr;
+ -- Given the address (obj) of a tagged object, return a
+ -- pointer to the record controller of this object.
-------------
-- Adjust --
@@ -103,13 +106,17 @@ package body System.Finalization_Implementation is
Object.My_Address - Object'Address;
procedure Ptr_Adjust (Ptr : in out Finalizable_Ptr);
- -- Subtract the offset to the pointer
+ -- Substract the offset to the pointer
procedure Reverse_Adjust (P : Finalizable_Ptr);
- -- Adjust the components in the reverse order in which they are stored
+ -- Ajust the components in the reverse order in which they are stored
-- on the finalization list. (Adjust and Finalization are not done in
-- the same order)
+ ----------------
+ -- Ptr_Adjust --
+ ----------------
+
procedure Ptr_Adjust (Ptr : in out Finalizable_Ptr) is
begin
if Ptr /= null then
@@ -117,6 +124,10 @@ package body System.Finalization_Implementation is
end if;
end Ptr_Adjust;
+ --------------------
+ -- Reverse_Adjust --
+ --------------------
+
procedure Reverse_Adjust (P : Finalizable_Ptr) is
begin
if P /= null then
@@ -210,7 +221,6 @@ package body System.Finalization_Implementation is
L := Obj'Unchecked_Access;
end;
end if;
-
end Attach_To_Final_List;
---------------------
@@ -222,27 +232,18 @@ package body System.Finalization_Implementation is
A : System.Address;
B : Short_Short_Integer)
is
- V : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
- Offset : constant SSE.Storage_Offset := RC_Offset (V'Tag);
-
- Controller : RC_Ptr;
+ V : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
+ Controller : constant RC_Ptr := Get_Deep_Controller (A);
begin
- -- Has controlled components
-
- if Offset /= 0 then
- if Offset > 0 then
- Controller := To_RC_Ptr (A + Offset);
- else
- Controller := To_RC_Ptr (Get_RC_Dynamically (A));
- end if;
-
+ if Controller /= null then
Adjust (Controller.all);
Attach_To_Final_List (L, Controller.all, B);
+ end if;
-- Is controlled
- elsif V.all in Finalizable then
+ if V.all in Finalizable then
Adjust (V.all);
Attach_To_Final_List (L, Finalizable (V.all), 1);
end if;
@@ -257,24 +258,17 @@ package body System.Finalization_Implementation is
A : System.Address;
B : Short_Short_Integer)
is
- V : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
- Offset : constant SSE.Storage_Offset := RC_Offset (V'Tag);
-
- Controller : RC_Ptr;
+ V : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
+ Controller : constant RC_Ptr := Get_Deep_Controller (A);
begin
- if Offset /= 0 then
- if Offset > 0 then
- Controller := To_RC_Ptr (A + Offset);
- else
- Controller := To_RC_Ptr (Get_RC_Dynamically (A));
- end if;
-
+ if Controller /= null then
Attach_To_Final_List (L, Controller.all, B);
+ end if;
-- Is controlled
- elsif V.all in Finalizable then
+ if V.all in Finalizable then
Attach_To_Final_List (L, V.all, B);
end if;
end Deep_Tag_Attach;
@@ -290,30 +284,21 @@ package body System.Finalization_Implementation is
is
pragma Warnings (Off, L);
- V : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
- Offset : constant SSE.Storage_Offset := RC_Offset (V'Tag);
-
- Controller : RC_Ptr;
+ V : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
+ Controller : constant RC_Ptr := Get_Deep_Controller (A);
begin
- -- Has controlled components
-
- if Offset /= 0 then
- if Offset > 0 then
- Controller := To_RC_Ptr (A + Offset);
- else
- Controller := To_RC_Ptr (Get_RC_Dynamically (A));
- end if;
-
+ if Controller /= null then
if B then
Finalize_One (Controller.all);
else
Finalize (Controller.all);
end if;
+ end if;
-- Is controlled
- elsif V.all in Finalizable then
+ if V.all in Finalizable then
if B then
Finalize_One (V.all);
else
@@ -331,32 +316,23 @@ package body System.Finalization_Implementation is
A : System.Address;
B : Short_Short_Integer)
is
- V : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
- Offset : constant SSE.Storage_Offset := RC_Offset (V'Tag);
-
- Controller : RC_Ptr;
+ V : constant SFR.Finalizable_Ptr := To_Finalizable_Ptr (A);
+ Controller : constant RC_Ptr := Get_Deep_Controller (A);
begin
-- This procedure should not be called if the object has no
-- controlled components
- if Offset = 0 then
-
+ if Controller = null then
raise Program_Error;
-- Has controlled components
else
- if Offset > 0 then
- Controller := To_RC_Ptr (A + Offset);
- else
- Controller := To_RC_Ptr (Get_RC_Dynamically (A));
- end if;
+ Initialize (Controller.all);
+ Attach_To_Final_List (L, Controller.all, B);
end if;
- Initialize (Controller.all);
- Attach_To_Final_List (L, Controller.all, B);
-
-- Is controlled
if V.all in Finalizable then
@@ -437,10 +413,10 @@ package body System.Finalization_Implementation is
P : Finalizable_Ptr := L;
Q : Finalizable_Ptr;
- type Fake_Exception_Occurrence is record
+ type Fake_Exception_Occurence is record
Id : Exception_Id;
end record;
- type Ptr is access all Fake_Exception_Occurrence;
+ type Ptr is access all Fake_Exception_Occurence;
-- Let's get the current exception before starting to finalize in
-- order to check if we are in the abort case if an exception is
@@ -448,8 +424,9 @@ package body System.Finalization_Implementation is
function To_Ptr is new
Ada.Unchecked_Conversion (Exception_Occurrence_Access, Ptr);
- X : Exception_Id :=
- To_Ptr (System.Soft_Links.Get_Current_Excep.all).Id;
+
+ X : constant Exception_Id :=
+ To_Ptr (System.Soft_Links.Get_Current_Excep.all).Id;
begin
while P /= null loop
@@ -479,36 +456,72 @@ package body System.Finalization_Implementation is
when E_Occ : others => Raise_From_Finalize (null, False, E_Occ);
end Finalize_One;
- ------------------------
- -- Get_RC_Dynamically --
- ------------------------
+ -------------------------
+ -- Get_Deep_Controller --
+ -------------------------
- function Get_RC_Dynamically (Obj : Address) return Address is
+ function Get_Deep_Controller (Obj : System.Address) return RC_Ptr is
+ The_Tag : Ada.Tags.Tag := To_Finalizable_Ptr (Obj)'Tag;
+ Offset : SSE.Storage_Offset := RC_Offset (The_Tag);
- -- define a faked record controller to avoid generating
- -- unnecessary expanded code for controlled types
+ begin
- type Faked_Record_Controller is record
- Tag, Prec, Next : Address;
- end record;
+ -- Fetch the controller from the Parent or above if necessary
+ -- when there are no controller at this level
- -- Reconstruction of a type with characteristics
- -- comparable to the original type
+ while Offset = -2 loop
+ The_Tag := Parent_Tag (The_Tag);
+ Offset := RC_Offset (The_Tag);
+ end loop;
- D : constant := Storage_Unit - 1;
+ -- No Controlled component case
- type Faked_Type_Of_Obj is record
- Parent : SSE.Storage_Array
- (1 .. (Parent_Size (Obj) + D) / Storage_Unit);
- Controller : Faked_Record_Controller;
- end record;
+ if Offset = 0 then
+ return null;
- type Obj_Ptr is access all Faked_Type_Of_Obj;
- function To_Obj_Ptr is new Ada.Unchecked_Conversion (Address, Obj_Ptr);
+ -- The _controller Offset is known statically
- begin
- return To_Obj_Ptr (Obj).Controller'Address;
- end Get_RC_Dynamically;
+ elsif Offset > 0 then
+ return To_RC_Ptr (Obj + Offset);
+
+ -- At this stage, we know that the controller is part of the
+ -- ancestor corresponding to the tag "The_Tag" and that its parent
+ -- is variable sized. We assume that the _controller is the first
+ -- compoment right after the parent.
+ -- ??? note that it may not be true if there are new discriminants.
+
+ else -- Offset = -1
+
+ declare
+ -- define a faked record controller to avoid generating
+ -- unnecessary expanded code for controlled types
+
+ type Faked_Record_Controller is record
+ Tag, Prec, Next : Address;
+ end record;
+
+ -- Reconstruction of a type with characteristics
+ -- comparable to the original type
+
+ D : constant := Storage_Unit - 1;
+
+ type Parent_Type is new SSE.Storage_Array
+ (1 .. (Parent_Size (Obj, The_Tag) + D) / Storage_Unit);
+ for Parent_Type'Alignment use Address'Alignment;
+
+ type Faked_Type_Of_Obj is record
+ Parent : Parent_Type;
+ Controller : Faked_Record_Controller;
+ end record;
+ type Obj_Ptr is access all Faked_Type_Of_Obj;
+ function To_Obj_Ptr is
+ new Ada.Unchecked_Conversion (Address, Obj_Ptr);
+
+ begin
+ return To_RC_Ptr (To_Obj_Ptr (Obj).Controller'Address);
+ end;
+ end if;
+ end Get_Deep_Controller;
----------------
-- Initialize --