* gcc.dg/compat/struct-layout-1_generate.c (dg_options): New. Moved
[official-gcc.git] / gcc / ada / a-tags.adb
blob3f841c622f4c15174383b03e5410862b2509150d
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- A D A . T A G S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
10 -- --
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. --
21 -- --
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. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
32 ------------------------------------------------------------------------------
34 with Ada.Exceptions;
35 with Ada.Unchecked_Conversion;
36 with System.HTable;
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
68 -- Data table.
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
90 function To_Tag is
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_Tag_Ptr is
109 new Ada.Unchecked_Conversion (System.Address, Tag_Ptr);
111 function To_Type_Specific_Data_Ptr is
112 new Ada.Unchecked_Conversion (System.Address, Type_Specific_Data_Ptr);
114 -------------------------------
115 -- Inline_Always Subprograms --
116 -------------------------------
118 -- Inline_always subprograms must be placed before their first call to
119 -- avoid defeating the frontend inlining mechanism and thus ensure the
120 -- generation of their correct debug info.
122 -------------------
123 -- CW_Membership --
124 -------------------
126 -- Canonical implementation of Classwide Membership corresponding to:
128 -- Obj in Typ'Class
130 -- Each dispatch table contains a reference to a table of ancestors (stored
131 -- in the first part of the Tags_Table) and a count of the level of
132 -- inheritance "Idepth".
134 -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
135 -- contained in the dispatch table referenced by Obj'Tag . Knowing the
136 -- level of inheritance of both types, this can be computed in constant
137 -- time by the formula:
139 -- TSD (Obj'tag).Tags_Table (TSD (Obj'tag).Idepth - TSD (Typ'tag).Idepth)
140 -- = Typ'tag
142 function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean is
143 Obj_TSD_Ptr : constant Addr_Ptr :=
144 To_Addr_Ptr (To_Address (Obj_Tag) - DT_Typeinfo_Ptr_Size);
145 Typ_TSD_Ptr : constant Addr_Ptr :=
146 To_Addr_Ptr (To_Address (Typ_Tag) - DT_Typeinfo_Ptr_Size);
147 Obj_TSD : constant Type_Specific_Data_Ptr :=
148 To_Type_Specific_Data_Ptr (Obj_TSD_Ptr.all);
149 Typ_TSD : constant Type_Specific_Data_Ptr :=
150 To_Type_Specific_Data_Ptr (Typ_TSD_Ptr.all);
151 Pos : constant Integer := Obj_TSD.Idepth - Typ_TSD.Idepth;
152 begin
153 return Pos >= 0 and then Obj_TSD.Tags_Table (Pos) = Typ_Tag;
154 end CW_Membership;
156 ----------------------
157 -- Get_External_Tag --
158 ----------------------
160 function Get_External_Tag (T : Tag) return System.Address is
161 TSD_Ptr : constant Addr_Ptr :=
162 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
163 TSD : constant Type_Specific_Data_Ptr :=
164 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
165 begin
166 return To_Address (TSD.External_Tag);
167 end Get_External_Tag;
169 -------------------
170 -- Is_Primary_DT --
171 -------------------
173 function Is_Primary_DT (T : Tag) return Boolean is
174 begin
175 return DT (T).Signature = Primary_DT;
176 end Is_Primary_DT;
178 ---------
179 -- OSD --
180 ---------
182 function OSD (T : Tag) return Object_Specific_Data_Ptr is
183 OSD_Ptr : constant Addr_Ptr :=
184 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
185 begin
186 return To_Object_Specific_Data_Ptr (OSD_Ptr.all);
187 end OSD;
189 ---------
190 -- SSD --
191 ---------
193 function SSD (T : Tag) return Select_Specific_Data_Ptr is
194 TSD_Ptr : constant Addr_Ptr :=
195 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
196 TSD : constant Type_Specific_Data_Ptr :=
197 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
198 begin
199 return TSD.SSD;
200 end SSD;
202 -------------------------
203 -- External_Tag_HTable --
204 -------------------------
206 type HTable_Headers is range 1 .. 64;
208 -- The following internal package defines the routines used for the
209 -- instantiation of a new System.HTable.Static_HTable (see below). See
210 -- spec in g-htable.ads for details of usage.
212 package HTable_Subprograms is
213 procedure Set_HT_Link (T : Tag; Next : Tag);
214 function Get_HT_Link (T : Tag) return Tag;
215 function Hash (F : System.Address) return HTable_Headers;
216 function Equal (A, B : System.Address) return Boolean;
217 end HTable_Subprograms;
219 package External_Tag_HTable is new System.HTable.Static_HTable (
220 Header_Num => HTable_Headers,
221 Element => Dispatch_Table,
222 Elmt_Ptr => Tag,
223 Null_Ptr => null,
224 Set_Next => HTable_Subprograms.Set_HT_Link,
225 Next => HTable_Subprograms.Get_HT_Link,
226 Key => System.Address,
227 Get_Key => Get_External_Tag,
228 Hash => HTable_Subprograms.Hash,
229 Equal => HTable_Subprograms.Equal);
231 ------------------------
232 -- HTable_Subprograms --
233 ------------------------
235 -- Bodies of routines for hash table instantiation
237 package body HTable_Subprograms is
239 -----------
240 -- Equal --
241 -----------
243 function Equal (A, B : System.Address) return Boolean is
244 Str1 : constant Cstring_Ptr := To_Cstring_Ptr (A);
245 Str2 : constant Cstring_Ptr := To_Cstring_Ptr (B);
246 J : Integer := 1;
247 begin
248 loop
249 if Str1 (J) /= Str2 (J) then
250 return False;
251 elsif Str1 (J) = ASCII.NUL then
252 return True;
253 else
254 J := J + 1;
255 end if;
256 end loop;
257 end Equal;
259 -----------------
260 -- Get_HT_Link --
261 -----------------
263 function Get_HT_Link (T : Tag) return Tag is
264 TSD_Ptr : constant Addr_Ptr :=
265 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
266 TSD : constant Type_Specific_Data_Ptr :=
267 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
268 begin
269 return TSD.HT_Link.all;
270 end Get_HT_Link;
272 ----------
273 -- Hash --
274 ----------
276 function Hash (F : System.Address) return HTable_Headers is
277 function H is new System.HTable.Hash (HTable_Headers);
278 Str : constant Cstring_Ptr := To_Cstring_Ptr (F);
279 Res : constant HTable_Headers := H (Str (1 .. Length (Str)));
280 begin
281 return Res;
282 end Hash;
284 -----------------
285 -- Set_HT_Link --
286 -----------------
288 procedure Set_HT_Link (T : Tag; Next : Tag) is
289 TSD_Ptr : constant Addr_Ptr :=
290 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
291 TSD : constant Type_Specific_Data_Ptr :=
292 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
293 begin
294 TSD.HT_Link.all := Next;
295 end Set_HT_Link;
297 end HTable_Subprograms;
299 ------------------
300 -- Base_Address --
301 ------------------
303 function Base_Address (This : System.Address) return System.Address is
304 begin
305 return This - Offset_To_Top (This);
306 end Base_Address;
308 --------------------
309 -- Descendant_Tag --
310 --------------------
312 function Descendant_Tag (External : String; Ancestor : Tag) return Tag is
313 Int_Tag : constant Tag := Internal_Tag (External);
315 begin
316 if not Is_Descendant_At_Same_Level (Int_Tag, Ancestor) then
317 raise Tag_Error;
318 end if;
320 return Int_Tag;
321 end Descendant_Tag;
323 --------------
324 -- Displace --
325 --------------
327 function Displace
328 (This : System.Address;
329 T : Tag) return System.Address
331 Iface_Table : Interface_Data_Ptr;
332 Obj_Base : System.Address;
333 Obj_DT : Dispatch_Table_Ptr;
334 Obj_DT_Tag : Tag;
336 begin
337 if System."=" (This, System.Null_Address) then
338 return System.Null_Address;
339 end if;
341 Obj_Base := Base_Address (This);
342 Obj_DT_Tag := To_Tag_Ptr (Obj_Base).all;
343 Obj_DT := DT (To_Tag_Ptr (Obj_Base).all);
344 Iface_Table := To_Type_Specific_Data_Ptr (Obj_DT.TSD).Interfaces_Table;
346 if Iface_Table /= null then
347 for Id in 1 .. Iface_Table.Nb_Ifaces loop
348 if Iface_Table.Ifaces_Table (Id).Iface_Tag = T then
350 -- Case of Static value of Offset_To_Top
352 if Iface_Table.Ifaces_Table (Id).Static_Offset_To_Top then
353 Obj_Base := Obj_Base +
354 Iface_Table.Ifaces_Table (Id).Offset_To_Top_Value;
356 -- Otherwise call the function generated by the expander to
357 -- provide the value.
359 else
360 Obj_Base := Obj_Base +
361 Iface_Table.Ifaces_Table (Id).Offset_To_Top_Func.all
362 (Obj_Base);
363 end if;
365 return Obj_Base;
366 end if;
367 end loop;
368 end if;
370 -- Check if T is an immediate ancestor. This is required to handle
371 -- conversion of class-wide interfaces to tagged types.
373 if CW_Membership (Obj_DT_Tag, T) then
374 return Obj_Base;
375 end if;
377 -- If the object does not implement the interface we must raise CE
379 raise Constraint_Error with "invalid interface conversion";
380 end Displace;
382 --------
383 -- DT --
384 --------
386 function DT (T : Tag) return Dispatch_Table_Ptr is
387 Offset : constant SSE.Storage_Offset :=
388 To_Dispatch_Table_Ptr (T).Prims_Ptr'Position;
389 begin
390 return To_Dispatch_Table_Ptr (To_Address (T) - Offset);
391 end DT;
393 -------------------
394 -- IW_Membership --
395 -------------------
397 -- Canonical implementation of Classwide Membership corresponding to:
399 -- Obj in Iface'Class
401 -- Each dispatch table contains a table with the tags of all the
402 -- implemented interfaces.
404 -- Obj is in Iface'Class if Iface'Tag is found in the table of interfaces
405 -- that are contained in the dispatch table referenced by Obj'Tag.
407 function IW_Membership (This : System.Address; T : Tag) return Boolean is
408 Iface_Table : Interface_Data_Ptr;
409 Obj_Base : System.Address;
410 Obj_DT : Dispatch_Table_Ptr;
411 Obj_TSD : Type_Specific_Data_Ptr;
413 begin
414 Obj_Base := Base_Address (This);
415 Obj_DT := DT (To_Tag_Ptr (Obj_Base).all);
416 Obj_TSD := To_Type_Specific_Data_Ptr (Obj_DT.TSD);
417 Iface_Table := Obj_TSD.Interfaces_Table;
419 if Iface_Table /= null then
420 for Id in 1 .. Iface_Table.Nb_Ifaces loop
421 if Iface_Table.Ifaces_Table (Id).Iface_Tag = T then
422 return True;
423 end if;
424 end loop;
425 end if;
427 -- Look for the tag in the ancestor tags table. This is required for:
428 -- Iface_CW in Typ'Class
430 for Id in 0 .. Obj_TSD.Idepth loop
431 if Obj_TSD.Tags_Table (Id) = T then
432 return True;
433 end if;
434 end loop;
436 return False;
437 end IW_Membership;
439 -------------------
440 -- Expanded_Name --
441 -------------------
443 function Expanded_Name (T : Tag) return String is
444 Result : Cstring_Ptr;
445 TSD_Ptr : Addr_Ptr;
446 TSD : Type_Specific_Data_Ptr;
448 begin
449 if T = No_Tag then
450 raise Tag_Error;
451 end if;
453 TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
454 TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all);
455 Result := TSD.Expanded_Name;
456 return Result (1 .. Length (Result));
457 end Expanded_Name;
459 ------------------
460 -- External_Tag --
461 ------------------
463 function External_Tag (T : Tag) return String is
464 Result : Cstring_Ptr;
465 TSD_Ptr : Addr_Ptr;
466 TSD : Type_Specific_Data_Ptr;
468 begin
469 if T = No_Tag then
470 raise Tag_Error;
471 end if;
473 TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
474 TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all);
475 Result := TSD.External_Tag;
476 return Result (1 .. Length (Result));
477 end External_Tag;
479 ---------------------
480 -- Get_Entry_Index --
481 ---------------------
483 function Get_Entry_Index (T : Tag; Position : Positive) return Positive is
484 begin
485 return SSD (T).SSD_Table (Position).Index;
486 end Get_Entry_Index;
488 ----------------------
489 -- Get_Prim_Op_Kind --
490 ----------------------
492 function Get_Prim_Op_Kind
493 (T : Tag;
494 Position : Positive) return Prim_Op_Kind
496 begin
497 return SSD (T).SSD_Table (Position).Kind;
498 end Get_Prim_Op_Kind;
500 ----------------------
501 -- Get_Offset_Index --
502 ----------------------
504 function Get_Offset_Index
505 (T : Tag;
506 Position : Positive) return Positive
508 begin
509 if Is_Primary_DT (T) then
510 return Position;
511 else
512 return OSD (T).OSD_Table (Position);
513 end if;
514 end Get_Offset_Index;
516 -------------------
517 -- Get_RC_Offset --
518 -------------------
520 function Get_RC_Offset (T : Tag) return SSE.Storage_Offset is
521 TSD_Ptr : constant Addr_Ptr :=
522 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
523 TSD : constant Type_Specific_Data_Ptr :=
524 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
525 begin
526 return TSD.RC_Offset;
527 end Get_RC_Offset;
529 ---------------------
530 -- Get_Tagged_Kind --
531 ---------------------
533 function Get_Tagged_Kind (T : Tag) return Tagged_Kind is
534 begin
535 return DT (T).Tag_Kind;
536 end Get_Tagged_Kind;
538 -----------------------------
539 -- Interface_Ancestor_Tags --
540 -----------------------------
542 function Interface_Ancestor_Tags (T : Tag) return Tag_Array is
543 TSD_Ptr : constant Addr_Ptr :=
544 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
545 TSD : constant Type_Specific_Data_Ptr :=
546 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
547 Iface_Table : constant Interface_Data_Ptr := TSD.Interfaces_Table;
549 begin
550 if Iface_Table = null then
551 declare
552 Table : Tag_Array (1 .. 0);
553 begin
554 return Table;
555 end;
556 else
557 declare
558 Table : Tag_Array (1 .. Iface_Table.Nb_Ifaces);
559 begin
560 for J in 1 .. Iface_Table.Nb_Ifaces loop
561 Table (J) := Iface_Table.Ifaces_Table (J).Iface_Tag;
562 end loop;
564 return Table;
565 end;
566 end if;
567 end Interface_Ancestor_Tags;
569 ------------------
570 -- Internal_Tag --
571 ------------------
573 -- Internal tags have the following format:
574 -- "Internal tag at 16#ADDRESS#: <full-name-of-tagged-type>"
576 Internal_Tag_Header : constant String := "Internal tag at ";
577 Header_Separator : constant Character := '#';
579 function Internal_Tag (External : String) return Tag is
580 Ext_Copy : aliased String (External'First .. External'Last + 1);
581 Res : Tag := null;
583 begin
584 -- Handle locally defined tagged types
586 if External'Length > Internal_Tag_Header'Length
587 and then
588 External (External'First ..
589 External'First + Internal_Tag_Header'Length - 1)
590 = Internal_Tag_Header
591 then
592 declare
593 Addr_First : constant Natural :=
594 External'First + Internal_Tag_Header'Length;
595 Addr_Last : Natural;
596 Addr : Integer_Address;
598 begin
599 -- Search the second separator (#) to identify the address
601 Addr_Last := Addr_First;
603 for J in 1 .. 2 loop
604 while Addr_Last <= External'Last
605 and then External (Addr_Last) /= Header_Separator
606 loop
607 Addr_Last := Addr_Last + 1;
608 end loop;
610 -- Skip the first separator
612 if J = 1 then
613 Addr_Last := Addr_Last + 1;
614 end if;
615 end loop;
617 if Addr_Last <= External'Last then
619 -- Protect the run-time against wrong internal tags. We
620 -- cannot use exception handlers here because it would
621 -- disable the use of this run-time compiling with
622 -- restriction No_Exception_Handler.
624 declare
625 C : Character;
626 Wrong_Tag : Boolean := False;
628 begin
629 if External (Addr_First) /= '1'
630 or else External (Addr_First + 1) /= '6'
631 or else External (Addr_First + 2) /= '#'
632 then
633 Wrong_Tag := True;
635 else
636 for J in Addr_First + 3 .. Addr_Last - 1 loop
637 C := External (J);
639 if not (C in '0' .. '9')
640 and then not (C in 'A' .. 'F')
641 and then not (C in 'a' .. 'f')
642 then
643 Wrong_Tag := True;
644 exit;
645 end if;
646 end loop;
647 end if;
649 -- Convert the numeric value into a tag
651 if not Wrong_Tag then
652 Addr := Integer_Address'Value
653 (External (Addr_First .. Addr_Last));
655 -- Internal tags never have value 0
657 if Addr /= 0 then
658 return To_Tag (Addr);
659 end if;
660 end if;
661 end;
662 end if;
663 end;
665 -- Handle library-level tagged types
667 else
668 -- Make NUL-terminated copy of external tag string
670 Ext_Copy (External'Range) := External;
671 Ext_Copy (Ext_Copy'Last) := ASCII.NUL;
672 Res := External_Tag_HTable.Get (Ext_Copy'Address);
673 end if;
675 if Res = null then
676 declare
677 Msg1 : constant String := "unknown tagged type: ";
678 Msg2 : String (1 .. Msg1'Length + External'Length);
680 begin
681 Msg2 (1 .. Msg1'Length) := Msg1;
682 Msg2 (Msg1'Length + 1 .. Msg1'Length + External'Length) :=
683 External;
684 Ada.Exceptions.Raise_Exception (Tag_Error'Identity, Msg2);
685 end;
686 end if;
688 return Res;
689 end Internal_Tag;
691 ---------------------------------
692 -- Is_Descendant_At_Same_Level --
693 ---------------------------------
695 function Is_Descendant_At_Same_Level
696 (Descendant : Tag;
697 Ancestor : Tag) return Boolean
699 D_TSD_Ptr : constant Addr_Ptr :=
700 To_Addr_Ptr (To_Address (Descendant)
701 - DT_Typeinfo_Ptr_Size);
702 A_TSD_Ptr : constant Addr_Ptr :=
703 To_Addr_Ptr (To_Address (Ancestor) - DT_Typeinfo_Ptr_Size);
704 D_TSD : constant Type_Specific_Data_Ptr :=
705 To_Type_Specific_Data_Ptr (D_TSD_Ptr.all);
706 A_TSD : constant Type_Specific_Data_Ptr :=
707 To_Type_Specific_Data_Ptr (A_TSD_Ptr.all);
709 begin
710 return CW_Membership (Descendant, Ancestor)
711 and then D_TSD.Access_Level = A_TSD.Access_Level;
712 end Is_Descendant_At_Same_Level;
714 ------------
715 -- Length --
716 ------------
718 function Length (Str : Cstring_Ptr) return Natural is
719 Len : Integer;
721 begin
722 Len := 1;
723 while Str (Len) /= ASCII.NUL loop
724 Len := Len + 1;
725 end loop;
727 return Len - 1;
728 end Length;
730 -------------------
731 -- Offset_To_Top --
732 -------------------
734 function Offset_To_Top
735 (This : System.Address) return SSE.Storage_Offset
737 Tag_Size : constant SSE.Storage_Count :=
738 SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit));
740 type Storage_Offset_Ptr is access SSE.Storage_Offset;
741 function To_Storage_Offset_Ptr is
742 new Unchecked_Conversion (System.Address, Storage_Offset_Ptr);
744 Curr_DT : Dispatch_Table_Ptr;
746 begin
747 Curr_DT := DT (To_Tag_Ptr (This).all);
749 if Curr_DT.Offset_To_Top = SSE.Storage_Offset'Last then
750 return To_Storage_Offset_Ptr (This + Tag_Size).all;
751 else
752 return Curr_DT.Offset_To_Top;
753 end if;
754 end Offset_To_Top;
756 -----------------
757 -- Parent_Size --
758 -----------------
760 function Parent_Size
761 (Obj : System.Address;
762 T : Tag) return SSE.Storage_Count
764 Parent_Slot : constant Positive := 1;
765 -- The tag of the parent is always in the first slot of the table of
766 -- ancestor tags.
768 TSD_Ptr : constant Addr_Ptr :=
769 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
770 TSD : constant Type_Specific_Data_Ptr :=
771 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
772 -- Pointer to the TSD
774 Parent_Tag : constant Tag := TSD.Tags_Table (Parent_Slot);
775 Parent_TSD_Ptr : constant Addr_Ptr :=
776 To_Addr_Ptr (To_Address (Parent_Tag)
777 - DT_Typeinfo_Ptr_Size);
778 Parent_TSD : constant Type_Specific_Data_Ptr :=
779 To_Type_Specific_Data_Ptr (Parent_TSD_Ptr.all);
781 begin
782 -- Here we compute the size of the _parent field of the object
784 return SSE.Storage_Count (Parent_TSD.Size_Func.all (Obj));
785 end Parent_Size;
787 ----------------
788 -- Parent_Tag --
789 ----------------
791 function Parent_Tag (T : Tag) return Tag is
792 TSD_Ptr : Addr_Ptr;
793 TSD : Type_Specific_Data_Ptr;
795 begin
796 if T = No_Tag then
797 raise Tag_Error;
798 end if;
800 TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
801 TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all);
803 -- The Parent_Tag of a root-level tagged type is defined to be No_Tag.
804 -- The first entry in the Ancestors_Tags array will be null for such
805 -- a type, but it's better to be explicit about returning No_Tag in
806 -- this case.
808 if TSD.Idepth = 0 then
809 return No_Tag;
810 else
811 return TSD.Tags_Table (1);
812 end if;
813 end Parent_Tag;
815 -------------------------------
816 -- Register_Interface_Offset --
817 -------------------------------
819 procedure Register_Interface_Offset
820 (This : System.Address;
821 Interface_T : Tag;
822 Is_Static : Boolean;
823 Offset_Value : SSE.Storage_Offset;
824 Offset_Func : Offset_To_Top_Function_Ptr)
826 Prim_DT : Dispatch_Table_Ptr;
827 Iface_Table : Interface_Data_Ptr;
829 begin
830 -- "This" points to the primary DT and we must save Offset_Value in
831 -- the Offset_To_Top field of the corresponding dispatch table.
833 Prim_DT := DT (To_Tag_Ptr (This).all);
834 Iface_Table := To_Type_Specific_Data_Ptr (Prim_DT.TSD).Interfaces_Table;
836 -- Save Offset_Value in the table of interfaces of the primary DT.
837 -- This data will be used by the subprogram "Displace" to give support
838 -- to backward abstract interface type conversions.
840 -- Register the offset in the table of interfaces
842 if Iface_Table /= null then
843 for Id in 1 .. Iface_Table.Nb_Ifaces loop
844 if Iface_Table.Ifaces_Table (Id).Iface_Tag = Interface_T then
845 if Is_Static or else Offset_Value = 0 then
846 Iface_Table.Ifaces_Table (Id).Static_Offset_To_Top := True;
847 Iface_Table.Ifaces_Table (Id).Offset_To_Top_Value :=
848 Offset_Value;
849 else
850 Iface_Table.Ifaces_Table (Id).Static_Offset_To_Top := False;
851 Iface_Table.Ifaces_Table (Id).Offset_To_Top_Func :=
852 Offset_Func;
853 end if;
855 return;
856 end if;
857 end loop;
858 end if;
860 -- If we arrive here there is some error in the run-time data structure
862 raise Program_Error;
863 end Register_Interface_Offset;
865 ------------------
866 -- Register_Tag --
867 ------------------
869 procedure Register_Tag (T : Tag) is
870 begin
871 External_Tag_HTable.Set (T);
872 end Register_Tag;
874 -------------------
875 -- Secondary_Tag --
876 -------------------
878 function Secondary_Tag (T, Iface : Tag) return Tag is
879 Iface_Table : Interface_Data_Ptr;
880 Obj_DT : Dispatch_Table_Ptr;
882 begin
883 if not Is_Primary_DT (T) then
884 raise Program_Error;
885 end if;
887 Obj_DT := DT (T);
888 Iface_Table := To_Type_Specific_Data_Ptr (Obj_DT.TSD).Interfaces_Table;
890 if Iface_Table /= null then
891 for Id in 1 .. Iface_Table.Nb_Ifaces loop
892 if Iface_Table.Ifaces_Table (Id).Iface_Tag = Iface then
893 return Iface_Table.Ifaces_Table (Id).Secondary_DT;
894 end if;
895 end loop;
896 end if;
898 -- If the object does not implement the interface we must raise CE
900 raise Constraint_Error with "invalid interface conversion";
901 end Secondary_Tag;
903 ---------------------
904 -- Set_Entry_Index --
905 ---------------------
907 procedure Set_Entry_Index
908 (T : Tag;
909 Position : Positive;
910 Value : Positive)
912 begin
913 SSD (T).SSD_Table (Position).Index := Value;
914 end Set_Entry_Index;
916 -----------------------
917 -- Set_Offset_To_Top --
918 -----------------------
920 procedure Set_Dynamic_Offset_To_Top
921 (This : System.Address;
922 Interface_T : Tag;
923 Offset_Value : SSE.Storage_Offset;
924 Offset_Func : Offset_To_Top_Function_Ptr)
926 Sec_Base : System.Address;
927 Sec_DT : Dispatch_Table_Ptr;
928 begin
929 -- Save the offset to top field in the secondary dispatch table
931 if Offset_Value /= 0 then
932 Sec_Base := This + Offset_Value;
933 Sec_DT := DT (To_Tag_Ptr (Sec_Base).all);
934 Sec_DT.Offset_To_Top := SSE.Storage_Offset'Last;
935 end if;
937 Register_Interface_Offset
938 (This, Interface_T, False, Offset_Value, Offset_Func);
939 end Set_Dynamic_Offset_To_Top;
941 ----------------------
942 -- Set_Prim_Op_Kind --
943 ----------------------
945 procedure Set_Prim_Op_Kind
946 (T : Tag;
947 Position : Positive;
948 Value : Prim_Op_Kind)
950 begin
951 SSD (T).SSD_Table (Position).Kind := Value;
952 end Set_Prim_Op_Kind;
954 ------------------------
955 -- Wide_Expanded_Name --
956 ------------------------
958 WC_Encoding : Character;
959 pragma Import (C, WC_Encoding, "__gl_wc_encoding");
960 -- Encoding method for source, as exported by binder
962 function Wide_Expanded_Name (T : Tag) return Wide_String is
963 S : constant String := Expanded_Name (T);
964 W : Wide_String (1 .. S'Length);
965 L : Natural;
966 begin
967 String_To_Wide_String
968 (S, W, L, Get_WC_Encoding_Method (WC_Encoding));
969 return W (1 .. L);
970 end Wide_Expanded_Name;
972 -----------------------------
973 -- Wide_Wide_Expanded_Name --
974 -----------------------------
976 function Wide_Wide_Expanded_Name (T : Tag) return Wide_Wide_String is
977 S : constant String := Expanded_Name (T);
978 W : Wide_Wide_String (1 .. S'Length);
979 L : Natural;
980 begin
981 String_To_Wide_Wide_String
982 (S, W, L, Get_WC_Encoding_Method (WC_Encoding));
983 return W (1 .. L);
984 end Wide_Wide_Expanded_Name;
986 end Ada.Tags;