OSDN Git Service

2010-01-25 Bob Duff <duff@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_atag.adb
index c2c37a7..d5cdf0b 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 2006-2007, Free Software Foundation, Inc.         --
+--          Copyright (C) 2006-2009, 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- --
 --                                                                          --
 ------------------------------------------------------------------------------
 
+with Atree;    use Atree;
 with Einfo;    use Einfo;
 with Elists;   use Elists;
 with Exp_Util; use Exp_Util;
+with Namet;    use Namet;
 with Nlists;   use Nlists;
 with Nmake;    use Nmake;
 with Rtsfind;  use Rtsfind;
+with Sinfo;    use Sinfo;
+with Sem_Aux;  use Sem_Aux;
 with Sem_Util; use Sem_Util;
 with Stand;    use Stand;
 with Snames;   use Snames;
@@ -50,21 +54,14 @@ package body Exp_Atag is
    --    To_Dispatch_Table_Ptr
    --      (To_Address (Tag_Node) - Tag_Node.Prims_Ptr'Position);
 
-   function Build_TSD (Loc : Source_Ptr; Tag_Node : Node_Id) return Node_Id;
+   function Build_TSD
+     (Loc           : Source_Ptr;
+      Tag_Node_Addr : Node_Id) return Node_Id;
    --  Build code that retrieves the address of the record containing the Type
    --  Specific Data generated by GNAT.
    --
    --  Generate: To_Type_Specific_Data_Ptr
-   --              (To_Addr_Ptr (To_Address (Tag) - Typeinfo_Offset).all);
-
-   function Build_Predef_Prims
-     (Loc      : Source_Ptr;
-      Tag_Node : Node_Id) return Node_Id;
-   --  Build code that retrieves the address of the dispatch table containing
-   --  the predefined Ada primitives:
-   --
-   --  Generate: To_Predef_Prims_Table_Ptr
-   --              (To_Addr_Ptr (To_Address (Tag) - Predef_Prims_Offset).all);
+   --              (To_Addr_Ptr (Tag_Node_Addr - Typeinfo_Offset).all);
 
    ------------------------------------------------
    -- Build_Common_Dispatching_Select_Statements --
@@ -146,39 +143,90 @@ package body Exp_Atag is
    -- Build_CW_Membership --
    -------------------------
 
-   function Build_CW_Membership
+   procedure Build_CW_Membership
      (Loc          : Source_Ptr;
-      Obj_Tag_Node : Node_Id;
-      Typ_Tag_Node : Node_Id) return Node_Id
+      Obj_Tag_Node : in out Node_Id;
+      Typ_Tag_Node : Node_Id;
+      Related_Nod  : Node_Id;
+      New_Node     : out Node_Id)
    is
-      function Build_Pos return Node_Id;
-      --  Generate TSD (Obj_Tag).Idepth - TSD (Typ_Tag).Idepth;
+      Tag_Addr : constant Entity_Id := Make_Defining_Identifier (Loc,
+                                         New_Internal_Name ('D'));
+      Obj_TSD  : constant Entity_Id := Make_Defining_Identifier (Loc,
+                                         New_Internal_Name ('D'));
+      Typ_TSD  : constant Entity_Id := Make_Defining_Identifier (Loc,
+                                         New_Internal_Name ('D'));
+      Index    : constant Entity_Id := Make_Defining_Identifier (Loc,
+                                         New_Internal_Name ('D'));
 
