1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
9 -- Copyright (C) 1992-2007, 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 ------------------------------------------------------------------------------
35 with Ada
.Unchecked_Conversion
;
37 with System
.Storage_Elements
; use System
.Storage_Elements
;
38 with System
.WCh_Con
; use System
.WCh_Con
;
39 with System
.WCh_StW
; use System
.WCh_StW
;
41 pragma Elaborate_All
(System
.HTable
);
43 package body Ada
.Tags
is
45 -----------------------
46 -- Local Subprograms --
47 -----------------------
49 function CW_Membership
(Obj_Tag
: Tag
; Typ_Tag
: Tag
) return Boolean;
50 -- Given the tag of an object and the tag associated to a type, return
51 -- true if Obj is in Typ'Class.
53 function Get_External_Tag
(T
: Tag
) return System
.Address
;
54 -- Returns address of a null terminated string containing the external name
56 function Is_Primary_DT
(T
: Tag
) return Boolean;
57 -- Given a tag returns True if it has the signature of a primary dispatch
58 -- table. This is Inline_Always since it is called from other Inline_
59 -- Always subprograms where we want no out of line code to be generated.
61 function Length
(Str
: Cstring_Ptr
) return Natural;
62 -- Length of string represented by the given pointer (treating the string
63 -- as a C-style string, which is Nul terminated).
65 function OSD
(T
: Tag
) return Object_Specific_Data_Ptr
;
66 -- Ada 2005 (AI-251): Given a pointer T to a secondary dispatch table,
67 -- retrieve the address of the record containing the Object Specific
70 function SSD
(T
: Tag
) return Select_Specific_Data_Ptr
;
71 -- Ada 2005 (AI-251): Given a pointer T to a dispatch Table, retrieves the
72 -- address of the record containing the Select Specific Data in T's TSD.
74 pragma Inline_Always
(CW_Membership
);
75 pragma Inline_Always
(Get_External_Tag
);
76 pragma Inline_Always
(Is_Primary_DT
);
77 pragma Inline_Always
(OSD
);
78 pragma Inline_Always
(SSD
);
80 -- Unchecked conversions
82 function To_Address
is
83 new Unchecked_Conversion
(Cstring_Ptr
, System
.Address
);
85 function To_Cstring_Ptr
is
86 new Unchecked_Conversion
(System
.Address
, Cstring_Ptr
);
88 -- Disable warnings on possible aliasing problem
91 new Unchecked_Conversion
(Integer_Address
, Tag
);
93 function To_Addr_Ptr
is
94 new Ada
.Unchecked_Conversion
(System
.Address
, Addr_Ptr
);
96 function To_Address
is
97 new Ada
.Unchecked_Conversion
(Tag
, System
.Address
);
99 function To_Dispatch_Table_Ptr
is
100 new Ada
.Unchecked_Conversion
(Tag
, Dispatch_Table_Ptr
);
102 function To_Dispatch_Table_Ptr
is
103 new Ada
.Unchecked_Conversion
(System
.Address
, Dispatch_Table_Ptr
);
105 function To_Object_Specific_Data_Ptr
is
106 new Ada
.Unchecked_Conversion
(System
.Address
, Object_Specific_Data_Ptr
);
108 function To_Predef_Prims_Table_Ptr
is
109 new Ada
.Unchecked_Conversion
(System
.Address
, Predef_Prims_Table_Ptr
);
111 function To_Tag_Ptr
is
112 new Ada
.Unchecked_Conversion
(System
.Address
, Tag_Ptr
);
114 function To_Type_Specific_Data_Ptr
is
115 new Ada
.Unchecked_Conversion
(System
.Address
, Type_Specific_Data_Ptr
);
117 ------------------------------------------------
118 -- Unchecked Conversions for other components --
119 ------------------------------------------------
122 is access function (A
: System
.Address
) return Long_Long_Integer;
124 function To_Acc_Size
is new Unchecked_Conversion
(System
.Address
, Acc_Size
);
125 -- The profile of the implicitly defined _size primitive
127 -------------------------------
128 -- Inline_Always Subprograms --
129 -------------------------------
131 -- Inline_always subprograms must be placed before their first call to
132 -- avoid defeating the frontend inlining mechanism and thus ensure the
133 -- generation of their correct debug info.
139 -- Canonical implementation of Classwide Membership corresponding to:
143 -- Each dispatch table contains a reference to a table of ancestors (stored
144 -- in the first part of the Tags_Table) and a count of the level of
145 -- inheritance "Idepth".
147 -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
148 -- contained in the dispatch table referenced by Obj'Tag . Knowing the
149 -- level of inheritance of both types, this can be computed in constant
150 -- time by the formula:
152 -- TSD (Obj'tag).Tags_Table (TSD (Obj'tag).Idepth - TSD (Typ'tag).Idepth)
155 function CW_Membership
(Obj_Tag
: Tag
; Typ_Tag
: Tag
) return Boolean is
156 Obj_TSD_Ptr
: constant Addr_Ptr
:=
157 To_Addr_Ptr
(To_Address
(Obj_Tag
) - DT_Typeinfo_Ptr_Size
);
158 Typ_TSD_Ptr
: constant Addr_Ptr
:=
159 To_Addr_Ptr
(To_Address
(Typ_Tag
) - DT_Typeinfo_Ptr_Size
);
160 Obj_TSD
: constant Type_Specific_Data_Ptr
:=
161 To_Type_Specific_Data_Ptr
(Obj_TSD_Ptr
.all);
162 Typ_TSD
: constant Type_Specific_Data_Ptr
:=
163 To_Type_Specific_Data_Ptr
(Typ_TSD_Ptr
.all);
164 Pos
: constant Integer := Obj_TSD
.Idepth
- Typ_TSD
.Idepth
;
166 return Pos
>= 0 and then Obj_TSD
.Tags_Table
(Pos
) = Typ_Tag
;
169 ----------------------
170 -- Get_External_Tag --
171 ----------------------
173 function Get_External_Tag
(T
: Tag
) return System
.Address
is
174 TSD_Ptr
: constant Addr_Ptr
:=
175 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
176 TSD
: constant Type_Specific_Data_Ptr
:=
177 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
179 return To_Address
(TSD
.External_Tag
);
180 end Get_External_Tag
;
186 function Is_Primary_DT
(T
: Tag
) return Boolean is
188 return DT
(T
).Signature
= Primary_DT
;
195 function OSD
(T
: Tag
) return Object_Specific_Data_Ptr
is
196 OSD_Ptr
: constant Addr_Ptr
:=
197 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
199 return To_Object_Specific_Data_Ptr
(OSD_Ptr
.all);
206 function SSD
(T
: Tag
) return Select_Specific_Data_Ptr
is
207 TSD_Ptr
: constant Addr_Ptr
:=
208 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
209 TSD
: constant Type_Specific_Data_Ptr
:=
210 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
215 -------------------------
216 -- External_Tag_HTable --
217 -------------------------
219 type HTable_Headers
is range 1 .. 64;
221 -- The following internal package defines the routines used for the
222 -- instantiation of a new System.HTable.Static_HTable (see below). See
223 -- spec in g-htable.ads for details of usage.
225 package HTable_Subprograms
is
226 procedure Set_HT_Link
(T
: Tag
; Next
: Tag
);
227 function Get_HT_Link
(T
: Tag
) return Tag
;
228 function Hash
(F
: System
.Address
) return HTable_Headers
;
229 function Equal
(A
, B
: System
.Address
) return Boolean;
230 end HTable_Subprograms
;
232 package External_Tag_HTable
is new System
.HTable
.Static_HTable
(
233 Header_Num
=> HTable_Headers
,
234 Element
=> Dispatch_Table
,
237 Set_Next
=> HTable_Subprograms
.Set_HT_Link
,
238 Next
=> HTable_Subprograms
.Get_HT_Link
,
239 Key
=> System
.Address
,
240 Get_Key
=> Get_External_Tag
,
241 Hash
=> HTable_Subprograms
.Hash
,
242 Equal
=> HTable_Subprograms
.Equal
);
244 ------------------------
245 -- HTable_Subprograms --
246 ------------------------
248 -- Bodies of routines for hash table instantiation
250 package body HTable_Subprograms
is
256 function Equal
(A
, B
: System
.Address
) return Boolean is
257 Str1
: constant Cstring_Ptr
:= To_Cstring_Ptr
(A
);
258 Str2
: constant Cstring_Ptr
:= To_Cstring_Ptr
(B
);
262 if Str1
(J
) /= Str2
(J
) then
264 elsif Str1
(J
) = ASCII
.NUL
then
276 function Get_HT_Link
(T
: Tag
) return Tag
is
277 TSD_Ptr
: constant Addr_Ptr
:=
278 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
279 TSD
: constant Type_Specific_Data_Ptr
:=
280 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
282 return TSD
.HT_Link
.all;
289 function Hash
(F
: System
.Address
) return HTable_Headers
is
290 function H
is new System
.HTable
.Hash
(HTable_Headers
);
291 Str
: constant Cstring_Ptr
:= To_Cstring_Ptr
(F
);
292 Res
: constant HTable_Headers
:= H
(Str
(1 .. Length
(Str
)));
301 procedure Set_HT_Link
(T
: Tag
; Next
: Tag
) is
302 TSD_Ptr
: constant Addr_Ptr
:=
303 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
304 TSD
: constant Type_Specific_Data_Ptr
:=
305 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
307 TSD
.HT_Link
.all := Next
;
310 end HTable_Subprograms
;
316 function Base_Address
(This
: System
.Address
) return System
.Address
is
318 return This
- Offset_To_Top
(This
);
326 (This
: System
.Address
;
327 T
: Tag
) return System
.Address
329 Iface_Table
: Interface_Data_Ptr
;
330 Obj_Base
: System
.Address
;
331 Obj_DT
: Dispatch_Table_Ptr
;
335 if System
."=" (This
, System
.Null_Address
) then
336 return System
.Null_Address
;
339 Obj_Base
:= Base_Address
(This
);
340 Obj_DT_Tag
:= To_Tag_Ptr
(Obj_Base
).all;
341 Obj_DT
:= DT
(To_Tag_Ptr
(Obj_Base
).all);
342 Iface_Table
:= To_Type_Specific_Data_Ptr
(Obj_DT
.TSD
).Interfaces_Table
;
344 if Iface_Table
/= null then
345 for Id
in 1 .. Iface_Table
.Nb_Ifaces
loop
346 if Iface_Table
.Ifaces_Table
(Id
).Iface_Tag
= T
then
348 -- Case of Static value of Offset_To_Top
350 if Iface_Table
.Ifaces_Table
(Id
).Static_Offset_To_Top
then
351 Obj_Base
:= Obj_Base
+
352 Iface_Table
.Ifaces_Table
(Id
).Offset_To_Top_Value
;
354 -- Otherwise call the function generated by the expander to
355 -- provide the value.
358 Obj_Base
:= Obj_Base
+
359 Iface_Table
.Ifaces_Table
(Id
).Offset_To_Top_Func
.all
368 -- Check if T is an immediate ancestor. This is required to handle
369 -- conversion of class-wide interfaces to tagged types.
371 if CW_Membership
(Obj_DT_Tag
, T
) then
375 -- If the object does not implement the interface we must raise CE
377 raise Constraint_Error
with "invalid interface conversion";
384 function DT
(T
: Tag
) return Dispatch_Table_Ptr
is
385 Offset
: constant SSE
.Storage_Offset
:=
386 To_Dispatch_Table_Ptr
(T
).Prims_Ptr
'Position;
388 return To_Dispatch_Table_Ptr
(To_Address
(T
) - Offset
);
395 -- Canonical implementation of Classwide Membership corresponding to:
397 -- Obj in Iface'Class
399 -- Each dispatch table contains a table with the tags of all the
400 -- implemented interfaces.
402 -- Obj is in Iface'Class if Iface'Tag is found in the table of interfaces
403 -- that are contained in the dispatch table referenced by Obj'Tag.
405 function IW_Membership
(This
: System
.Address
; T
: Tag
) return Boolean is
406 Iface_Table
: Interface_Data_Ptr
;
407 Obj_Base
: System
.Address
;
408 Obj_DT
: Dispatch_Table_Ptr
;
409 Obj_TSD
: Type_Specific_Data_Ptr
;
412 Obj_Base
:= Base_Address
(This
);
413 Obj_DT
:= DT
(To_Tag_Ptr
(Obj_Base
).all);
414 Obj_TSD
:= To_Type_Specific_Data_Ptr
(Obj_DT
.TSD
);
415 Iface_Table
:= Obj_TSD
.Interfaces_Table
;
417 if Iface_Table
/= null then
418 for Id
in 1 .. Iface_Table
.Nb_Ifaces
loop
419 if Iface_Table
.Ifaces_Table
(Id
).Iface_Tag
= T
then
425 -- Look for the tag in the ancestor tags table. This is required for:
426 -- Iface_CW in Typ'Class
428 for Id
in 0 .. Obj_TSD
.Idepth
loop
429 if Obj_TSD
.Tags_Table
(Id
) = T
then
441 function Descendant_Tag
(External
: String; Ancestor
: Tag
) return Tag
is
442 Int_Tag
: constant Tag
:= Internal_Tag
(External
);
445 if not Is_Descendant_At_Same_Level
(Int_Tag
, Ancestor
) then
456 function Expanded_Name
(T
: Tag
) return String is
457 Result
: Cstring_Ptr
;
459 TSD
: Type_Specific_Data_Ptr
;
466 TSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
467 TSD
:= To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
468 Result
:= TSD
.Expanded_Name
;
469 return Result
(1 .. Length
(Result
));
476 function External_Tag
(T
: Tag
) return String is
477 Result
: Cstring_Ptr
;
479 TSD
: Type_Specific_Data_Ptr
;
486 TSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
487 TSD
:= To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
488 Result
:= TSD
.External_Tag
;
489 return Result
(1 .. Length
(Result
));
492 ---------------------
493 -- Get_Entry_Index --
494 ---------------------
496 function Get_Entry_Index
(T
: Tag
; Position
: Positive) return Positive is
498 return SSD
(T
).SSD_Table
(Position
).Index
;
501 ----------------------
502 -- Get_Prim_Op_Kind --
503 ----------------------
505 function Get_Prim_Op_Kind
507 Position
: Positive) return Prim_Op_Kind
510 return SSD
(T
).SSD_Table
(Position
).Kind
;
511 end Get_Prim_Op_Kind
;
513 ----------------------
514 -- Get_Offset_Index --
515 ----------------------
517 function Get_Offset_Index
519 Position
: Positive) return Positive
522 if Is_Primary_DT
(T
) then
525 return OSD
(T
).OSD_Table
(Position
);
527 end Get_Offset_Index
;
533 function Get_RC_Offset
(T
: Tag
) return SSE
.Storage_Offset
is
534 TSD_Ptr
: constant Addr_Ptr
:=
535 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
536 TSD
: constant Type_Specific_Data_Ptr
:=
537 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
539 return TSD
.RC_Offset
;
542 ---------------------
543 -- Get_Tagged_Kind --
544 ---------------------
546 function Get_Tagged_Kind
(T
: Tag
) return Tagged_Kind
is
548 return DT
(T
).Tag_Kind
;
551 -----------------------------
552 -- Interface_Ancestor_Tags --
553 -----------------------------
555 function Interface_Ancestor_Tags
(T
: Tag
) return Tag_Array
is
556 TSD_Ptr
: constant Addr_Ptr
:=
557 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
558 TSD
: constant Type_Specific_Data_Ptr
:=
559 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
560 Iface_Table
: constant Interface_Data_Ptr
:= TSD
.Interfaces_Table
;
563 if Iface_Table
= null then
565 Table
: Tag_Array
(1 .. 0);
571 Table
: Tag_Array
(1 .. Iface_Table
.Nb_Ifaces
);
573 for J
in 1 .. Iface_Table
.Nb_Ifaces
loop
574 Table
(J
) := Iface_Table
.Ifaces_Table
(J
).Iface_Tag
;
580 end Interface_Ancestor_Tags
;
586 -- Internal tags have the following format:
587 -- "Internal tag at 16#ADDRESS#: <full-name-of-tagged-type>"
589 Internal_Tag_Header
: constant String := "Internal tag at ";
590 Header_Separator
: constant Character := '#';
592 function Internal_Tag
(External
: String) return Tag
is
593 Ext_Copy
: aliased String (External
'First .. External
'Last + 1);
597 -- Handle locally defined tagged types
599 if External
'Length > Internal_Tag_Header
'Length
601 External
(External
'First ..
602 External
'First + Internal_Tag_Header
'Length - 1)
603 = Internal_Tag_Header
606 Addr_First
: constant Natural :=
607 External
'First + Internal_Tag_Header
'Length;
609 Addr
: Integer_Address
;
612 -- Search the second separator (#) to identify the address
614 Addr_Last
:= Addr_First
;
617 while Addr_Last
<= External
'Last
618 and then External
(Addr_Last
) /= Header_Separator
620 Addr_Last
:= Addr_Last
+ 1;
623 -- Skip the first separator
626 Addr_Last
:= Addr_Last
+ 1;
630 if Addr_Last
<= External
'Last then
632 -- Protect the run-time against wrong internal tags. We
633 -- cannot use exception handlers here because it would
634 -- disable the use of this run-time compiling with
635 -- restriction No_Exception_Handler.
639 Wrong_Tag
: Boolean := False;
642 if External
(Addr_First
) /= '1'
643 or else External
(Addr_First
+ 1) /= '6'
644 or else External
(Addr_First
+ 2) /= '#'
649 for J
in Addr_First
+ 3 .. Addr_Last
- 1 loop
652 if not (C
in '0' .. '9')
653 and then not (C
in 'A' .. 'F')
654 and then not (C
in 'a' .. 'f')
662 -- Convert the numeric value into a tag
664 if not Wrong_Tag
then
665 Addr
:= Integer_Address
'Value
666 (External
(Addr_First
.. Addr_Last
));
668 -- Internal tags never have value 0
671 return To_Tag
(Addr
);
678 -- Handle library-level tagged types
681 -- Make NUL-terminated copy of external tag string
683 Ext_Copy
(External
'Range) := External
;
684 Ext_Copy
(Ext_Copy
'Last) := ASCII
.NUL
;
685 Res
:= External_Tag_HTable
.Get
(Ext_Copy
'Address);
690 Msg1
: constant String := "unknown tagged type: ";
691 Msg2
: String (1 .. Msg1
'Length + External
'Length);
694 Msg2
(1 .. Msg1
'Length) := Msg1
;
695 Msg2
(Msg1
'Length + 1 .. Msg1
'Length + External
'Length) :=
697 Ada
.Exceptions
.Raise_Exception
(Tag_Error
'Identity, Msg2
);
704 ---------------------------------
705 -- Is_Descendant_At_Same_Level --
706 ---------------------------------
708 function Is_Descendant_At_Same_Level
710 Ancestor
: Tag
) return Boolean
712 D_TSD_Ptr
: constant Addr_Ptr
:=
713 To_Addr_Ptr
(To_Address
(Descendant
)
714 - DT_Typeinfo_Ptr_Size
);
715 A_TSD_Ptr
: constant Addr_Ptr
:=
716 To_Addr_Ptr
(To_Address
(Ancestor
) - DT_Typeinfo_Ptr_Size
);
717 D_TSD
: constant Type_Specific_Data_Ptr
:=
718 To_Type_Specific_Data_Ptr
(D_TSD_Ptr
.all);
719 A_TSD
: constant Type_Specific_Data_Ptr
:=
720 To_Type_Specific_Data_Ptr
(A_TSD_Ptr
.all);
723 return CW_Membership
(Descendant
, Ancestor
)
724 and then D_TSD
.Access_Level
= A_TSD
.Access_Level
;
725 end Is_Descendant_At_Same_Level
;
731 function Length
(Str
: Cstring_Ptr
) return Natural is
736 while Str
(Len
) /= ASCII
.Nul
loop
747 function Offset_To_Top
748 (This
: System
.Address
) return SSE
.Storage_Offset
750 Tag_Size
: constant SSE
.Storage_Count
:=
751 SSE
.Storage_Count
(1 * (Standard
'Address_Size / System
.Storage_Unit
));
753 type Storage_Offset_Ptr
is access SSE
.Storage_Offset
;
754 function To_Storage_Offset_Ptr
is
755 new Unchecked_Conversion
(System
.Address
, Storage_Offset_Ptr
);
757 Curr_DT
: Dispatch_Table_Ptr
;
760 Curr_DT
:= DT
(To_Tag_Ptr
(This
).all);
762 if Curr_DT
.Offset_To_Top
= SSE
.Storage_Offset
'Last then
763 return To_Storage_Offset_Ptr
(This
+ Tag_Size
).all;
765 return Curr_DT
.Offset_To_Top
;
774 (Obj
: System
.Address
;
775 T
: Tag
) return SSE
.Storage_Count
777 Parent_Slot
: constant Positive := 1;
778 -- The tag of the parent is always in the first slot of the table of
781 Size_Slot
: constant Positive := 1;
782 -- The pointer to the _size primitive is always in the first slot of
783 -- the dispatch table.
785 TSD_Ptr
: constant Addr_Ptr
:=
786 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
787 TSD
: constant Type_Specific_Data_Ptr
:=
788 To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
789 -- Pointer to the TSD
791 Parent_Tag
: constant Tag
:= TSD
.Tags_Table
(Parent_Slot
);
792 Parent_Predef_Prims_Ptr
: constant Addr_Ptr
:=
793 To_Addr_Ptr
(To_Address
(Parent_Tag
)
794 - DT_Predef_Prims_Offset
);
795 Parent_Predef_Prims
: constant Predef_Prims_Table_Ptr
:=
796 To_Predef_Prims_Table_Ptr
797 (Parent_Predef_Prims_Ptr
.all);
799 -- The tag of the parent type through the dispatch table and its
800 -- Predef_Prims field.
802 F
: constant Acc_Size
:=
803 To_Acc_Size
(Parent_Predef_Prims
(Size_Slot
));
804 -- Access to the _size primitive of the parent
807 -- Here we compute the size of the _parent field of the object
809 return SSE
.Storage_Count
(F
.all (Obj
));
816 function Parent_Tag
(T
: Tag
) return Tag
is
818 TSD
: Type_Specific_Data_Ptr
;
825 TSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
826 TSD
:= To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);
828 -- The Parent_Tag of a root-level tagged type is defined to be No_Tag.
829 -- The first entry in the Ancestors_Tags array will be null for such
830 -- a type, but it's better to be explicit about returning No_Tag in
833 if TSD
.Idepth
= 0 then
836 return TSD
.Tags_Table
(1);
844 procedure Register_Tag
(T
: Tag
) is
846 External_Tag_HTable
.Set
(T
);
849 ---------------------
850 -- Set_Entry_Index --
851 ---------------------
853 procedure Set_Entry_Index
859 SSD
(T
).SSD_Table
(Position
).Index
:= Value
;
862 -----------------------
863 -- Set_Offset_To_Top --
864 -----------------------
866 procedure Set_Offset_To_Top
867 (This
: System
.Address
;
870 Offset_Value
: SSE
.Storage_Offset
;
871 Offset_Func
: Offset_To_Top_Function_Ptr
)
873 Prim_DT
: Dispatch_Table_Ptr
;
874 Sec_Base
: System
.Address
;
875 Sec_DT
: Dispatch_Table_Ptr
;
876 Iface_Table
: Interface_Data_Ptr
;
879 -- Save the offset to top field in the secondary dispatch table
881 if Offset_Value
/= 0 then
882 Sec_Base
:= This
+ Offset_Value
;
883 Sec_DT
:= DT
(To_Tag_Ptr
(Sec_Base
).all);
886 Sec_DT
.Offset_To_Top
:= Offset_Value
;
888 Sec_DT
.Offset_To_Top
:= SSE
.Storage_Offset
'Last;
892 -- "This" points to the primary DT and we must save Offset_Value in
893 -- the Offset_To_Top field of the corresponding secondary dispatch
896 Prim_DT
:= DT
(To_Tag_Ptr
(This
).all);
897 Iface_Table
:= To_Type_Specific_Data_Ptr
(Prim_DT
.TSD
).Interfaces_Table
;
899 -- Save Offset_Value in the table of interfaces of the primary DT.
900 -- This data will be used by the subprogram "Displace" to give support
901 -- to backward abstract interface type conversions.
903 -- Register the offset in the table of interfaces
905 if Iface_Table
/= null then
906 for Id
in 1 .. Iface_Table
.Nb_Ifaces
loop
907 if Iface_Table
.Ifaces_Table
(Id
).Iface_Tag
= Interface_T
then
908 Iface_Table
.Ifaces_Table
(Id
).Static_Offset_To_Top
:=
912 Iface_Table
.Ifaces_Table
(Id
).Offset_To_Top_Value
915 Iface_Table
.Ifaces_Table
(Id
).Offset_To_Top_Func
924 -- If we arrive here there is some error in the run-time data structure
927 end Set_Offset_To_Top
;
929 ----------------------
930 -- Set_Prim_Op_Kind --
931 ----------------------
933 procedure Set_Prim_Op_Kind
936 Value
: Prim_Op_Kind
)
939 SSD
(T
).SSD_Table
(Position
).Kind
:= Value
;
940 end Set_Prim_Op_Kind
;
942 ------------------------
943 -- Wide_Expanded_Name --
944 ------------------------
946 WC_Encoding
: Character;
947 pragma Import
(C
, WC_Encoding
, "__gl_wc_encoding");
948 -- Encoding method for source, as exported by binder
950 function Wide_Expanded_Name
(T
: Tag
) return Wide_String is
952 return String_To_Wide_String
953 (Expanded_Name
(T
), Get_WC_Encoding_Method
(WC_Encoding
));
954 end Wide_Expanded_Name
;
956 -----------------------------
957 -- Wide_Wide_Expanded_Name --
958 -----------------------------
960 function Wide_Wide_Expanded_Name
(T
: Tag
) return Wide_Wide_String
is
962 return String_To_Wide_Wide_String
963 (Expanded_Name
(T
), Get_WC_Encoding_Method
(WC_Encoding
));
964 end Wide_Wide_Expanded_Name
;