1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
9 -- Copyright (C) 1992-2005, 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 ------------------------------------------------------------------------------
36 with System
.Storage_Elements
; use System
.Storage_Elements
;
38 pragma Elaborate_All
(System
.HTable
);
40 package body Ada
.Tags
is
42 -- Structure of the GNAT Primary Dispatch Table
44 -- +-----------------------+
46 -- +-----------------------+
48 -- +-----------------------+
49 -- | Typeinfo_Ptr/TSD_Ptr | ---> Type Specific Data
50 -- Tag ---> +-----------------------+ +-------------------+
51 -- | table of | | inheritance depth |
52 -- : primitive ops : +-------------------+
53 -- | pointers | | access level |
54 -- +-----------------------+ +-------------------+
56 -- +-------------------+
58 -- +-------------------+
59 -- | hash table link |
60 -- +-------------------+
61 -- | remotely callable |
62 -- +-------------------+
63 -- | rec ctrler offset |
64 -- +-------------------+
66 -- +-------------------+
68 -- +-------------------+
69 -- Select Specific Data <--- | SSD_Ptr |
70 -- +-----------------------+ +-------------------+
71 -- | table of primitive | | table of |
72 -- : operation : : ancestor :
74 -- +-----------------------+ +-------------------+
75 -- | table of | | table of |
76 -- : entry : : interface :
77 -- | indices | | tags |
78 -- +-----------------------+ +-------------------+
80 -- Structure of the GNAT Secondary Dispatch Table
82 -- +-----------------------+
84 -- +-----------------------+
86 -- +-----------------------+
87 -- | OSD_Ptr |---> Object Specific Data
88 -- Tag ---> +-----------------------+ +---------------+
89 -- | table of | | num prim ops |
90 -- : primitive op : +---------------+
91 -- | thunk pointers | | table of |
92 -- +-----------------------+ + primitive |
96 Offset_To_Signature
: constant SSE
.Storage_Count
:=
98 + DT_Offset_To_Top_Size
101 subtype Cstring
is String (Positive);
102 type Cstring_Ptr
is access all Cstring
;
104 -- We suppress index checks because the declared size in the record below
105 -- is a dummy size of one (see below).
107 type Tag_Table
is array (Natural range <>) of Tag
;
108 pragma Suppress_Initialization
(Tag_Table
);
109 pragma Suppress
(Index_Check
, On
=> Tag_Table
);
111 -- Object specific data types
113 type Object_Specific_Data_Array
is array (Positive range <>) of Positive;
115 type Object_Specific_Data
(Nb_Prim
: Positive) is record
116 Num_Prim_Ops
: Natural;
117 -- Number of primitive operations of the dispatch table. This field is
118 -- used by the run-time check routines that are activated when the
119 -- run-time is compiled with assertions enabled.
121 OSD_Table
: Object_Specific_Data_Array
(1 .. Nb_Prim
);
122 -- Table used in secondary DT to reference their counterpart in the
123 -- select specific data (in the TSD of the primary DT). This construct
124 -- is used in the handling of dispatching triggers in select statements.
125 -- Nb_Prim is the number of non-predefined primitive operations.
128 -- Select specific data types
130 type Select_Specific_Data_Element
is record
135 type Select_Specific_Data_Array
is
136 array (Positive range <>) of Select_Specific_Data_Element
;
138 type Select_Specific_Data
(Nb_Prim
: Positive) is record
139 SSD_Table
: Select_Specific_Data_Array
(1 .. Nb_Prim
);
140 -- NOTE: Nb_Prim is the number of non-predefined primitive operations
143 -- Type specific data types
145 type Type_Specific_Data
is record
147 -- Inheritance Depth Level: Used to implement the membership test
148 -- associated with single inheritance of tagged types in constant-time.
149 -- In addition it also indicates the size of the first table stored in
150 -- the Tags_Table component (see comment below).
152 Access_Level
: Natural;
153 -- Accessibility level required to give support to Ada 2005 nested type
154 -- extensions. This feature allows safe nested type extensions by
155 -- shifting the accessibility checks to certain operations, rather than
156 -- being enforced at the type declaration. In particular, by performing
157 -- run-time accessibility checks on class-wide allocators, class-wide
158 -- function return, and class-wide stream I/O, the danger of objects
159 -- outliving their type declaration can be eliminated (Ada 2005: AI-344)
161 Expanded_Name
: Cstring_Ptr
;
162 External_Tag
: Cstring_Ptr
;
164 -- Components used to give support to the Ada.Tags subprograms described
167 Remotely_Callable
: Boolean;
168 -- Used to check ARM E.4 (18)
170 RC_Offset
: SSE
.Storage_Offset
;
171 -- Controller Offset: Used to give support to tagged controlled objects
172 -- (see Get_Deep_Controller at s-finimp)
174 Num_Prim_Ops
: Natural;
175 -- Number of primitive operations of the dispatch table. This field is
176 -- used for additional run-time checks when the run-time is compiled
177 -- with assertions enabled.
179 Num_Interfaces
: Natural;
180 -- Number of abstract interface types implemented by the tagged type.
181 -- The value Idepth+Num_Interfaces indicates the end of the second table
182 -- stored in the Tags_Table component. It is used to implement the
183 -- membership test associated with interfaces (Ada 2005:AI-251).
185 SSD_Ptr
: System
.Address
;
186 -- Pointer to a table of records used in dispatching selects. This
187 -- field has a meaningful value for all tagged types that implement
188 -- a limited, protected, synchronized or task interfaces and have
189 -- non-predefined primitive operations.
191 Tags_Table
: Tag_Table
(0 .. 1);
192 -- The size of the Tags_Table array actually depends on the tagged type
193 -- to which it applies. The compiler ensures that has enough space to
194 -- store all the entries of the two tables phisically stored there: the
195 -- "table of ancestor tags" and the "table of interface tags". For this
196 -- purpose we are using the same mechanism as for the Prims_Ptr array in
197 -- the Dispatch_Table record. See comments below on Prims_Ptr for
201 type Dispatch_Table
is record
203 -- According to the C++ ABI the components Offset_To_Top and
204 -- Typeinfo_Ptr are stored just "before" the dispatch table (that is,
205 -- the Prims_Ptr table), and they are referenced with negative offsets
206 -- referring to the base of the dispatch table. The _Tag (or the
207 -- VTable_Ptr in C++ terminology) must point to the base of the virtual
208 -- table, just after these components, to point to the Prims_Ptr table.
209 -- For this purpose the expander generates a Prims_Ptr table that has
210 -- enough space for these additional components, and generates code that
211 -- displaces the _Tag to point after these components.
213 -- Offset_To_Top : Natural;
214 -- Typeinfo_Ptr : System.Address;
216 Prims_Ptr
: Address_Array
(1 .. 1);
217 -- The size of the Prims_Ptr array actually depends on the tagged type
218 -- to which it applies. For each tagged type, the expander computes the
219 -- actual array size, allocates the Dispatch_Table record accordingly,
220 -- and generates code that displaces the base of the record after the
221 -- Typeinfo_Ptr component. For this reason the first two components have
222 -- been commented in the previous declaration. The access to these
223 -- components is done by means of local functions.
225 -- To avoid the use of discriminants to define the actual size of the
226 -- dispatch table, we used to declare the tag as a pointer to a record
227 -- that contains an arbitrary array of addresses, using Positive as its
228 -- index. This ensures that there are never range checks when accessing
229 -- the dispatch table, but it prevents GDB from displaying tagged types
230 -- properly. A better approach is to declare this record type as holding
231 -- small number of addresses, and to explicitly suppress checks on it.
233 -- Note that in both cases, this type is never allocated, and serves
234 -- only to declare the corresponding access type.
237 -- Run-time check types and subprograms: These subprograms are used only
238 -- when the run-time is compiled with assertions enabled.
240 type Signature_Type
is
242 Must_Be_Secondary_DT
,
243 Must_Be_Primary_Or_Secondary_DT
,
245 Must_Be_Primary_Or_Interface
);
246 -- Type of signature accepted by primitives in this package that are called
247 -- during the elaboration of tagged types. This type is used by the routine
248 -- Check_Signature that is called only when the run-time is compiled with
249 -- assertions enabled.
251 ---------------------------------------------
252 -- Unchecked Conversions for String Fields --
253 ---------------------------------------------
255 function To_Address
is
256 new Unchecked_Conversion
(Cstring_Ptr
, System
.Address
);
258 function To_Cstring_Ptr
is
259 new Unchecked_Conversion
(System
.Address
, Cstring_Ptr
);
261 ------------------------------------------------
262 -- Unchecked Conversions for other components --
263 ------------------------------------------------
266 is access function (A
: System
.Address
) return Long_Long_Integer;
268 function To_Acc_Size
is new Unchecked_Conversion
(System
.Address
, Acc_Size
);
269 -- The profile of the implicitly defined _size primitive
271 type Storage_Offset_Ptr
is access System
.Storage_Elements
.Storage_Offset
;
273 function To_Storage_Offset_Ptr
is
274 new Unchecked_Conversion
(System
.Address
, Storage_Offset_Ptr
);
276 -----------------------
277 -- Local Subprograms --
278 -----------------------
282 Index
: Natural) return Boolean;
283 -- Check that Index references a valid entry of the dispatch table of T
285 function Check_Signature
(T
: Tag
; Kind
: Signature_Type
) return Boolean;
286 -- Check that the signature of T is valid and corresponds with the subset
287 -- specified by the signature Kind.
292 Entry_Count
: Natural) return Boolean;
293 -- Verify that Old_T and New_T have at least Entry_Count entries
295 function Get_Num_Prim_Ops
(T
: Tag
) return Natural;
296 -- Retrieve the number of primitive operations in the dispatch table of T
298 function Is_Primary_DT
(T
: Tag
) return Boolean;
299 pragma Inline_Always
(Is_Primary_DT
);
300 -- Given a tag returns True if it has the signature of a primary dispatch
301 -- table. This is Inline_Always since it is called from other Inline_
302 -- Always subprograms where we want no out of line code to be generated.
304 function Length
(Str
: Cstring_Ptr
) return Natural;
305 -- Length of string represented by the given pointer (treating the string
306 -- as a C-style string, which is Nul terminated).
308 function Offset_To_Top
309 (T
: Tag
) return System
.Storage_Elements
.Storage_Offset
;
310 -- Returns the current value of the offset_to_top component available in
311 -- the prologue of the dispatch table.
313 function Typeinfo_Ptr
(T
: Tag
) return System
.Address
;
314 -- Returns the current value of the typeinfo_ptr component available in
315 -- the prologue of the dispatch table.
317 pragma Unreferenced
(Typeinfo_Ptr
);
318 -- These functions will be used for full compatibility with the C++ ABI
320 -------------------------
321 -- External_Tag_HTable --
322 -------------------------
324 type HTable_Headers
is range 1 .. 64;
326 -- The following internal package defines the routines used for the
327 -- instantiation of a new System.HTable.Static_HTable (see below). See
328 -- spec in g-htable.ads for details of usage.
330 package HTable_Subprograms
is
331 procedure Set_HT_Link
(T
: Tag
; Next
: Tag
);
332 function Get_HT_Link
(T
: Tag
) return Tag
;
333 function Hash
(F
: System
.Address
) return HTable_Headers
;
334 function Equal
(A
, B
: System
.Address
) return Boolean;
335 end HTable_Subprograms
;
337 package External_Tag_HTable
is new System
.HTable
.Static_HTable
(
338 Header_Num
=> HTable_Headers
,
339 Element
=> Dispatch_Table
,
342 Set_Next
=> HTable_Subprograms
.Set_HT_Link
,
343 Next
=> HTable_Subprograms
.Get_HT_Link
,
344 Key
=> System
.Address
,
345 Get_Key
=> Get_External_Tag
,
346 Hash
=> HTable_Subprograms
.Hash
,
347 Equal
=> HTable_Subprograms
.Equal
);
349 ------------------------
350 -- HTable_Subprograms --
351 ------------------------
353 -- Bodies of routines for hash table instantiation
355 package body HTable_Subprograms
is
361 function Equal
(A
, B
: System
.Address
) return Boolean is
362 Str1
: constant Cstring_Ptr
:= To_Cstring_Ptr
(A
);
363 Str2
: constant Cstring_Ptr
:= To_Cstring_Ptr
(B
);
367 if Str1
(J
) /= Str2
(J
) then
369 elsif Str1
(J
) = ASCII
.NUL
then
381 function Get_HT_Link
(T
: Tag
) return Tag
is
383 return TSD
(T
).HT_Link
;
390 function Hash
(F
: System
.Address
) return HTable_Headers
is
391 function H
is new System
.HTable
.Hash
(HTable_Headers
);
392 Str
: constant Cstring_Ptr
:= To_Cstring_Ptr
(F
);
393 Res
: constant HTable_Headers
:= H
(Str
(1 .. Length
(Str
)));
402 procedure Set_HT_Link
(T
: Tag
; Next
: Tag
) is
404 TSD
(T
).HT_Link
:= Next
;
407 end HTable_Subprograms
;
415 Index
: Natural) return Boolean
417 Max_Entries
: constant Natural := Get_Num_Prim_Ops
(T
);
420 return Index
/= 0 and then Index
<= Max_Entries
;
423 ---------------------
424 -- Check_Signature --
425 ---------------------
427 function Check_Signature
(T
: Tag
; Kind
: Signature_Type
) return Boolean is
428 Offset_To_Top_Ptr
: constant Storage_Offset_Ptr
:=
429 To_Storage_Offset_Ptr
(To_Address
(T
)
430 - Offset_To_Signature
);
432 Signature
: constant Signature_Values
:=
433 To_Signature_Values
(Offset_To_Top_Ptr
.all);
435 Signature_Id
: Signature_Kind
;
438 if Signature
(1) /= Valid_Signature
then
439 Signature_Id
:= Unknown
;
441 elsif Signature
(2) in Primary_DT
.. Abstract_Interface
then
442 Signature_Id
:= Signature
(2);
445 Signature_Id
:= Unknown
;
450 if Kind
= Must_Be_Secondary_DT
451 or else Kind
= Must_Be_Interface
457 if Kind
= Must_Be_Primary_DT
458 or else Kind
= Must_Be_Interface
463 when Abstract_Interface
=>
464 if Kind
= Must_Be_Primary_DT
465 or else Kind
= Must_Be_Secondary_DT
466 or else Kind
= Must_Be_Primary_Or_Secondary_DT
486 Entry_Count
: Natural) return Boolean
488 Max_Entries_Old
: constant Natural := Get_Num_Prim_Ops
(Old_T
);
489 Max_Entries_New
: constant Natural := Get_Num_Prim_Ops
(New_T
);
492 return Entry_Count
<= Max_Entries_Old
493 and then Entry_Count
<= Max_Entries_New
;
500 -- Canonical implementation of Classwide Membership corresponding to:
504 -- Each dispatch table contains a reference to a table of ancestors (stored
505 -- in the first part of the Tags_Table) and a count of the level of
506 -- inheritance "Idepth".
508 -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
509 -- contained in the dispatch table referenced by Obj'Tag . Knowing the
510 -- level of inheritance of both types, this can be computed in constant
511 -- time by the formula:
513 -- Obj'tag.TSD.Ancestor_Tags (Obj'tag.TSD.Idepth - Typ'tag.TSD.Idepth)
516 function CW_Membership
(Obj_Tag
: Tag
; Typ_Tag
: Tag
) return Boolean is
519 pragma Assert
(Check_Signature
(Obj_Tag
, Must_Be_Primary_DT
));
520 pragma Assert
(Check_Signature
(Typ_Tag
, Must_Be_Primary_DT
));
521 Pos
:= TSD
(Obj_Tag
).Idepth
- TSD
(Typ_Tag
).Idepth
;
522 return Pos
>= 0 and then TSD
(Obj_Tag
).Tags_Table
(Pos
) = Typ_Tag
;
529 -- Canonical implementation of Classwide Membership corresponding to:
531 -- Obj in Iface'Class
533 -- Each dispatch table contains a table with the tags of all the
534 -- implemented interfaces.
536 -- Obj is in Iface'Class if Iface'Tag is found in the table of interfaces
537 -- that are contained in the dispatch table referenced by Obj'Tag.
539 function IW_Membership
(This
: System
.Address
; T
: Tag
) return Boolean is
540 Curr_DT
: constant Tag
:= To_Tag_Ptr
(This
).all;
543 Obj_Base
: System
.Address
;
545 Obj_TSD
: Type_Specific_Data_Ptr
;
549 (Check_Signature
(Curr_DT
, Must_Be_Primary_Or_Secondary_DT
));
551 (Check_Signature
(T
, Must_Be_Primary_Or_Interface
));
553 Obj_Base
:= This
- Offset_To_Top
(Curr_DT
);
554 Obj_DT
:= To_Tag_Ptr
(Obj_Base
).all;
557 (Check_Signature
(Curr_DT
, Must_Be_Primary_DT
));
559 Obj_TSD
:= TSD
(Obj_DT
);
560 Last_Id
:= Obj_TSD
.Idepth
+ Obj_TSD
.Num_Interfaces
;
562 if Obj_TSD
.Num_Interfaces
> 0 then
564 -- Traverse the ancestor tags table plus the interface tags table.
565 -- The former part is required for:
567 -- Iface_CW in Typ'Class
571 if Obj_TSD
.Tags_Table
(Id
) = T
then
576 exit when Id
> Last_Id
;
587 function Descendant_Tag
(External
: String; Ancestor
: Tag
) return Tag
is
591 pragma Assert
(Check_Signature
(Ancestor
, Must_Be_Primary_DT
));
592 Int_Tag
:= Internal_Tag
(External
);
593 pragma Assert
(Check_Signature
(Int_Tag
, Must_Be_Primary_DT
));
595 if not Is_Descendant_At_Same_Level
(Int_Tag
, Ancestor
) then
606 function Expanded_Name
(T
: Tag
) return String is
607 Result
: Cstring_Ptr
;
614 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Interface
));
615 Result
:= TSD
(T
).Expanded_Name
;
616 return Result
(1 .. Length
(Result
));
623 function External_Tag
(T
: Tag
) return String is
624 Result
: Cstring_Ptr
;
631 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Interface
));
632 Result
:= TSD
(T
).External_Tag
;
634 return Result
(1 .. Length
(Result
));
637 ----------------------
638 -- Get_Access_Level --
639 ----------------------
641 function Get_Access_Level
(T
: Tag
) return Natural is
643 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
644 return TSD
(T
).Access_Level
;
645 end Get_Access_Level
;
647 ---------------------
648 -- Get_Entry_Index --
649 ---------------------
651 function Get_Entry_Index
(T
: Tag
; Position
: Positive) return Positive is
652 Index
: constant Integer := Position
- Default_Prim_Op_Count
;
654 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
655 pragma Assert
(Index
> 0);
656 return SSD
(T
).SSD_Table
(Index
).Index
;
659 ----------------------
660 -- Get_External_Tag --
661 ----------------------
663 function Get_External_Tag
(T
: Tag
) return System
.Address
is
665 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
666 return To_Address
(TSD
(T
).External_Tag
);
667 end Get_External_Tag
;
669 ----------------------
670 -- Get_Num_Prim_Ops --
671 ----------------------
673 function Get_Num_Prim_Ops
(T
: Tag
) return Natural is
675 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Secondary_DT
));
677 if Is_Primary_DT
(T
) then
678 return TSD
(T
).Num_Prim_Ops
;
680 return OSD
(Interface_Tag
(T
)).Num_Prim_Ops
;
682 end Get_Num_Prim_Ops
;
684 -------------------------
685 -- Get_Prim_Op_Address --
686 -------------------------
688 function Get_Prim_Op_Address
690 Position
: Positive) return System
.Address
693 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Secondary_DT
));
694 pragma Assert
(Check_Index
(T
, Position
));
695 return T
.Prims_Ptr
(Position
);
696 end Get_Prim_Op_Address
;
698 ----------------------
699 -- Get_Prim_Op_Kind --
700 ----------------------
702 function Get_Prim_Op_Kind
704 Position
: Positive) return Prim_Op_Kind
706 Index
: constant Integer := Position
- Default_Prim_Op_Count
;
708 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
709 pragma Assert
(Index
> 0);
710 return SSD
(T
).SSD_Table
(Index
).Kind
;
711 end Get_Prim_Op_Kind
;
713 ----------------------
714 -- Get_Offset_Index --
715 ----------------------
717 function Get_Offset_Index
719 Position
: Positive) return Positive
721 Index
: constant Integer := Position
- Default_Prim_Op_Count
;
723 pragma Assert
(Check_Signature
(Tag
(T
), Must_Be_Secondary_DT
));
724 pragma Assert
(Index
> 0);
725 return OSD
(T
).OSD_Table
(Index
);
726 end Get_Offset_Index
;
732 function Get_RC_Offset
(T
: Tag
) return SSE
.Storage_Offset
is
734 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
735 return TSD
(T
).RC_Offset
;
738 ---------------------------
739 -- Get_Remotely_Callable --
740 ---------------------------
742 function Get_Remotely_Callable
(T
: Tag
) return Boolean is
744 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
745 return TSD
(T
).Remotely_Callable
;
746 end Get_Remotely_Callable
;
752 procedure Inherit_DT
(Old_T
: Tag
; New_T
: Tag
; Entry_Count
: Natural) is
754 pragma Assert
(Check_Signature
(Old_T
, Must_Be_Primary_Or_Secondary_DT
));
755 pragma Assert
(Check_Signature
(New_T
, Must_Be_Primary_Or_Secondary_DT
));
756 pragma Assert
(Check_Size
(Old_T
, New_T
, Entry_Count
));
758 if Old_T
/= null then
759 New_T
.Prims_Ptr
(1 .. Entry_Count
) :=
760 Old_T
.Prims_Ptr
(1 .. Entry_Count
);
768 procedure Inherit_TSD
(Old_Tag
: Tag
; New_Tag
: Tag
) is
769 New_TSD_Ptr
: Type_Specific_Data_Ptr
;
770 Old_TSD_Ptr
: Type_Specific_Data_Ptr
;
773 pragma Assert
(Check_Signature
(New_Tag
, Must_Be_Primary_Or_Interface
));
774 New_TSD_Ptr
:= TSD
(New_Tag
);
776 if Old_Tag
/= null then
778 (Check_Signature
(Old_Tag
, Must_Be_Primary_Or_Interface
));
779 Old_TSD_Ptr
:= TSD
(Old_Tag
);
780 New_TSD_Ptr
.Idepth
:= Old_TSD_Ptr
.Idepth
+ 1;
781 New_TSD_Ptr
.Num_Interfaces
:= Old_TSD_Ptr
.Num_Interfaces
;
783 -- Copy the "table of ancestor tags" plus the "table of interfaces"
786 New_TSD_Ptr
.Tags_Table
787 (1 .. New_TSD_Ptr
.Idepth
+ New_TSD_Ptr
.Num_Interfaces
) :=
788 Old_TSD_Ptr
.Tags_Table
789 (0 .. Old_TSD_Ptr
.Idepth
+ Old_TSD_Ptr
.Num_Interfaces
);
791 New_TSD_Ptr
.Idepth
:= 0;
792 New_TSD_Ptr
.Num_Interfaces
:= 0;
795 New_TSD_Ptr
.Tags_Table
(0) := New_Tag
;
802 function Internal_Tag
(External
: String) return Tag
is
803 Ext_Copy
: aliased String (External
'First .. External
'Last + 1);
807 -- Make a copy of the string representing the external tag with
808 -- a null at the end.
810 Ext_Copy
(External
'Range) := External
;
811 Ext_Copy
(Ext_Copy
'Last) := ASCII
.NUL
;
812 Res
:= External_Tag_HTable
.Get
(Ext_Copy
'Address);
816 Msg1
: constant String := "unknown tagged type: ";
817 Msg2
: String (1 .. Msg1
'Length + External
'Length);
820 Msg2
(1 .. Msg1
'Length) := Msg1
;
821 Msg2
(Msg1
'Length + 1 .. Msg1
'Length + External
'Length) :=
823 Ada
.Exceptions
.Raise_Exception
(Tag_Error
'Identity, Msg2
);
830 ---------------------------------
831 -- Is_Descendant_At_Same_Level --
832 ---------------------------------
834 function Is_Descendant_At_Same_Level
836 Ancestor
: Tag
) return Boolean
839 return CW_Membership
(Descendant
, Ancestor
)
840 and then TSD
(Descendant
).Access_Level
= TSD
(Ancestor
).Access_Level
;
841 end Is_Descendant_At_Same_Level
;
847 function Is_Primary_DT
(T
: Tag
) return Boolean is
848 Offset_To_Top_Ptr
: constant Storage_Offset_Ptr
:=
849 To_Storage_Offset_Ptr
(To_Address
(T
)
850 - Offset_To_Signature
);
851 Signature
: constant Signature_Values
:=
852 To_Signature_Values
(Offset_To_Top_Ptr
.all);
854 return Signature
(2) = Primary_DT
;
861 function Length
(Str
: Cstring_Ptr
) return Natural is
865 while Str
(Len
) /= ASCII
.Nul
loop
876 function Offset_To_Top
877 (T
: Tag
) return System
.Storage_Elements
.Storage_Offset
879 Offset_To_Top_Ptr
: constant Storage_Offset_Ptr
:=
880 To_Storage_Offset_Ptr
(To_Address
(T
)
881 - DT_Typeinfo_Ptr_Size
882 - DT_Offset_To_Top_Size
);
885 return Offset_To_Top_Ptr
.all;
893 (T
: Interface_Tag
) return Object_Specific_Data_Ptr
898 OSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
899 return To_Object_Specific_Data_Ptr
(OSD_Ptr
.all);
907 (Obj
: System
.Address
;
908 T
: Tag
) return SSE
.Storage_Count
911 -- The tag of the parent type through the dispatch table
914 -- Access to the _size primitive of the parent. We assume that it is
915 -- always in the first slot of the dispatch table.
918 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
919 Parent_Tag
:= TSD
(T
).Tags_Table
(1);
920 F
:= To_Acc_Size
(Parent_Tag
.Prims_Ptr
(1));
922 -- Here we compute the size of the _parent field of the object
924 return SSE
.Storage_Count
(F
.all (Obj
));
931 function Parent_Tag
(T
: Tag
) return Tag
is
937 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
939 -- The Parent_Tag of a root-level tagged type is defined to be No_Tag.
940 -- The first entry in the Ancestors_Tags array will be null for such
941 -- a type, but it's better to be explicit about returning No_Tag in
944 if TSD
(T
).Idepth
= 0 then
947 return TSD
(T
).Tags_Table
(1);
951 ----------------------------
952 -- Register_Interface_Tag --
953 ----------------------------
955 procedure Register_Interface_Tag
(T
: Tag
; Interface_T
: Tag
) is
956 New_T_TSD
: Type_Specific_Data_Ptr
;
960 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
961 pragma Assert
(Check_Signature
(Interface_T
, Must_Be_Interface
));
963 New_T_TSD
:= TSD
(T
);
965 -- Check if the interface is already registered
967 if New_T_TSD
.Num_Interfaces
> 0 then
969 Id
: Natural := New_T_TSD
.Idepth
+ 1;
970 Last_Id
: constant Natural := New_T_TSD
.Idepth
971 + New_T_TSD
.Num_Interfaces
;
975 if New_T_TSD
.Tags_Table
(Id
) = Interface_T
then
980 exit when Id
> Last_Id
;
985 New_T_TSD
.Num_Interfaces
:= New_T_TSD
.Num_Interfaces
+ 1;
986 Index
:= New_T_TSD
.Idepth
+ New_T_TSD
.Num_Interfaces
;
987 New_T_TSD
.Tags_Table
(Index
) := Interface_T
;
988 end Register_Interface_Tag
;
994 procedure Register_Tag
(T
: Tag
) is
996 External_Tag_HTable
.Set
(T
);
999 ----------------------
1000 -- Set_Access_Level --
1001 ----------------------
1003 procedure Set_Access_Level
(T
: Tag
; Value
: Natural) is
1005 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
1006 TSD
(T
).Access_Level
:= Value
;
1007 end Set_Access_Level
;
1009 ---------------------
1010 -- Set_Entry_Index --
1011 ---------------------
1013 procedure Set_Entry_Index
1015 Position
: Positive;
1018 Index
: constant Integer := Position
- Default_Prim_Op_Count
;
1021 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
1022 pragma Assert
(Index
> 0);
1023 SSD
(T
).SSD_Table
(Index
).Index
:= Value
;
1024 end Set_Entry_Index
;
1026 -----------------------
1027 -- Set_Expanded_Name --
1028 -----------------------
1030 procedure Set_Expanded_Name
(T
: Tag
; Value
: System
.Address
) is
1033 (Check_Signature
(T
, Must_Be_Primary_Or_Interface
));
1034 TSD
(T
).Expanded_Name
:= To_Cstring_Ptr
(Value
);
1035 end Set_Expanded_Name
;
1037 ----------------------
1038 -- Set_External_Tag --
1039 ----------------------
1041 procedure Set_External_Tag
(T
: Tag
; Value
: System
.Address
) is
1043 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Interface
));
1044 TSD
(T
).External_Tag
:= To_Cstring_Ptr
(Value
);
1045 end Set_External_Tag
;
1047 ----------------------
1048 -- Set_Num_Prim_Ops --
1049 ----------------------
1051 procedure Set_Num_Prim_Ops
(T
: Tag
; Value
: Natural) is
1053 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Secondary_DT
));
1055 if Is_Primary_DT
(T
) then
1056 TSD
(T
).Num_Prim_Ops
:= Value
;
1058 OSD
(Interface_Tag
(T
)).Num_Prim_Ops
:= Value
;
1060 end Set_Num_Prim_Ops
;
1062 ----------------------
1063 -- Set_Offset_Index --
1064 ----------------------
1066 procedure Set_Offset_Index
1068 Position
: Positive;
1071 Index
: constant Integer := Position
- Default_Prim_Op_Count
;
1073 pragma Assert
(Check_Signature
(Tag
(T
), Must_Be_Secondary_DT
));
1074 pragma Assert
(Index
> 0);
1075 OSD
(T
).OSD_Table
(Index
) := Value
;
1076 end Set_Offset_Index
;
1078 -----------------------
1079 -- Set_Offset_To_Top --
1080 -----------------------
1082 procedure Set_Offset_To_Top
1084 Value
: System
.Storage_Elements
.Storage_Offset
)
1086 Offset_To_Top_Ptr
: constant Storage_Offset_Ptr
:=
1087 To_Storage_Offset_Ptr
(To_Address
(T
)
1088 - DT_Typeinfo_Ptr_Size
1089 - DT_Offset_To_Top_Size
);
1091 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Secondary_DT
));
1092 Offset_To_Top_Ptr
.all := Value
;
1093 end Set_Offset_To_Top
;
1099 procedure Set_OSD
(T
: Interface_Tag
; Value
: System
.Address
) is
1102 pragma Assert
(Check_Signature
(Tag
(T
), Must_Be_Secondary_DT
));
1103 OSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
1104 OSD_Ptr
.all := Value
;
1107 -------------------------
1108 -- Set_Prim_Op_Address --
1109 -------------------------
1111 procedure Set_Prim_Op_Address
1113 Position
: Positive;
1114 Value
: System
.Address
)
1117 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Secondary_DT
));
1118 pragma Assert
(Check_Index
(T
, Position
));
1119 T
.Prims_Ptr
(Position
) := Value
;
1120 end Set_Prim_Op_Address
;
1122 ----------------------
1123 -- Set_Prim_Op_Kind --
1124 ----------------------
1126 procedure Set_Prim_Op_Kind
1128 Position
: Positive;
1129 Value
: Prim_Op_Kind
)
1131 Index
: constant Integer := Position
- Default_Prim_Op_Count
;
1133 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
1134 pragma Assert
(Index
> 0);
1135 SSD
(T
).SSD_Table
(Index
).Kind
:= Value
;
1136 end Set_Prim_Op_Kind
;
1142 procedure Set_RC_Offset
(T
: Tag
; Value
: SSE
.Storage_Offset
) is
1144 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
1145 TSD
(T
).RC_Offset
:= Value
;
1148 ---------------------------
1149 -- Set_Remotely_Callable --
1150 ---------------------------
1152 procedure Set_Remotely_Callable
(T
: Tag
; Value
: Boolean) is
1154 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
1155 TSD
(T
).Remotely_Callable
:= Value
;
1156 end Set_Remotely_Callable
;
1162 procedure Set_SSD
(T
: Tag
; Value
: System
.Address
) is
1164 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_DT
));
1165 TSD
(T
).SSD_Ptr
:= Value
;
1172 procedure Set_TSD
(T
: Tag
; Value
: System
.Address
) is
1175 pragma Assert
(Check_Signature
(T
, Must_Be_Primary_Or_Interface
));
1176 TSD_Ptr
:= To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
1177 TSD_Ptr
.all := Value
;
1184 function SSD
(T
: Tag
) return Select_Specific_Data_Ptr
is
1186 return To_Select_Specific_Data_Ptr
(TSD
(T
).SSD_Ptr
);
1193 function Typeinfo_Ptr
(T
: Tag
) return System
.Address
is
1194 TSD_Ptr
: constant Addr_Ptr
:=
1195 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
1204 function TSD
(T
: Tag
) return Type_Specific_Data_Ptr
is
1205 TSD_Ptr
: constant Addr_Ptr
:=
1206 To_Addr_Ptr
(To_Address
(T
) - DT_Typeinfo_Ptr_Size
);
1208 return To_Type_Specific_Data_Ptr
(TSD_Ptr
.all);