-      function Build_Pos return Node_Id is
-      begin
-         return
+   begin
+      --  Generate:
+
+      --    Tag_Addr : constant Tag := Address!(Obj_Tag);
+      --    Obj_TSD  : constant Type_Specific_Data_Ptr
+      --                          := Build_TSD (Tag_Addr);
+      --    Typ_TSD  : constant Type_Specific_Data_Ptr
+      --                          := Build_TSD (Address!(Typ_Tag));
+      --    Index    : constant Integer := Obj_TSD.Idepth - Typ_TSD.Idepth
+      --    Index > 0 and then Obj_TSD.Tags_Table (Index) = Typ'Tag
+
+      Insert_Action (Related_Nod,
+        Make_Object_Declaration (Loc,
+          Defining_Identifier => Tag_Addr,
+          Constant_Present    => True,
+          Object_Definition   => New_Reference_To (RTE (RE_Address), Loc),
+          Expression          => Unchecked_Convert_To
+                                   (RTE (RE_Address), Obj_Tag_Node)));
+
+      --  Unchecked_Convert_To relocates Obj_Tag_Node and therefore we must
+      --  update it.
+
+      Obj_Tag_Node := Expression (Expression (Parent (Tag_Addr)));
+
+      Insert_Action (Related_Nod,
+        Make_Object_Declaration (Loc,
+          Defining_Identifier => Obj_TSD,
+          Constant_Present    => True,
+          Object_Definition   => New_Reference_To
+                                   (RTE (RE_Type_Specific_Data_Ptr), Loc),
+          Expression => Build_TSD (Loc, New_Reference_To (Tag_Addr, Loc))));
+
+      Insert_Action (Related_Nod,
+        Make_Object_Declaration (Loc,
+          Defining_Identifier => Typ_TSD,
+          Constant_Present    => True,
+          Object_Definition   => New_Reference_To
+                                   (RTE (RE_Type_Specific_Data_Ptr), Loc),
+          Expression => Build_TSD (Loc,
+                          Unchecked_Convert_To (RTE (RE_Address),
+                            Typ_Tag_Node))));
+
+      Insert_Action (Related_Nod,
+        Make_Object_Declaration (Loc,
+          Defining_Identifier => Index,
+          Constant_Present    => True,
+          Object_Definition   => New_Occurrence_Of (Standard_Integer, Loc),
+          Expression =>
             Make_Op_Subtract (Loc,
               Left_Opnd =>
                 Make_Selected_Component (Loc,
-                  Prefix => Build_TSD (Loc, Duplicate_Subexpr (Obj_Tag_Node)),
+                  Prefix        => New_Reference_To (Obj_TSD, Loc),
                   Selector_Name =>
-                    New_Reference_To (RTE_Record_Component (RE_Idepth), Loc)),
+                     New_Reference_To
+                       (RTE_Record_Component (RE_Idepth), Loc)),
 
-              Right_Opnd =>
-                Make_Selected_Component (Loc,
-                  Prefix => Build_TSD (Loc, Duplicate_Subexpr (Typ_Tag_Node)),
-                  Selector_Name =>
-                    New_Reference_To (RTE_Record_Component (RE_Idepth), Loc)));
-      end Build_Pos;
-
-   --  Start of processing for Build_CW_Membership
+               Right_Opnd =>
+                 Make_Selected_Component (Loc,
+                   Prefix        => New_Reference_To (Typ_TSD, Loc),
+                   Selector_Name =>
+                     New_Reference_To
+                       (RTE_Record_Component (RE_Idepth), Loc)))));
 
-   begin
-      return
+      New_Node :=
         Make_And_Then (Loc,
           Left_Opnd =>
             Make_Op_Ge (Loc,
-              Left_Opnd  => Build_Pos,
+              Left_Opnd  => New_Occurrence_Of (Index, Loc),
               Right_Opnd => Make_Integer_Literal (Loc, Uint_0)),
 
           Right_Opnd =>
@@ -187,12 +235,12 @@ package body Exp_Atag is
                 Make_Indexed_Component (Loc,
                   Prefix =>
                     Make_Selected_Component (Loc,
-                      Prefix => Build_TSD (Loc, Obj_Tag_Node),
+                      Prefix        => New_Reference_To (Obj_TSD, Loc),
                       Selector_Name =>
                         New_Reference_To
                           (RTE_Record_Component (RE_Tags_Table), Loc)),
                   Expressions =>
-                    New_List (Build_Pos)),
+                    New_List (New_Occurrence_Of (Index, Loc))),
 
               Right_Opnd => Typ_Tag_Node));
    end Build_CW_Membership;
