aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHristian Kirtchev <kirtchev@adacore.com>2012-05-15 12:09:44 +0000
committerArnaud Charlet <charlet@gcc.gnu.org>2012-05-15 14:09:44 +0200
commitb0d7135584eb90c1d4de57d754c8963b1703fcc6 (patch)
treee54aec67d2825cbc15550a9abbb2f2b48bcfcc7b
parent5b5b27adff45664299c19f4666e078f4acecfdf7 (diff)
downloadgcc-b0d7135584eb90c1d4de57d754c8963b1703fcc6.zip
gcc-b0d7135584eb90c1d4de57d754c8963b1703fcc6.tar.gz
gcc-b0d7135584eb90c1d4de57d754c8963b1703fcc6.tar.bz2
exp_ch4.adb (Insert_Dereference_Action): Reimplemented.
2012-05-15 Hristian Kirtchev <kirtchev@adacore.com> * exp_ch4.adb (Insert_Dereference_Action): Reimplemented. The routine performs address and size adjustments for dereferences of heap-allocated controlled objects. This manipulation is needed in order to restore the original state of the memory at the time it was allocated by the finalization machinery. * rtsfind.ads: Add RE_Adjust_Controlled_Dereference to tables RE_Id and RE_Unit_Table. * sinfo.adb (Has_Dereference_Action): New routine. (Set_Has_Dereference_Action): New routine. * sinfo.ads: Add new semantic flag Has_Dereference_Action along its association in nodes. (Has_Dereference_Action): New routine and pragma Inline. (Set_Has_Dereference_Action): New routine and pragma Inline. * s-stposu.ads, s-stposu.adb (Adjust_Controlled_Dereference): New routine. From-SVN: r187530
-rw-r--r--gcc/ada/ChangeLog18
-rw-r--r--gcc/ada/exp_ch4.adb184
-rw-r--r--gcc/ada/rtsfind.ads2
-rw-r--r--gcc/ada/s-stposu.adb20
-rw-r--r--gcc/ada/s-stposu.ads10
-rw-r--r--gcc/ada/sinfo.adb16
-rw-r--r--gcc/ada/sinfo.ads15
7 files changed, 226 insertions, 39 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 81f1da4..605539b 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,21 @@
+2012-05-15 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch4.adb (Insert_Dereference_Action): Reimplemented. The
+ routine performs address and size adjustments for dereferences
+ of heap-allocated controlled objects. This manipulation is needed
+ in order to restore the original state of the memory at the time
+ it was allocated by the finalization machinery.
+ * rtsfind.ads: Add RE_Adjust_Controlled_Dereference to tables
+ RE_Id and RE_Unit_Table.
+ * sinfo.adb (Has_Dereference_Action): New routine.
+ (Set_Has_Dereference_Action): New routine.
+ * sinfo.ads: Add new semantic flag Has_Dereference_Action along
+ its association in nodes.
+ (Has_Dereference_Action): New routine and pragma Inline.
+ (Set_Has_Dereference_Action): New routine and pragma Inline.
+ * s-stposu.ads, s-stposu.adb (Adjust_Controlled_Dereference): New
+ routine.
+
2012-05-15 Thomas Quinot <quinot@adacore.com>
* uintp.adb (Image_Uint): Use UI_Div_Rem to get quotient and
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 4efa476..505d239 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -10117,11 +10117,6 @@ package body Exp_Ch4 is
-------------------------------
procedure Insert_Dereference_Action (N : Node_Id) is
- Loc : constant Source_Ptr := Sloc (N);
- Typ : constant Entity_Id := Etype (N);
- Pool : constant Entity_Id := Associated_Storage_Pool (Typ);
- Pnod : constant Node_Id := Parent (N);
-
function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean;
-- Return true if type of P is derived from Checked_Pool;
@@ -10149,57 +10144,172 @@ package body Exp_Ch4 is
return False;
end Is_Checked_Storage_Pool;
+ -- Local variables
+
+ Typ : constant Entity_Id := Etype (N);
+ Desig : constant Entity_Id := Available_View (Designated_Type (Typ));
+ Loc : constant Source_Ptr := Sloc (N);
+ Pool : constant Entity_Id := Associated_Storage_Pool (Typ);
+ Pnod : constant Node_Id := Parent (N);
+
+ Addr : Entity_Id;
+ Alig : Entity_Id;
+ Deref : Node_Id;
+ Size : Entity_Id;
+ Stmt : Node_Id;
+
-- Start of processing for Insert_Dereference_Action
begin
pragma Assert (Nkind (Pnod) = N_Explicit_Dereference);
- if not (Is_Checked_Storage_Pool (Pool)
- and then Comes_From_Source (Original_Node (Pnod)))
- then
+ -- Do not re-expand a dereference which has already been processed by
+ -- this routine.
+
+ if Has_Dereference_Action (Pnod) then
return;
- end if;
- Insert_Action (N,
- Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (
- Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
+ -- Do not perform this type of expansion for internally-generated
+ -- dereferences.
- Parameter_Associations => New_List (
+ elsif not Comes_From_Source (Original_Node (Pnod)) then
+ return;
- -- Pool
+ -- A dereference action is only applicable to objects which have been
+ -- allocated on a checked pool.
- New_Reference_To (Pool, Loc),
+ elsif not Is_Checked_Storage_Pool (Pool) then
+ return;
+ end if;
- -- Storage_Address. We use the attribute Pool_Address, which uses
- -- the pointer itself to find the address of the object, and which
- -- handles unconstrained arrays properly by computing the address
- -- of the template. i.e. the correct address of the corresponding
- -- allocation.
+ -- Extract the address of the dereferenced object. Generate:
+ -- Addr : System.Address := <N>'Pool_Address;
- Make_Attribute_Reference (Loc,
- Prefix => Duplicate_Subexpr_Move_Checks (N),
- Attribute_Name => Name_Pool_Address),
+ Addr := Make_Temporary (Loc, 'P');
- -- Size_In_Storage_Elements
+ Insert_Action (N,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Addr,
+ Object_Definition =>
+ New_Reference_To (RTE (RE_Address), Loc),
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix => Duplicate_Subexpr_Move_Checks (N),
+ Attribute_Name => Name_Pool_Address)));
+
+ -- Calculate the size of the dereferenced object. Generate:
+ -- Size : Storage_Count := <N>.all'Size / Storage_Unit;
+
+ Deref :=
+ Make_Explicit_Dereference (Loc,
+ Prefix => Duplicate_Subexpr_Move_Checks (N));
+ Set_Has_Dereference_Action (Deref);
- Make_Op_Divide (Loc,
- Left_Opnd =>
+ Size := Make_Temporary (Loc, 'S');
+
+ Insert_Action (N,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Size,
+ Object_Definition =>
+ New_Reference_To (RTE (RE_Storage_Count), Loc),
+ Expression =>
+ Make_Op_Divide (Loc,
+ Left_Opnd =>
Make_Attribute_Reference (Loc,
- Prefix =>
- Make_Explicit_Dereference (Loc,
- Duplicate_Subexpr_Move_Checks (N)),
+ Prefix => Deref,
Attribute_Name => Name_Size),
Right_Opnd =>
- Make_Integer_Literal (Loc, System_Storage_Unit)),
+ Make_Integer_Literal (Loc, System_Storage_Unit))));
- -- Alignment
+ -- Calculate the alignment of the dereferenced object. Generate:
+ -- Alig : constant Storage_Count := <N>.all'Alignment;
- Make_Attribute_Reference (Loc,
- Prefix =>
- Make_Explicit_Dereference (Loc,
- Duplicate_Subexpr_Move_Checks (N)),
- Attribute_Name => Name_Alignment))));
+ Deref :=
+ Make_Explicit_Dereference (Loc,
+ Prefix => Duplicate_Subexpr_Move_Checks (N));
+ Set_Has_Dereference_Action (Deref);
+
+ Alig := Make_Temporary (Loc, 'A');
+
+ Insert_Action (N,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Alig,
+ Object_Definition =>
+ New_Reference_To (RTE (RE_Storage_Count), Loc),
+ Expression =>
+ Make_Attribute_Reference (Loc,
+ Prefix => Deref,
+ Attribute_Name => Name_Alignment)));
+
+ -- A dereference of a controlled object requires special processing. The
+ -- finalization machinery requests additional space from the underlying
+ -- pool to allocate and hide two pointers. As a result, a checked pool
+ -- may mark the wrong memory as valid. Since checked pools do not have
+ -- knowledge of hidden pointers, we have to bring the two pointers back
+ -- in view in order to restore the original state of the object.
+
+ if Needs_Finalization (Desig) then
+
+ -- Adjust the address and size of the dereferenced object. Generate:
+ -- Adjust_Controlled_Dereference (Addr, Size, Alig);
+
+ Stmt :=
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Reference_To (RTE (RE_Adjust_Controlled_Dereference), Loc),
+ Parameter_Associations => New_List (
+ New_Reference_To (Addr, Loc),
+ New_Reference_To (Size, Loc),
+ New_Reference_To (Alig, Loc)));
+
+ -- Class-wide types complicate things because we cannot determine
+ -- statically whether the actual object is truly controlled. We must
+ -- generate a runtime check to detect this property. Generate:
+ --
+ -- if Needs_Finalization (<N>.all'Tag) then
+ -- <Stmt>;
+ -- end if;
+
+ if Is_Class_Wide_Type (Desig) then
+ Deref :=
+ Make_Explicit_Dereference (Loc,
+ Prefix => Duplicate_Subexpr_Move_Checks (N));
+ Set_Has_Dereference_Action (Deref);
+
+ Stmt :=
+ Make_If_Statement (Loc,
+ Condition =>
+ Make_Function_Call (Loc,
+ Name =>
+ New_Reference_To (RTE (RE_Needs_Finalization), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => Deref,
+ Attribute_Name => Name_Tag))),
+ Then_Statements => New_List (Stmt));
+ end if;
+
+ Insert_Action (N, Stmt);
+ end if;
+
+ -- Generate:
+ -- Dereference (Pool, Addr, Size, Alig);
+
+ Insert_Action (N,
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Reference_To
+ (Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
+ Parameter_Associations => New_List (
+ New_Reference_To (Pool, Loc),
+ New_Reference_To (Addr, Loc),
+ New_Reference_To (Size, Loc),
+ New_Reference_To (Alig, Loc))));
+
+ -- Mark the explicit dereference as processed to avoid potential
+ -- infinite expansion.
+
+ Set_Has_Dereference_Action (Pnod);
exception
when RE_Not_Available =>
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index a01505c..5b7345f 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -1401,6 +1401,7 @@ package Rtsfind is
RE_Root_Storage_Pool, -- System.Storage_Pools
RE_Root_Storage_Pool_Ptr, -- System.Storage_Pools
+ RE_Adjust_Controlled_Dereference, -- System.Storage_Pools.Subpools
RE_Allocate_Any_Controlled, -- System.Storage_Pools.Subpools
RE_Deallocate_Any_Controlled, -- System.Storage_Pools.Subpools
RE_Header_Size_With_Padding, -- System.Storage_Pools.Subpools
@@ -2624,6 +2625,7 @@ package Rtsfind is
RE_Root_Storage_Pool => System_Storage_Pools,
RE_Root_Storage_Pool_Ptr => System_Storage_Pools,
+ RE_Adjust_Controlled_Dereference => System_Storage_Pools_Subpools,
RE_Allocate_Any_Controlled => System_Storage_Pools_Subpools,
RE_Deallocate_Any_Controlled => System_Storage_Pools_Subpools,
RE_Header_Size_With_Padding => System_Storage_Pools_Subpools,
diff --git a/gcc/ada/s-stposu.adb b/gcc/ada/s-stposu.adb
index 5ee3f2d..282cb7d 100644
--- a/gcc/ada/s-stposu.adb
+++ b/gcc/ada/s-stposu.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2011, Free Software Foundation, Inc. --
+-- Copyright (C) 2011-2012, 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- --
@@ -56,6 +56,24 @@ package body System.Storage_Pools.Subpools is
procedure Detach (N : not null SP_Node_Ptr);
-- Unhook a subpool node from an arbitrary subpool list
+ procedure Adjust_Controlled_Dereference
+ (Addr : in out System.Address;
+ Storage_Size : in out System.Storage_Elements.Storage_Count;
+ Alignment : System.Storage_Elements.Storage_Count)
+ is
+ Header_And_Padding : constant Storage_Offset :=
+ Header_Size_With_Padding (Alignment);
+ begin
+ -- Expose the two hidden pointers by shifting the address from the
+ -- start of the object to the FM_Node equivalent of the pointers.
+
+ Addr := Addr - Header_And_Padding;
+
+ -- Update the size of the object to include the two pointers
+
+ Storage_Size := Storage_Size + Header_And_Padding;
+ end Adjust_Controlled_Dereference;
+
--------------
-- Allocate --
--------------
diff --git a/gcc/ada/s-stposu.ads b/gcc/ada/s-stposu.ads
index 47099d2..40fe676 100644
--- a/gcc/ada/s-stposu.ads
+++ b/gcc/ada/s-stposu.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2011, Free Software Foundation, Inc. --
+-- Copyright (C) 2011-2012, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
@@ -249,6 +249,14 @@ private
-- This back pointer is used in subpool deallocation.
end record;
+ procedure Adjust_Controlled_Dereference
+ (Addr : in out System.Address;
+ Storage_Size : in out System.Storage_Elements.Storage_Count;
+ Alignment : System.Storage_Elements.Storage_Count);
+ -- Given the memory attributes of a heap-allocated object that is known to
+ -- be controlled, adjust the address and size of the object to include the
+ -- two hidden pointers inserted by the finalization machinery.
+
-- ??? Once Storage_Pools.Allocate_Any is removed, this should be renamed
-- to Allocate_Any.
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
index a89f9b2..e7ad52e 100644
--- a/gcc/ada/sinfo.adb
+++ b/gcc/ada/sinfo.adb
@@ -1427,6 +1427,14 @@ package body Sinfo is
return Flag15 (N);
end Has_Created_Identifier;
+ function Has_Dereference_Action
+ (N : Node_Id) return Boolean is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Explicit_Dereference);
+ return Flag13 (N);
+ end Has_Dereference_Action;
+
function Has_Dynamic_Length_Check
(N : Node_Id) return Boolean is
begin
@@ -4515,6 +4523,14 @@ package body Sinfo is
Set_Flag15 (N, Val);
end Set_Has_Created_Identifier;
+ procedure Set_Has_Dereference_Action
+ (N : Node_Id; Val : Boolean := True) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Explicit_Dereference);
+ Set_Flag13 (N, Val);
+ end Set_Has_Dereference_Action;
+
procedure Set_Has_Dynamic_Length_Check
(N : Node_Id; Val : Boolean := True) is
begin
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index fa7dbee..4ece762 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -1111,6 +1111,12 @@ package Sinfo is
-- handler is deleted during optimization. For further details on why
-- this is required, see Exp_Ch11.Remove_Handler_Entries.
+ -- Has_Dereference_Action (Flag13-Sem)
+ -- This flag is present in N_Explicit_Dereference nodes. It is set to
+ -- indicate that the expansion has aready produced a call to primitive
+ -- Dereference of a System.Checked_Pools.Checked_Pool implementation.
+ -- Such dereference actions are produced for debugging purposes.
+
-- Has_Dynamic_Length_Check (Flag10-Sem)
-- This flag is present in all expression nodes. It is set to indicate
-- that one of the routines in unit Checks has generated a length check
@@ -3192,6 +3198,7 @@ package Sinfo is
-- Prefix (Node3)
-- Actual_Designated_Subtype (Node4-Sem)
-- Atomic_Sync_Required (Flag14-Sem)
+ -- Has_Dereference_Action (Flag13-Sem)
-- plus fields for expression
-------------------------------
@@ -8524,6 +8531,9 @@ package Sinfo is
function Has_Created_Identifier
(N : Node_Id) return Boolean; -- Flag15
+ function Has_Dereference_Action
+ (N : Node_Id) return Boolean; -- Flag13
+
function Has_Dynamic_Length_Check
(N : Node_Id) return Boolean; -- Flag10
@@ -9508,6 +9518,9 @@ package Sinfo is
procedure Set_Has_Created_Identifier
(N : Node_Id; Val : Boolean := True); -- Flag15
+ procedure Set_Has_Dereference_Action
+ (N : Node_Id; Val : Boolean := True); -- Flag13
+
procedure Set_Has_Dynamic_Length_Check
(N : Node_Id; Val : Boolean := True); -- Flag10
@@ -11947,6 +11960,7 @@ package Sinfo is
pragma Inline (Handled_Statement_Sequence);
pragma Inline (Handler_List_Entry);
pragma Inline (Has_Created_Identifier);
+ pragma Inline (Has_Dereference_Action);
pragma Inline (Has_Dynamic_Length_Check);
pragma Inline (Has_Dynamic_Range_Check);
pragma Inline (Has_Init_Expression);
@@ -12272,6 +12286,7 @@ package Sinfo is
pragma Inline (Set_Handled_Statement_Sequence);
pragma Inline (Set_Handler_List_Entry);
pragma Inline (Set_Has_Created_Identifier);
+ pragma Inline (Set_Has_Dereference_Action);
pragma Inline (Set_Has_Dynamic_Length_Check);
pragma Inline (Set_Has_Init_Expression);
pragma Inline (Set_Has_Local_Raise);