1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
9 -- Copyright (C) 1992-2015, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
33 with Ada
.Unchecked_Conversion
;
36 with System
.Storage_Elements
; use System
.Storage_Elements
;
37 with System
.WCh_Con
; use System
.WCh_Con
;
38 with System
.WCh_StW
; use System
.WCh_StW
;
40 pragma Elaborate
(System
.HTable
);
41 -- Elaborate needed instead of Elaborate_All to avoid elaboration cycles
42 -- when polling is turned on. This is safe because HTable doesn't do anything
43 -- at elaboration time; it just contains a generic package we want to
46 package body Ada
.Tags
is
48 -----------------------
49 -- Local Subprograms --
50 -----------------------
52 function CW_Membership
(Obj_Tag
: Tag
; Typ_Tag
: Tag
) return Boolean;
53 -- Given the tag of an object and the tag associated to a type, return
54 -- true if Obj is in Typ'Class.
56 function Get_External_Tag
(T
: Tag
) return System
.Address
;
57 -- Returns address of a null terminated string containing the external name
59 function Is_Primary_DT
(T
: Tag
) return Boolean;
60 -- Given a tag returns True if it has the signature of a primary dispatch
61 -- table. This is Inline_Always since it is called from other Inline_
62 -- Always subprograms where we want no out of line code to be generated.
64 function Length
(Str
: Cstring_Ptr
) return Natural;
65 -- Length of string represented by the given pointer (treating the string
66 -- as a C-style string, which is Nul terminated). See comment in body
67 -- explaining why we cannot use the normal strlen built-in.
69 function OSD
(T
: Tag
) return Object_Specific_Data_Ptr
;
70 -- Ada 2005 (AI-251): Given a pointer T to a secondary dispatch table,
71 -- retrieve the address of the record containing the Object Specific
74 function SSD
(T
: Tag
) return Select_Specific_Data_Ptr
;
75 -- Ada 2005 (AI-251): Given a pointer T to a dispatch Table, retrieves the
76 -- address of the record containing the Select Specific Data in T's TSD.
78 pragma Inline_Always
(CW_Membership
);
79 pragma Inline_Always
(Get_External_Tag
);
80 pragma Inline_Always
(Is_Primary_DT
);
81 pragma Inline_Always
(OSD
);
82 pragma Inline_Always
(SSD
);
84 -- Unchecked conversions
86 function To_Address
is
87 new Unchecked_Conversion
(Cstring_Ptr
, System
.Address
);
89 function To_Cstring_Ptr
is
90 new Unchecked_Conversion
(System
.Address
, Cstring_Ptr
);
92 -- Disable warnings on possible aliasing problem
95 new Unchecked_Conversion
(Integer_Address
, Tag
);
97 function To_Addr_Ptr
is
98 new Ada
.Unchecked_Conversion
(System
.Address
, Addr_Ptr
);
100 function To_Address
is
101 new Ada
.Unchecked_Conversion
(Tag
, System
.Address
);
103 function To_Dispatch_Table_Ptr
is
104 new Ada
.Unchecked_Conversion
(Tag
, Dispatch_Table_Ptr
);
106 function To_Dispatch_Table_Ptr
is
107 new Ada
.Unchecked_Conversion
(System
.Address
, Dispatch_Table_Ptr
);
109 function To_Object_Specific_Data_Ptr
is
110 new Ada
.Unchecked_Conversion
(System
.Address
, Object_Specific_Data_Ptr
);
112 function To_Tag_Ptr
is
113 new Ada
.Unchecked_Conversion
(System
.Address
, Tag_Ptr
);
115 function To_Type_Specific_Data_Ptr
is
116 new Ada
.Unchecked_Conversion
(System
.Address
, Type_Specific_Data_Ptr
);
118 -------------------------------
119 -- Inline_Always Subprograms --
120 -------------------------------
122 -- Inline_always subprograms must be placed before their first call to
123 -- avoid defeating the frontend inlining mechanism and thus ensure the
124 -- generation of their correct debug info.
130 -- Canonical implementation of Classwide Membership corresponding to:
134 -- Each dispatch table contains a reference to a table of ancestors (stored
135 -- in the first part of the Tags_Table) and a count of the level of
136 -- inheritance "Idepth".
138 -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
139 -- contained in the dispatch table referenced by Obj'Tag . Knowing the
140 -- level of inheritance of both types, this can be computed in constant
141 -- time by the formula:
143 -- TSD (Obj'tag).Tags_Table (TSD (Obj'tag).Idepth - TSD (Typ'tag).Idepth)
146 function CW_Membership
(Obj_Tag
: Tag
; Typ_Tag
: Tag
) return Boolean is
147 Obj_TSD_Ptr
: constant Addr_Ptr
:=
148 To_Addr_Ptr
(To_Address
(Obj_Tag
) - DT_Typeinfo_Ptr_Size
);
149 Typ_TSD_Ptr
: constant Addr_Ptr
:=
150 To_Addr_Ptr
(To_Address
(Typ_Tag
) - DT_Typeinfo_Ptr_Size
);
151 Obj_TSD
: constant Type_Specific_Data_Ptr
:=
152 To_Type_Specific_Data_Ptr
(Obj_TSD_Ptr
.all);
153 Typ_TSD
: constant Type_Specific_Data_Ptr
:=
154 To_Type_Specific_Data_Ptr
(Typ_TSD_Ptr
.all);
155 Pos
: constant Integer := Obj_TSD
.Idepth
- Typ_TSD
.Idepth
;
157 return Pos
>= 0 and then Obj_TSD
.Tags_Table
(Pos
) = Typ_Tag
;
160 ----------------------
161 -- Get_External_Tag --
162 ----------------------
164 function Get_External_Tag
(T
: Tag
) return System
.Address
is
165 TSD_Ptr
: constant Addr_Ptr
:=
166 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
167 TSD
: constant Type_Specific_Data_Ptr
:=
168 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
170 return To_Address
(TSD
.External_Tag
);
171 end Get_External_Tag
;
177 function Is_Primary_DT
(T
: Tag
) return Boolean is
179 return DT
(T
).Signature
= Primary_DT
;
186 function OSD
(T
: Tag
) return Object_Specific_Data_Ptr
is
187 OSD_Ptr
: constant Addr_Ptr
:=
188 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
190 return To_Object_Specific_Data_Ptr
(OSD_Ptr
.all);
197 function SSD
(T
: Tag
) return Select_Specific_Data_Ptr
is
198 TSD_Ptr
: constant Addr_Ptr
:=
199 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
200 TSD
: constant Type_Specific_Data_Ptr
:=
201 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
206 -------------------------
207 -- External_Tag_HTable --
208 -------------------------
210 type HTable_Headers
is range 1 .. 64;
212 -- The following internal package defines the routines used for the
213 -- instantiation of a new System.HTable.Static_HTable (see below). See
214 -- spec in g-htable.ads for details of usage.
216 package HTable_Subprograms
is
217 procedure Set_HT_Link
(T
: Tag
; Next
: Tag
);
218 function Get_HT_Link
(T
: Tag
) return Tag
;
219 function Hash
(F
: System
.Address
) return HTable_Headers
;
220 function Equal
(A
, B
: System
.Address
) return Boolean;
221 end HTable_Subprograms
;
223 package External_Tag_HTable
is new System
.HTable
.Static_HTable
(
224 Header_Num
=> HTable_Headers
,
225 Element
=> Dispatch_Table
,
228 Set_Next
=> HTable_Subprograms
.Set_HT_Link
,
229 Next
=> HTable_Subprograms
.Get_HT_Link
,
230 Key
=> System
.Address
,
231 Get_Key
=> Get_External_Tag
,
232 Hash
=> HTable_Subprograms
.Hash
,
233 Equal
=> HTable_Subprograms
.Equal
);
235 ------------------------
236 -- HTable_Subprograms --
237 ------------------------
239 -- Bodies of routines for hash table instantiation
241 package body HTable_Subprograms
is
247 function Equal
(A
, B
: System
.Address
) return Boolean is
248 Str1
: constant Cstring_Ptr
:= To_Cstring_Ptr
(A
);
249 Str2
: constant Cstring_Ptr
:= To_Cstring_Ptr
(B
);
254 if Str1
(J
) /= Str2
(J
) then
256 elsif Str1
(J
) = ASCII
.NUL
then
268 function Get_HT_Link
(T
: Tag
) return Tag
is
269 TSD_Ptr
: constant Addr_Ptr
:=
270 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
271 TSD
: constant Type_Specific_Data_Ptr
:=
272 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
274 return TSD
.HT_Link
.all;
281 function Hash
(F
: System
.Address
) return HTable_Headers
is
282 function H
is new System
.HTable
.Hash
(HTable_Headers
);
283 Str
: constant Cstring_Ptr
:= To_Cstring_Ptr
(F
);
284 Res
: constant HTable_Headers
:= H
(Str
(1 .. Length
(Str
)));
293 procedure Set_HT_Link
(T
: Tag
; Next
: Tag
) is
294 TSD_Ptr
: constant Addr_Ptr
:=
295 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
296 TSD
: constant Type_Specific_Data_Ptr
:=
297 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
299 TSD
.HT_Link
.all := Next
;
302 end HTable_Subprograms
;
308 function Base_Address
(This
: System
.Address
) return System
.Address
is
310 return This
- Offset_To_Top
(This
);
317 procedure Check_TSD
(TSD
: Type_Specific_Data_Ptr
) is
320 E_Tag_Len
: constant Integer := Length
(TSD
.External_Tag
);
321 E_Tag
: String (1 .. E_Tag_Len
);
322 for E_Tag
'Address use TSD
.External_Tag
.all'Address;
323 pragma Import
(Ada
, E_Tag
);
325 Dup_Ext_Tag
: constant String := "duplicated external tag """;
328 -- Verify that the external tag of this TSD is not registered in the
329 -- runtime hash table.
331 T
:= External_Tag_HTable
.Get
(To_Address
(TSD
.External_Tag
));
335 -- Avoid concatenation, as it is not allowed in no run time mode
338 Msg
: String (1 .. Dup_Ext_Tag
'Length + E_Tag_Len
+ 1);
340 Msg
(1 .. Dup_Ext_Tag
'Length) := Dup_Ext_Tag
;
341 Msg
(Dup_Ext_Tag
'Length + 1 .. Dup_Ext_Tag
'Length + E_Tag_Len
) :=
343 Msg
(Msg
'Last) := '"';
344 raise Program_Error
with Msg
;
353 function Descendant_Tag
(External
: String; Ancestor
: Tag
) return Tag
is
354 Int_Tag
: constant Tag
:= Internal_Tag
(External
);
356 if not Is_Descendant_At_Same_Level
(Int_Tag
, Ancestor
) then
367 function Displace
(This
: System
.Address
; T
: Tag
) return System
.Address
is
368 Iface_Table
: Interface_Data_Ptr
;
369 Obj_Base
: System
.Address
;
370 Obj_DT
: Dispatch_Table_Ptr
;
374 if System
."=" (This
, System
.Null_Address
) then
375 return System
.Null_Address
;
378 Obj_Base
:= Base_Address
(This
);
379 Obj_DT_Tag
:= To_Tag_Ptr
(Obj_Base
).all;
380 Obj_DT
:= DT
(To_Tag_Ptr
(Obj_Base
).all);
381 Iface_Table
:= To_Type_Specific_Data_Ptr
(Obj_DT
.TSD
).Interfaces_Table
;
383 if Iface_Table
/= null then
384 for Id
in 1 .. Iface_Table
.Nb_Ifaces
loop
385 if Iface_Table
.Ifaces_Table
(Id
).Iface_Tag
= T
then
387 -- Case of Static value of Offset_To_Top
389 if Iface_Table
.Ifaces_Table
(Id
).Static_Offset_To_Top
then
390 Obj_Base
:= Obj_Base
+
391 Iface_Table
.Ifaces_Table
(Id
).Offset_To_Top_Value
;
393 -- Otherwise call the function generated by the expander to
394 -- provide the value.
397 Obj_Base
:= Obj_Base
+
398 Iface_Table
.Ifaces_Table
(Id
).Offset_To_Top_Func
.all
407 -- Check if T is an immediate ancestor. This is required to handle
408 -- conversion of class-wide interfaces to tagged types.
410 if CW_Membership
(Obj_DT_Tag
, T
) then
414 -- If the object does not implement the interface we must raise CE
416 raise Constraint_Error
with "invalid interface conversion";
423 function DT
(T
: Tag
) return Dispatch_Table_Ptr
is
424 Offset
: constant SSE
.Storage_Offset
:=
425 To_Dispatch_Table_Ptr
(T
).Prims_Ptr
'Position;
427 return To_Dispatch_Table_Ptr
(To_Address
(T
) - Offset
);
434 -- Canonical implementation of Classwide Membership corresponding to:
436 -- Obj in Iface'Class
438 -- Each dispatch table contains a table with the tags of all the
439 -- implemented interfaces.
441 -- Obj is in Iface'Class if Iface'Tag is found in the table of interfaces
442 -- that are contained in the dispatch table referenced by Obj'Tag.
444 function IW_Membership
(This
: System
.Address
; T
: Tag
) return Boolean is
445 Iface_Table
: Interface_Data_Ptr
;
446 Obj_Base
: System
.Address
;
447 Obj_DT
: Dispatch_Table_Ptr
;
448 Obj_TSD
: Type_Specific_Data_Ptr
;
451 Obj_Base
:= Base_Address
(This
);
452 Obj_DT
:= DT
(To_Tag_Ptr
(Obj_Base
).all);
453 Obj_TSD
:= To_Type_Specific_Data_Ptr
(Obj_DT
.TSD
);
454 Iface_Table
:= Obj_TSD
.Interfaces_Table
;
456 if Iface_Table
/= null then
457 for Id
in 1 .. Iface_Table
.Nb_Ifaces
loop
458 if Iface_Table
.Ifaces_Table
(Id
).Iface_Tag
= T
then
464 -- Look for the tag in the ancestor tags table. This is required for:
465 -- Iface_CW in Typ'Class
467 for Id
in 0 .. Obj_TSD
.Idepth
loop
468 if Obj_TSD
.Tags_Table
(Id
) = T
then
480 function Expanded_Name
(T
: Tag
) return String is
481 Result
: Cstring_Ptr
;
483 TSD
: Type_Specific_Data_Ptr
;
490 TSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
491 TSD
:= To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
492 Result
:= TSD
.Expanded_Name
;
493 return Result
(1 .. Length
(Result
));
500 function External_Tag
(T
: Tag
) return String is
501 Result
: Cstring_Ptr
;
503 TSD
: Type_Specific_Data_Ptr
;
510 TSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
511 TSD
:= To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
512 Result
:= TSD
.External_Tag
;
513 return Result
(1 .. Length
(Result
));
516 ---------------------
517 -- Get_Entry_Index --
518 ---------------------
520 function Get_Entry_Index
(T
: Tag
; Position
: Positive) return Positive is
522 return SSD
(T
).SSD_Table
(Position
).Index
;
525 ----------------------
526 -- Get_Prim_Op_Kind --
527 ----------------------
529 function Get_Prim_Op_Kind
531 Position
: Positive) return Prim_Op_Kind
534 return SSD
(T
).SSD_Table
(Position
).Kind
;
535 end Get_Prim_Op_Kind
;
537 ----------------------
538 -- Get_Offset_Index --
539 ----------------------
541 function Get_Offset_Index
543 Position
: Positive) return Positive
546 if Is_Primary_DT
(T
) then
549 return OSD
(T
).OSD_Table
(Position
);
551 end Get_Offset_Index
;
553 ---------------------
554 -- Get_Tagged_Kind --
555 ---------------------
557 function Get_Tagged_Kind
(T
: Tag
) return Tagged_Kind
is
559 return DT
(T
).Tag_Kind
;
562 -----------------------------
563 -- Interface_Ancestor_Tags --
564 -----------------------------
566 function Interface_Ancestor_Tags
(T
: Tag
) return Tag_Array
is
567 TSD_Ptr
: constant Addr_Ptr
:=
568 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
569 TSD
: constant Type_Specific_Data_Ptr
:=
570 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
571 Iface_Table
: constant Interface_Data_Ptr
:= TSD
.Interfaces_Table
;
574 if Iface_Table
= null then
576 Table
: Tag_Array
(1 .. 0);
583 Table
: Tag_Array
(1 .. Iface_Table
.Nb_Ifaces
);
585 for J
in 1 .. Iface_Table
.Nb_Ifaces
loop
586 Table
(J
) := Iface_Table
.Ifaces_Table
(J
).Iface_Tag
;
592 end Interface_Ancestor_Tags
;
598 -- Internal tags have the following format:
599 -- "Internal tag at 16#ADDRESS#: <full-name-of-tagged-type>"
601 Internal_Tag_Header
: constant String := "Internal tag at ";
602 Header_Separator
: constant Character := '#';
604 function Internal_Tag
(External
: String) return Tag
is
605 Ext_Copy
: aliased String (External
'First .. External
'Last + 1);
609 -- Handle locally defined tagged types
611 if External
'Length > Internal_Tag_Header
'Length
613 External
(External
'First ..
614 External
'First + Internal_Tag_Header
'Length - 1) =
618 Addr_First
: constant Natural :=
619 External
'First + Internal_Tag_Header
'Length;
621 Addr
: Integer_Address
;
624 -- Search the second separator (#) to identify the address
626 Addr_Last
:= Addr_First
;
629 while Addr_Last
<= External
'Last
630 and then External
(Addr_Last
) /= Header_Separator
632 Addr_Last
:= Addr_Last
+ 1;
635 -- Skip the first separator
638 Addr_Last
:= Addr_Last
+ 1;
642 if Addr_Last
<= External
'Last then
644 -- Protect the run-time against wrong internal tags. We
645 -- cannot use exception handlers here because it would
646 -- disable the use of this run-time compiling with
647 -- restriction No_Exception_Handler.
651 Wrong_Tag
: Boolean := False;
654 if External
(Addr_First
) /= '1'
655 or else External
(Addr_First
+ 1) /= '6'
656 or else External
(Addr_First
+ 2) /= '#'
661 for J
in Addr_First
+ 3 .. Addr_Last
- 1 loop
664 if not (C
in '0' .. '9')
665 and then not (C
in 'A' .. 'F')
666 and then not (C
in 'a' .. 'f')
674 -- Convert the numeric value into a tag
676 if not Wrong_Tag
then
677 Addr
:= Integer_Address
'Value
678 (External
(Addr_First
.. Addr_Last
));
680 -- Internal tags never have value 0
683 return To_Tag
(Addr
);
690 -- Handle library-level tagged types
693 -- Make NUL-terminated copy of external tag string
695 Ext_Copy
(External
'Range) := External
;
696 Ext_Copy
(Ext_Copy
'Last) := ASCII
.NUL
;
697 Res
:= External_Tag_HTable
.Get
(Ext_Copy
'Address);
702 Msg1
: constant String := "unknown tagged type: ";
703 Msg2
: String (1 .. Msg1
'Length + External
'Length);
706 Msg2
(1 .. Msg1
'Length) := Msg1
;
707 Msg2
(Msg1
'Length + 1 .. Msg1
'Length + External
'Length) :=
709 Ada
.Exceptions
.Raise_Exception
(Tag_Error
'Identity, Msg2
);
716 ---------------------------------
717 -- Is_Descendant_At_Same_Level --
718 ---------------------------------
720 function Is_Descendant_At_Same_Level
722 Ancestor
: Tag
) return Boolean
724 D_TSD_Ptr
: constant Addr_Ptr
:=
725 To_Addr_Ptr
(To_Address
(Descendant
) - DT_Typeinfo_Ptr_Size
);
726 A_TSD_Ptr
: constant Addr_Ptr
:=
727 To_Addr_Ptr
(To_Address
(Ancestor
) - DT_Typeinfo_Ptr_Size
);
728 D_TSD
: constant Type_Specific_Data_Ptr
:=
729 To_Type_Specific_Data_Ptr
(D_TSD_Ptr
.all);
730 A_TSD
: constant Type_Specific_Data_Ptr
:=
731 To_Type_Specific_Data_Ptr
(A_TSD_Ptr
.all);
734 return CW_Membership
(Descendant
, Ancestor
)
735 and then D_TSD
.Access_Level
= A_TSD
.Access_Level
;
736 end Is_Descendant_At_Same_Level
;
742 -- Note: This unit is used in the Ravenscar runtime library, so it cannot
743 -- depend on System.CTRL. Furthermore, this happens on CPUs where the GCC
744 -- intrinsic strlen may not be available, so we need to recode our own Ada
747 function Length
(Str
: Cstring_Ptr
) return Natural is
752 while Str
(Len
) /= ASCII
.NUL
loop
763 function Offset_To_Top
764 (This
: System
.Address
) return SSE
.Storage_Offset
766 Tag_Size
: constant SSE
.Storage_Count
:=
767 SSE
.Storage_Count
(1 * (Standard
'Address_Size / System
.Storage_Unit
));
769 type Storage_Offset_Ptr
is access SSE
.Storage_Offset
;
770 function To_Storage_Offset_Ptr
is
771 new Unchecked_Conversion
(System
.Address
, Storage_Offset_Ptr
);
773 Curr_DT
: Dispatch_Table_Ptr
;
776 Curr_DT
:= DT
(To_Tag_Ptr
(This
).all);
778 if Curr_DT
.Offset_To_Top
= SSE
.Storage_Offset
'Last then
779 return To_Storage_Offset_Ptr
(This
+ Tag_Size
).all;
781 return Curr_DT
.Offset_To_Top
;
785 ------------------------
786 -- Needs_Finalization --
787 ------------------------
789 function Needs_Finalization
(T
: Tag
) return Boolean is
790 TSD_Ptr
: constant Addr_Ptr
:=
791 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
792 TSD
: constant Type_Specific_Data_Ptr
:=
793 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
795 return TSD
.Needs_Finalization
;
796 end Needs_Finalization
;
803 (Obj
: System
.Address
;
804 T
: Tag
) return SSE
.Storage_Count
806 Parent_Slot
: constant Positive := 1;
807 -- The tag of the parent is always in the first slot of the table of
810 TSD_Ptr
: constant Addr_Ptr
:=
811 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
812 TSD
: constant Type_Specific_Data_Ptr
:=
813 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
814 -- Pointer to the TSD
816 Parent_Tag
: constant Tag
:= TSD
.Tags_Table
(Parent_Slot
);
817 Parent_TSD_Ptr
: constant Addr_Ptr
:=
818 To_Addr_Ptr
(To_Address
(Parent_Tag
) - DT_Typeinfo_Ptr_Size
);
819 Parent_TSD
: constant Type_Specific_Data_Ptr
:=
820 To_Type_Specific_Data_Ptr
(Parent_TSD_Ptr
.all);
823 -- Here we compute the size of the _parent field of the object
825 return SSE
.Storage_Count
(Parent_TSD
.Size_Func
.all (Obj
));
832 function Parent_Tag
(T
: Tag
) return Tag
is
834 TSD
: Type_Specific_Data_Ptr
;
841 TSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
842 TSD
:= To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
844 -- The Parent_Tag of a root-level tagged type is defined to be No_Tag.
845 -- The first entry in the Ancestors_Tags array will be null for such
846 -- a type, but it's better to be explicit about returning No_Tag in
849 if TSD
.Idepth
= 0 then
852 return TSD
.Tags_Table
(1);
856 -------------------------------
857 -- Register_Interface_Offset --
858 -------------------------------
860 procedure Register_Interface_Offset
861 (This
: System
.Address
;
864 Offset_Value
: SSE
.Storage_Offset
;
865 Offset_Func
: Offset_To_Top_Function_Ptr
)
867 Prim_DT
: Dispatch_Table_Ptr
;
868 Iface_Table
: Interface_Data_Ptr
;
871 -- "This" points to the primary DT and we must save Offset_Value in
872 -- the Offset_To_Top field of the corresponding dispatch table.
874 Prim_DT
:= DT
(To_Tag_Ptr
(This
).all);
875 Iface_Table
:= To_Type_Specific_Data_Ptr
(Prim_DT
.TSD
).Interfaces_Table
;
877 -- Save Offset_Value in the table of interfaces of the primary DT.
878 -- This data will be used by the subprogram "Displace" to give support
879 -- to backward abstract interface type conversions.
881 -- Register the offset in the table of interfaces
883 if Iface_Table
/= null then
884 for Id
in 1 .. Iface_Table
.Nb_Ifaces
loop
885 if Iface_Table
.Ifaces_Table
(Id
).Iface_Tag
= Interface_T
then
886 if Is_Static
or else Offset_Value
= 0 then
887 Iface_Table
.Ifaces_Table
(Id
).Static_Offset_To_Top
:= True;
888 Iface_Table
.Ifaces_Table
(Id
).Offset_To_Top_Value
:=
891 Iface_Table
.Ifaces_Table
(Id
).Static_Offset_To_Top
:= False;
892 Iface_Table
.Ifaces_Table
(Id
).Offset_To_Top_Func
:=
901 -- If we arrive here there is some error in the run-time data structure
904 end Register_Interface_Offset
;
910 procedure Register_Tag
(T
: Tag
) is
912 External_Tag_HTable
.Set
(T
);
919 function Secondary_Tag
(T
, Iface
: Tag
) return Tag
is
920 Iface_Table
: Interface_Data_Ptr
;
921 Obj_DT
: Dispatch_Table_Ptr
;
924 if not Is_Primary_DT
(T
) then
929 Iface_Table
:= To_Type_Specific_Data_Ptr
(Obj_DT
.TSD
).Interfaces_Table
;
931 if Iface_Table
/= null then
932 for Id
in 1 .. Iface_Table
.Nb_Ifaces
loop
933 if Iface_Table
.Ifaces_Table
(Id
).Iface_Tag
= Iface
then
934 return Iface_Table
.Ifaces_Table
(Id
).Secondary_DT
;
939 -- If the object does not implement the interface we must raise CE
941 raise Constraint_Error
with "invalid interface conversion";
944 ---------------------
945 -- Set_Entry_Index --
946 ---------------------
948 procedure Set_Entry_Index
954 SSD
(T
).SSD_Table
(Position
).Index
:= Value
;
957 -----------------------
958 -- Set_Offset_To_Top --
959 -----------------------
961 procedure Set_Dynamic_Offset_To_Top
962 (This
: System
.Address
;
964 Offset_Value
: SSE
.Storage_Offset
;
965 Offset_Func
: Offset_To_Top_Function_Ptr
)
967 Sec_Base
: System
.Address
;
968 Sec_DT
: Dispatch_Table_Ptr
;
971 -- Save the offset to top field in the secondary dispatch table
973 if Offset_Value
/= 0 then
974 Sec_Base
:= This
+ Offset_Value
;
975 Sec_DT
:= DT
(To_Tag_Ptr
(Sec_Base
).all);
976 Sec_DT
.Offset_To_Top
:= SSE
.Storage_Offset
'Last;
979 Register_Interface_Offset
980 (This
, Interface_T
, False, Offset_Value
, Offset_Func
);
981 end Set_Dynamic_Offset_To_Top
;
983 ----------------------
984 -- Set_Prim_Op_Kind --
985 ----------------------
987 procedure Set_Prim_Op_Kind
990 Value
: Prim_Op_Kind
)
993 SSD
(T
).SSD_Table
(Position
).Kind
:= Value
;
994 end Set_Prim_Op_Kind
;
996 ----------------------
997 -- Type_Is_Abstract --
998 ----------------------
1000 function Type_Is_Abstract
(T
: Tag
) return Boolean is
1002 TSD
: Type_Specific_Data_Ptr
;
1009 TSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
1010 TSD
:= To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
1011 return TSD
.Type_Is_Abstract
;
1012 end Type_Is_Abstract
;
1014 --------------------
1015 -- Unregister_Tag --
1016 --------------------
1018 procedure Unregister_Tag
(T
: Tag
) is
1020 External_Tag_HTable
.Remove
(Get_External_Tag
(T
));
1023 ------------------------
1024 -- Wide_Expanded_Name --
1025 ------------------------
1027 WC_Encoding
: Character;
1028 pragma Import
(C
, WC_Encoding
, "__gl_wc_encoding");
1029 -- Encoding method for source, as exported by binder
1031 function Wide_Expanded_Name
(T
: Tag
) return Wide_String is
1032 S
: constant String := Expanded_Name
(T
);
1033 W
: Wide_String (1 .. S
'Length);
1036 String_To_Wide_String
1037 (S
, W
, L
, Get_WC_Encoding_Method
(WC_Encoding
));
1039 end Wide_Expanded_Name
;
1041 -----------------------------
1042 -- Wide_Wide_Expanded_Name --
1043 -----------------------------
1045 function Wide_Wide_Expanded_Name
(T
: Tag
) return Wide_Wide_String
is
1046 S
: constant String := Expanded_Name
(T
);
1047 W
: Wide_Wide_String
(1 .. S
'Length);
1050 String_To_Wide_Wide_String
1051 (S
, W
, L
, Get_WC_Encoding_Method
(WC_Encoding
));
1053 end Wide_Wide_Expanded_Name
;