@@ -203,7 +251,8 @@ package body Exp_Atag is
 
    function Build_DT
      (Loc      : Source_Ptr;
-      Tag_Node : Node_Id) return Node_Id is
+      Tag_Node : Node_Id) return Node_Id
+   is
    begin
       return
         Make_Function_Call (Loc,
@@ -223,7 +272,9 @@ package body Exp_Atag is
    begin
       return
         Make_Selected_Component (Loc,
-          Prefix => Build_TSD (Loc, Tag_Node),
+          Prefix =>
+            Build_TSD (Loc,
+              Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
           Selector_Name =>
             New_Reference_To
               (RTE_Record_Component (RE_Access_Level), Loc));
@@ -233,16 +284,49 @@ package body Exp_Atag is
    -- Build_Get_Predefined_Prim_Op_Address --
    ------------------------------------------
 
-   function Build_Get_Predefined_Prim_Op_Address
+   procedure Build_Get_Predefined_Prim_Op_Address
      (Loc      : Source_Ptr;
-      Tag_Node : Node_Id;
-      Position : Uint) return Node_Id
+      Position : Uint;
+      Tag_Node : in out Node_Id;
+      New_Node : out Node_Id)
    is
+      Ctrl_Tag : Node_Id;
+
    begin
-      return
+      Ctrl_Tag := Unchecked_Convert_To (RTE (RE_Address), Tag_Node);
+
+      --  Unchecked_Convert_To relocates the controlling tag node and therefore
+      --  we must update it.
+
+      Tag_Node := Expression (Ctrl_Tag);
+
+      --  Build code that retrieves the address of the dispatch table
+      --  containing the predefined Ada primitives:
+      --
+      --  Generate:
+      --    To_Predef_Prims_Table_Ptr
+      --     (To_Addr_Ptr (To_Address (Tag) - Predef_Prims_Offset).all);
+
+      New_Node :=
         Make_Indexed_Component (Loc,
           Prefix =>
-            Build_Predef_Prims (Loc, Tag_Node),
+            Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
+              Make_Explicit_Dereference (Loc,
+                Unchecked_Convert_To (RTE (RE_Addr_Ptr),
+                  Make_Function_Call (Loc,
+                    Name =>
+                      Make_Expanded_Name (Loc,
+                        Chars => Name_Op_Subtract,
+                        Prefix =>
+                          New_Reference_To
+                            (RTU_Entity (System_Storage_Elements), Loc),
+                        Selector_Name =>
+                          Make_Identifier (Loc,
+                            Chars => Name_Op_Subtract)),
+                    Parameter_Associations => New_List (
+                      Ctrl_Tag,
+                      New_Reference_To (RTE (RE_DT_Predef_Prims_Offset),
+                                        Loc)))))),
           Expressions =>
             New_List (Make_Integer_Literal (Loc, Position)));
    end Build_Get_Predefined_Prim_Op_Address;
@@ -320,12 +404,15 @@ package body Exp_Atag is
    -- Build_Get_Prim_Op_Address --
    -------------------------------
 
-   function Build_Get_Prim_Op_Address
+   procedure Build_Get_Prim_Op_Address
      (Loc      : Source_Ptr;
       Typ      : Entity_Id;
-      Tag_Node : Node_Id;
-      Position : Uint) return Node_Id
+      Position : Uint;
+      Tag_Node : in out Node_Id;
+      New_Node : out Node_Id)
    is
+      New_Prefix : Node_Id;
+
    begin
       pragma Assert
         (Position <= DT_Entry_Count (First_Tag_Component (Typ)));
@@ -334,11 +421,18 @@ package body Exp_Atag is
       --  declaration required to convert the tag into a pointer to
       --  the prims_ptr table (see Freeze_Record_Type).
 
-      return
+      New_Prefix :=
+        Unchecked_Convert_To
+          (Node (Last_Elmt (Access_Disp_Table (Typ))), Tag_Node);
+
+      --  Unchecked_Convert_To relocates the controlling tag node and therefore
+      --  we must update it.
+
+      Tag_Node := Expression (New_Prefix);
+
+      New_Node :=
         Make_Indexed_Component (Loc,
-          Prefix =>
-            Unchecked_Convert_To
-              (Node (Last_Elmt (Access_Disp_Table (Typ))), Tag_Node),
+          Prefix      => New_Prefix,
           Expressions => New_List (Make_Integer_Literal (Loc, Position)));
    end Build_Get_Prim_Op_Address;
 
@@ -353,7 +447,9 @@ package body Exp_Atag is
    begin
       return
         Make_Selected_Component (Loc,
-          Prefix => Build_TSD (Loc, Tag_Node),
+          Prefix =>
+            Build_TSD (Loc,
+              Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
           Selector_Name =>
             New_Reference_To
               (RTE_Record_Component (RE_Transportable), Loc));
@@ -397,35 +493,37 @@ package body Exp_Atag is
                   New_Reference_To (RTE (RE_Max_Predef_Prims), Loc))));
    end Build_Inherit_Predefined_Prims;
 
-   ------------------------
-   -- Build_Predef_Prims --
-   ------------------------
+   -------------------------
+   -- Build_Offset_To_Top --
+   -------------------------
 
-   function Build_Predef_Prims
-     (Loc      : Source_Ptr;
-      Tag_Node : Node_Id) return Node_Id
+   function Build_Offset_To_Top
+     (Loc       : Source_Ptr;
+      This_Node : Node_Id) return Node_Id
    is
+      Tag_Node : Node_Id;
+
    begin
-      return
-        Unchecked_Convert_To (RTE (RE_Predef_Prims_Table_Ptr),
-          Make_Explicit_Dereference (Loc,
-            Unchecked_Convert_To (RTE (RE_Addr_Ptr),
-              Make_Function_Call (Loc,
-                Name =>
-                  Make_Expanded_Name (Loc,
-                    Chars => Name_Op_Subtract,
-                    Prefix =>
-                      New_Reference_To
-                        (RTU_Entity (System_Storage_Elements), Loc),
-                    Selector_Name =>
-                      Make_Identifier (Loc,
-                        Chars => Name_Op_Subtract)),
+      Tag_Node :=
+        Make_Explicit_Dereference (Loc,
+          Unchecked_Convert_To (RTE (RE_Tag_Ptr), This_Node));
 
-                Parameter_Associations => New_List (
-                  Unchecked_Convert_To (RTE (RE_Address), Tag_Node),
-                  New_Reference_To (RTE (RE_DT_Predef_Prims_Offset),
-                                    Loc))))));
-   end Build_Predef_Prims;
+      return
+        Make_Explicit_Dereference (Loc,
+          Unchecked_Convert_To (RTE (RE_Offset_To_Top_Ptr),
+            Make_Function_Call (Loc,
+              Name =>
+                Make_Expanded_Name (Loc,
+                  Chars => Name_Op_Subtract,
+                  Prefix => New_Reference_To
+                             (RTU_Entity (System_Storage_Elements), Loc),
+                  Selector_Name => Make_Identifier (Loc,
+                                     Chars => Name_Op_Subtract)),
+              Parameter_Associations => New_List (
+                Unchecked_Convert_To (RTE (RE_Address), Tag_Node),
+                New_Reference_To (RTE (RE_DT_Offset_To_Top_Offset),
+                                  Loc)))));
+   end Build_Offset_To_Top;
 
    ------------------------------------------
    -- Build_Set_Predefined_Prim_Op_Address --
@@ -463,19 +561,81 @@ package body Exp_Atag is
       Position     : Uint;
       Address_Node : Node_Id) return Node_Id
    is
+      Ctrl_Tag : Node_Id := Tag_Node;
+      New_Node : Node_Id;
+
    begin
+      Build_Get_Prim_Op_Address (Loc, Typ, Position, Ctrl_Tag, New_Node);
+
       return
         Make_Assignment_Statement (Loc,
-          Name       => Build_Get_Prim_Op_Address
-                          (Loc, Typ, Tag_Node, Position),
+          Name       => New_Node,
           Expression => Address_Node);
    end Build_Set_Prim_Op_Address;
 
+   -----------------------------
+   -- Build_Set_Size_Function --
+   -----------------------------
+
+   function Build_Set_Size_Function
+     (Loc       : Source_Ptr;
+      Tag_Node  : Node_Id;
+      Size_Func : Entity_Id) return Node_Id is
+   begin
+      pragma Assert (Chars (Size_Func) = Name_uSize
+        and then RTE_Record_Component_Available (RE_Size_Func));
+      return
+        Make_Assignment_Statement (Loc,
+          Name =>
+            Make_Selected_Component (Loc,
+              Prefix =>
+                Build_TSD (Loc,
+                  Unchecked_Convert_To (RTE (RE_Address), Tag_Node)),
+              Selector_Name =>
+                New_Reference_To
+                  (RTE_Record_Component (RE_Size_Func), Loc)),
+          Expression =>
+            Unchecked_Convert_To (RTE (RE_Size_Ptr),
+              Make_Attribute_Reference (Loc,
+                Prefix => New_Reference_To (Size_Func, Loc),
+                Attribute_Name => Name_Unrestricted_Access)));
+   end Build_Set_Size_Function;
+
+   ------------------------------------
+   -- Build_Set_Static_Offset_To_Top --
+   ------------------------------------
+
+   function Build_Set_Static_Offset_To_Top
+     (Loc          : Source_Ptr;
+      Iface_Tag    : Node_Id;
+      Offset_Value : Node_Id) return Node_Id is
+   begin
+      return
+        Make_Assignment_Statement (Loc,
+          Make_Explicit_Dereference (Loc,
+            Unchecked_Convert_To (RTE (RE_Offset_To_Top_Ptr),
+              Make_Function_Call (Loc,
+                Name =>
+                  Make_Expanded_Name (Loc,
+                    Chars => Name_Op_Subtract,
+                    Prefix => New_Reference_To
+                               (RTU_Entity (System_Storage_Elements), Loc),
+                    Selector_Name => Make_Identifier (Loc,
+                                       Chars => Name_Op_Subtract)),
+                Parameter_Associations => New_List (
+                  Unchecked_Convert_To (RTE (RE_Address), Iface_Tag),
+                  New_Reference_To (RTE (RE_DT_Offset_To_Top_Offset),
+                                    Loc))))),
+          Offset_Value);
+   end Build_Set_Static_Offset_To_Top;
+
    ---------------
    -- Build_TSD --
    ---------------
 
-   function Build_TSD (Loc : Source_Ptr; Tag_Node : Node_Id) return Node_Id is
+   function Build_TSD
+     (Loc           : Source_Ptr;
+      Tag_Node_Addr : Node_Id) return Node_Id is
    begin
       return
         Unchecked_Convert_To (RTE (RE_Type_Specific_Data_Ptr),
@@ -493,9 +653,9 @@ package body Exp_Atag is
                         Chars => Name_Op_Subtract)),
 
                 Parameter_Associations => New_List (
-                  Unchecked_Convert_To (RTE (RE_Address), Tag_Node),
-                    New_Reference_To
-                      (RTE (RE_DT_Typeinfo_Ptr_Size), Loc))))));
+                  Tag_Node_Addr,
+                  New_Reference_To
+                    (RTE (RE_DT_Typeinfo_Ptr_Size), Loc))))));
    end Build_TSD;
 
 end Exp_Atag;