annotate gcc/ada/libgnat/a-tags.adb @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT RUN-TIME COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- A D A . T A G S --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
kono
parents:
diff changeset
9 -- Copyright (C) 1992-2017, Free Software Foundation, Inc. --
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNAT is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
kono
parents:
diff changeset
17 -- --
kono
parents:
diff changeset
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
kono
parents:
diff changeset
19 -- additional permissions described in the GCC Runtime Library Exception, --
kono
parents:
diff changeset
20 -- version 3.1, as published by the Free Software Foundation. --
kono
parents:
diff changeset
21 -- --
kono
parents:
diff changeset
22 -- You should have received a copy of the GNU General Public License and --
kono
parents:
diff changeset
23 -- a copy of the GCC Runtime Library Exception along with this program; --
kono
parents:
diff changeset
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
kono
parents:
diff changeset
25 -- <http://www.gnu.org/licenses/>. --
kono
parents:
diff changeset
26 -- --
kono
parents:
diff changeset
27 -- GNAT was originally developed by the GNAT team at New York University. --
kono
parents:
diff changeset
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
kono
parents:
diff changeset
29 -- --
kono
parents:
diff changeset
30 ------------------------------------------------------------------------------
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 with Ada.Exceptions;
kono
parents:
diff changeset
33 with Ada.Unchecked_Conversion;
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 with System.HTable;
kono
parents:
diff changeset
36 with System.Storage_Elements; use System.Storage_Elements;
kono
parents:
diff changeset
37 with System.WCh_Con; use System.WCh_Con;
kono
parents:
diff changeset
38 with System.WCh_StW; use System.WCh_StW;
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 pragma Elaborate (System.HTable);
kono
parents:
diff changeset
41 -- Elaborate needed instead of Elaborate_All to avoid elaboration cycles
kono
parents:
diff changeset
42 -- when polling is turned on. This is safe because HTable doesn't do anything
kono
parents:
diff changeset
43 -- at elaboration time; it just contains a generic package we want to
kono
parents:
diff changeset
44 -- instantiate.
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 package body Ada.Tags is
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 -----------------------
kono
parents:
diff changeset
49 -- Local Subprograms --
kono
parents:
diff changeset
50 -----------------------
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean;
kono
parents:
diff changeset
53 -- Given the tag of an object and the tag associated to a type, return
kono
parents:
diff changeset
54 -- true if Obj is in Typ'Class.
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 function Get_External_Tag (T : Tag) return System.Address;
kono
parents:
diff changeset
57 -- Returns address of a null terminated string containing the external name
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 function Is_Primary_DT (T : Tag) return Boolean;
kono
parents:
diff changeset
60 -- Given a tag returns True if it has the signature of a primary dispatch
kono
parents:
diff changeset
61 -- table. This is Inline_Always since it is called from other Inline_
kono
parents:
diff changeset
62 -- Always subprograms where we want no out of line code to be generated.
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 function IW_Membership
kono
parents:
diff changeset
65 (Descendant_TSD : Type_Specific_Data_Ptr;
kono
parents:
diff changeset
66 T : Tag) return Boolean;
kono
parents:
diff changeset
67 -- Subsidiary function of IW_Membership and CW_Membership which factorizes
kono
parents:
diff changeset
68 -- the functionality needed to check if a given descendant implements an
kono
parents:
diff changeset
69 -- interface tag T.
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 function Length (Str : Cstring_Ptr) return Natural;
kono
parents:
diff changeset
72 -- Length of string represented by the given pointer (treating the string
kono
parents:
diff changeset
73 -- as a C-style string, which is Nul terminated). See comment in body
kono
parents:
diff changeset
74 -- explaining why we cannot use the normal strlen built-in.
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 function OSD (T : Tag) return Object_Specific_Data_Ptr;
kono
parents:
diff changeset
77 -- Ada 2005 (AI-251): Given a pointer T to a secondary dispatch table,
kono
parents:
diff changeset
78 -- retrieve the address of the record containing the Object Specific
kono
parents:
diff changeset
79 -- Data table.
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 function SSD (T : Tag) return Select_Specific_Data_Ptr;
kono
parents:
diff changeset
82 -- Ada 2005 (AI-251): Given a pointer T to a dispatch Table, retrieves the
kono
parents:
diff changeset
83 -- address of the record containing the Select Specific Data in T's TSD.
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 pragma Inline_Always (CW_Membership);
kono
parents:
diff changeset
86 pragma Inline_Always (Get_External_Tag);
kono
parents:
diff changeset
87 pragma Inline_Always (Is_Primary_DT);
kono
parents:
diff changeset
88 pragma Inline_Always (OSD);
kono
parents:
diff changeset
89 pragma Inline_Always (SSD);
kono
parents:
diff changeset
90
kono
parents:
diff changeset
91 -- Unchecked conversions
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 function To_Address is
kono
parents:
diff changeset
94 new Unchecked_Conversion (Cstring_Ptr, System.Address);
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 function To_Cstring_Ptr is
kono
parents:
diff changeset
97 new Unchecked_Conversion (System.Address, Cstring_Ptr);
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 -- Disable warnings on possible aliasing problem
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 function To_Tag is
kono
parents:
diff changeset
102 new Unchecked_Conversion (Integer_Address, Tag);
kono
parents:
diff changeset
103
kono
parents:
diff changeset
104 function To_Addr_Ptr is
kono
parents:
diff changeset
105 new Ada.Unchecked_Conversion (System.Address, Addr_Ptr);
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 function To_Address is
kono
parents:
diff changeset
108 new Ada.Unchecked_Conversion (Tag, System.Address);
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 function To_Dispatch_Table_Ptr is
kono
parents:
diff changeset
111 new Ada.Unchecked_Conversion (Tag, Dispatch_Table_Ptr);
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 function To_Dispatch_Table_Ptr is
kono
parents:
diff changeset
114 new Ada.Unchecked_Conversion (System.Address, Dispatch_Table_Ptr);
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 function To_Object_Specific_Data_Ptr is
kono
parents:
diff changeset
117 new Ada.Unchecked_Conversion (System.Address, Object_Specific_Data_Ptr);
kono
parents:
diff changeset
118
kono
parents:
diff changeset
119 function To_Tag_Ptr is
kono
parents:
diff changeset
120 new Ada.Unchecked_Conversion (System.Address, Tag_Ptr);
kono
parents:
diff changeset
121
kono
parents:
diff changeset
122 function To_Type_Specific_Data_Ptr is
kono
parents:
diff changeset
123 new Ada.Unchecked_Conversion (System.Address, Type_Specific_Data_Ptr);
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 -------------------------------
kono
parents:
diff changeset
126 -- Inline_Always Subprograms --
kono
parents:
diff changeset
127 -------------------------------
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 -- Inline_always subprograms must be placed before their first call to
kono
parents:
diff changeset
130 -- avoid defeating the frontend inlining mechanism and thus ensure the
kono
parents:
diff changeset
131 -- generation of their correct debug info.
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 -------------------
kono
parents:
diff changeset
134 -- CW_Membership --
kono
parents:
diff changeset
135 -------------------
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 -- Canonical implementation of Classwide Membership corresponding to:
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 -- Obj in Typ'Class
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 -- Each dispatch table contains a reference to a table of ancestors (stored
kono
parents:
diff changeset
142 -- in the first part of the Tags_Table) and a count of the level of
kono
parents:
diff changeset
143 -- inheritance "Idepth".
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 -- Obj is in Typ'Class if Typ'Tag is in the table of ancestors that are
kono
parents:
diff changeset
146 -- contained in the dispatch table referenced by Obj'Tag . Knowing the
kono
parents:
diff changeset
147 -- level of inheritance of both types, this can be computed in constant
kono
parents:
diff changeset
148 -- time by the formula:
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 -- TSD (Obj'tag).Tags_Table (TSD (Obj'tag).Idepth - TSD (Typ'tag).Idepth)
kono
parents:
diff changeset
151 -- = Typ'tag
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 function CW_Membership (Obj_Tag : Tag; Typ_Tag : Tag) return Boolean is
kono
parents:
diff changeset
154 Obj_TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
155 To_Addr_Ptr (To_Address (Obj_Tag) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
156 Typ_TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
157 To_Addr_Ptr (To_Address (Typ_Tag) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
158 Obj_TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
159 To_Type_Specific_Data_Ptr (Obj_TSD_Ptr.all);
kono
parents:
diff changeset
160 Typ_TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
161 To_Type_Specific_Data_Ptr (Typ_TSD_Ptr.all);
kono
parents:
diff changeset
162 Pos : constant Integer := Obj_TSD.Idepth - Typ_TSD.Idepth;
kono
parents:
diff changeset
163 begin
kono
parents:
diff changeset
164 return Pos >= 0 and then Obj_TSD.Tags_Table (Pos) = Typ_Tag;
kono
parents:
diff changeset
165 end CW_Membership;
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 ----------------------
kono
parents:
diff changeset
168 -- Get_External_Tag --
kono
parents:
diff changeset
169 ----------------------
kono
parents:
diff changeset
170
kono
parents:
diff changeset
171 function Get_External_Tag (T : Tag) return System.Address is
kono
parents:
diff changeset
172 TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
173 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
174 TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
175 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
176 begin
kono
parents:
diff changeset
177 return To_Address (TSD.External_Tag);
kono
parents:
diff changeset
178 end Get_External_Tag;
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 -----------------
kono
parents:
diff changeset
181 -- Is_Abstract --
kono
parents:
diff changeset
182 -----------------
kono
parents:
diff changeset
183
kono
parents:
diff changeset
184 function Is_Abstract (T : Tag) return Boolean is
kono
parents:
diff changeset
185 TSD_Ptr : Addr_Ptr;
kono
parents:
diff changeset
186 TSD : Type_Specific_Data_Ptr;
kono
parents:
diff changeset
187
kono
parents:
diff changeset
188 begin
kono
parents:
diff changeset
189 if T = No_Tag then
kono
parents:
diff changeset
190 raise Tag_Error;
kono
parents:
diff changeset
191 end if;
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
194 TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
195 return TSD.Is_Abstract;
kono
parents:
diff changeset
196 end Is_Abstract;
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 -------------------
kono
parents:
diff changeset
199 -- Is_Primary_DT --
kono
parents:
diff changeset
200 -------------------
kono
parents:
diff changeset
201
kono
parents:
diff changeset
202 function Is_Primary_DT (T : Tag) return Boolean is
kono
parents:
diff changeset
203 begin
kono
parents:
diff changeset
204 return DT (T).Signature = Primary_DT;
kono
parents:
diff changeset
205 end Is_Primary_DT;
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 ---------
kono
parents:
diff changeset
208 -- OSD --
kono
parents:
diff changeset
209 ---------
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 function OSD (T : Tag) return Object_Specific_Data_Ptr is
kono
parents:
diff changeset
212 OSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
213 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
214 begin
kono
parents:
diff changeset
215 return To_Object_Specific_Data_Ptr (OSD_Ptr.all);
kono
parents:
diff changeset
216 end OSD;
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 ---------
kono
parents:
diff changeset
219 -- SSD --
kono
parents:
diff changeset
220 ---------
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 function SSD (T : Tag) return Select_Specific_Data_Ptr is
kono
parents:
diff changeset
223 TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
224 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
225 TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
226 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
227 begin
kono
parents:
diff changeset
228 return TSD.SSD;
kono
parents:
diff changeset
229 end SSD;
kono
parents:
diff changeset
230
kono
parents:
diff changeset
231 -------------------------
kono
parents:
diff changeset
232 -- External_Tag_HTable --
kono
parents:
diff changeset
233 -------------------------
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 type HTable_Headers is range 1 .. 64;
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 -- The following internal package defines the routines used for the
kono
parents:
diff changeset
238 -- instantiation of a new System.HTable.Static_HTable (see below). See
kono
parents:
diff changeset
239 -- spec in g-htable.ads for details of usage.
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 package HTable_Subprograms is
kono
parents:
diff changeset
242 procedure Set_HT_Link (T : Tag; Next : Tag);
kono
parents:
diff changeset
243 function Get_HT_Link (T : Tag) return Tag;
kono
parents:
diff changeset
244 function Hash (F : System.Address) return HTable_Headers;
kono
parents:
diff changeset
245 function Equal (A, B : System.Address) return Boolean;
kono
parents:
diff changeset
246 end HTable_Subprograms;
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 package External_Tag_HTable is new System.HTable.Static_HTable (
kono
parents:
diff changeset
249 Header_Num => HTable_Headers,
kono
parents:
diff changeset
250 Element => Dispatch_Table,
kono
parents:
diff changeset
251 Elmt_Ptr => Tag,
kono
parents:
diff changeset
252 Null_Ptr => null,
kono
parents:
diff changeset
253 Set_Next => HTable_Subprograms.Set_HT_Link,
kono
parents:
diff changeset
254 Next => HTable_Subprograms.Get_HT_Link,
kono
parents:
diff changeset
255 Key => System.Address,
kono
parents:
diff changeset
256 Get_Key => Get_External_Tag,
kono
parents:
diff changeset
257 Hash => HTable_Subprograms.Hash,
kono
parents:
diff changeset
258 Equal => HTable_Subprograms.Equal);
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 ------------------------
kono
parents:
diff changeset
261 -- HTable_Subprograms --
kono
parents:
diff changeset
262 ------------------------
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 -- Bodies of routines for hash table instantiation
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 package body HTable_Subprograms is
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 -----------
kono
parents:
diff changeset
269 -- Equal --
kono
parents:
diff changeset
270 -----------
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 function Equal (A, B : System.Address) return Boolean is
kono
parents:
diff changeset
273 Str1 : constant Cstring_Ptr := To_Cstring_Ptr (A);
kono
parents:
diff changeset
274 Str2 : constant Cstring_Ptr := To_Cstring_Ptr (B);
kono
parents:
diff changeset
275 J : Integer;
kono
parents:
diff changeset
276 begin
kono
parents:
diff changeset
277 J := 1;
kono
parents:
diff changeset
278 loop
kono
parents:
diff changeset
279 if Str1 (J) /= Str2 (J) then
kono
parents:
diff changeset
280 return False;
kono
parents:
diff changeset
281 elsif Str1 (J) = ASCII.NUL then
kono
parents:
diff changeset
282 return True;
kono
parents:
diff changeset
283 else
kono
parents:
diff changeset
284 J := J + 1;
kono
parents:
diff changeset
285 end if;
kono
parents:
diff changeset
286 end loop;
kono
parents:
diff changeset
287 end Equal;
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 -----------------
kono
parents:
diff changeset
290 -- Get_HT_Link --
kono
parents:
diff changeset
291 -----------------
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 function Get_HT_Link (T : Tag) return Tag is
kono
parents:
diff changeset
294 TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
295 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
296 TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
297 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
298 begin
kono
parents:
diff changeset
299 return TSD.HT_Link.all;
kono
parents:
diff changeset
300 end Get_HT_Link;
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 ----------
kono
parents:
diff changeset
303 -- Hash --
kono
parents:
diff changeset
304 ----------
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 function Hash (F : System.Address) return HTable_Headers is
kono
parents:
diff changeset
307 function H is new System.HTable.Hash (HTable_Headers);
kono
parents:
diff changeset
308 Str : constant Cstring_Ptr := To_Cstring_Ptr (F);
kono
parents:
diff changeset
309 Res : constant HTable_Headers := H (Str (1 .. Length (Str)));
kono
parents:
diff changeset
310 begin
kono
parents:
diff changeset
311 return Res;
kono
parents:
diff changeset
312 end Hash;
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 -----------------
kono
parents:
diff changeset
315 -- Set_HT_Link --
kono
parents:
diff changeset
316 -----------------
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 procedure Set_HT_Link (T : Tag; Next : Tag) is
kono
parents:
diff changeset
319 TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
320 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
321 TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
322 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
323 begin
kono
parents:
diff changeset
324 TSD.HT_Link.all := Next;
kono
parents:
diff changeset
325 end Set_HT_Link;
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327 end HTable_Subprograms;
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 ------------------
kono
parents:
diff changeset
330 -- Base_Address --
kono
parents:
diff changeset
331 ------------------
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 function Base_Address (This : System.Address) return System.Address is
kono
parents:
diff changeset
334 begin
kono
parents:
diff changeset
335 return This - Offset_To_Top (This);
kono
parents:
diff changeset
336 end Base_Address;
kono
parents:
diff changeset
337
kono
parents:
diff changeset
338 ---------------
kono
parents:
diff changeset
339 -- Check_TSD --
kono
parents:
diff changeset
340 ---------------
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 procedure Check_TSD (TSD : Type_Specific_Data_Ptr) is
kono
parents:
diff changeset
343 T : Tag;
kono
parents:
diff changeset
344
kono
parents:
diff changeset
345 E_Tag_Len : constant Integer := Length (TSD.External_Tag);
kono
parents:
diff changeset
346 E_Tag : String (1 .. E_Tag_Len);
kono
parents:
diff changeset
347 for E_Tag'Address use TSD.External_Tag.all'Address;
kono
parents:
diff changeset
348 pragma Import (Ada, E_Tag);
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 Dup_Ext_Tag : constant String := "duplicated external tag """;
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 begin
kono
parents:
diff changeset
353 -- Verify that the external tag of this TSD is not registered in the
kono
parents:
diff changeset
354 -- runtime hash table.
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356 T := External_Tag_HTable.Get (To_Address (TSD.External_Tag));
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 if T /= null then
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 -- Avoid concatenation, as it is not allowed in no run time mode
kono
parents:
diff changeset
361
kono
parents:
diff changeset
362 declare
kono
parents:
diff changeset
363 Msg : String (1 .. Dup_Ext_Tag'Length + E_Tag_Len + 1);
kono
parents:
diff changeset
364 begin
kono
parents:
diff changeset
365 Msg (1 .. Dup_Ext_Tag'Length) := Dup_Ext_Tag;
kono
parents:
diff changeset
366 Msg (Dup_Ext_Tag'Length + 1 .. Dup_Ext_Tag'Length + E_Tag_Len) :=
kono
parents:
diff changeset
367 E_Tag;
kono
parents:
diff changeset
368 Msg (Msg'Last) := '"';
kono
parents:
diff changeset
369 raise Program_Error with Msg;
kono
parents:
diff changeset
370 end;
kono
parents:
diff changeset
371 end if;
kono
parents:
diff changeset
372 end Check_TSD;
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 --------------------
kono
parents:
diff changeset
375 -- Descendant_Tag --
kono
parents:
diff changeset
376 --------------------
kono
parents:
diff changeset
377
kono
parents:
diff changeset
378 function Descendant_Tag (External : String; Ancestor : Tag) return Tag is
kono
parents:
diff changeset
379 Int_Tag : constant Tag := Internal_Tag (External);
kono
parents:
diff changeset
380 begin
kono
parents:
diff changeset
381 if not Is_Descendant_At_Same_Level (Int_Tag, Ancestor) then
kono
parents:
diff changeset
382 raise Tag_Error;
kono
parents:
diff changeset
383 else
kono
parents:
diff changeset
384 return Int_Tag;
kono
parents:
diff changeset
385 end if;
kono
parents:
diff changeset
386 end Descendant_Tag;
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 --------------
kono
parents:
diff changeset
389 -- Displace --
kono
parents:
diff changeset
390 --------------
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 function Displace (This : System.Address; T : Tag) return System.Address is
kono
parents:
diff changeset
393 Iface_Table : Interface_Data_Ptr;
kono
parents:
diff changeset
394 Obj_Base : System.Address;
kono
parents:
diff changeset
395 Obj_DT : Dispatch_Table_Ptr;
kono
parents:
diff changeset
396 Obj_DT_Tag : Tag;
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 begin
kono
parents:
diff changeset
399 if System."=" (This, System.Null_Address) then
kono
parents:
diff changeset
400 return System.Null_Address;
kono
parents:
diff changeset
401 end if;
kono
parents:
diff changeset
402
kono
parents:
diff changeset
403 Obj_Base := Base_Address (This);
kono
parents:
diff changeset
404 Obj_DT_Tag := To_Tag_Ptr (Obj_Base).all;
kono
parents:
diff changeset
405 Obj_DT := DT (To_Tag_Ptr (Obj_Base).all);
kono
parents:
diff changeset
406 Iface_Table := To_Type_Specific_Data_Ptr (Obj_DT.TSD).Interfaces_Table;
kono
parents:
diff changeset
407
kono
parents:
diff changeset
408 if Iface_Table /= null then
kono
parents:
diff changeset
409 for Id in 1 .. Iface_Table.Nb_Ifaces loop
kono
parents:
diff changeset
410 if Iface_Table.Ifaces_Table (Id).Iface_Tag = T then
kono
parents:
diff changeset
411
kono
parents:
diff changeset
412 -- Case of Static value of Offset_To_Top
kono
parents:
diff changeset
413
kono
parents:
diff changeset
414 if Iface_Table.Ifaces_Table (Id).Static_Offset_To_Top then
kono
parents:
diff changeset
415 Obj_Base := Obj_Base +
kono
parents:
diff changeset
416 Iface_Table.Ifaces_Table (Id).Offset_To_Top_Value;
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 -- Otherwise call the function generated by the expander to
kono
parents:
diff changeset
419 -- provide the value.
kono
parents:
diff changeset
420
kono
parents:
diff changeset
421 else
kono
parents:
diff changeset
422 Obj_Base := Obj_Base +
kono
parents:
diff changeset
423 Iface_Table.Ifaces_Table (Id).Offset_To_Top_Func.all
kono
parents:
diff changeset
424 (Obj_Base);
kono
parents:
diff changeset
425 end if;
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 return Obj_Base;
kono
parents:
diff changeset
428 end if;
kono
parents:
diff changeset
429 end loop;
kono
parents:
diff changeset
430 end if;
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 -- Check if T is an immediate ancestor. This is required to handle
kono
parents:
diff changeset
433 -- conversion of class-wide interfaces to tagged types.
kono
parents:
diff changeset
434
kono
parents:
diff changeset
435 if CW_Membership (Obj_DT_Tag, T) then
kono
parents:
diff changeset
436 return Obj_Base;
kono
parents:
diff changeset
437 end if;
kono
parents:
diff changeset
438
kono
parents:
diff changeset
439 -- If the object does not implement the interface we must raise CE
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 raise Constraint_Error with "invalid interface conversion";
kono
parents:
diff changeset
442 end Displace;
kono
parents:
diff changeset
443
kono
parents:
diff changeset
444 --------
kono
parents:
diff changeset
445 -- DT --
kono
parents:
diff changeset
446 --------
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 function DT (T : Tag) return Dispatch_Table_Ptr is
kono
parents:
diff changeset
449 Offset : constant SSE.Storage_Offset :=
kono
parents:
diff changeset
450 To_Dispatch_Table_Ptr (T).Prims_Ptr'Position;
kono
parents:
diff changeset
451 begin
kono
parents:
diff changeset
452 return To_Dispatch_Table_Ptr (To_Address (T) - Offset);
kono
parents:
diff changeset
453 end DT;
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 -------------------
kono
parents:
diff changeset
456 -- IW_Membership --
kono
parents:
diff changeset
457 -------------------
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 function IW_Membership
kono
parents:
diff changeset
460 (Descendant_TSD : Type_Specific_Data_Ptr;
kono
parents:
diff changeset
461 T : Tag) return Boolean
kono
parents:
diff changeset
462 is
kono
parents:
diff changeset
463 Iface_Table : Interface_Data_Ptr;
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 begin
kono
parents:
diff changeset
466 Iface_Table := Descendant_TSD.Interfaces_Table;
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 if Iface_Table /= null then
kono
parents:
diff changeset
469 for Id in 1 .. Iface_Table.Nb_Ifaces loop
kono
parents:
diff changeset
470 if Iface_Table.Ifaces_Table (Id).Iface_Tag = T then
kono
parents:
diff changeset
471 return True;
kono
parents:
diff changeset
472 end if;
kono
parents:
diff changeset
473 end loop;
kono
parents:
diff changeset
474 end if;
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 -- Look for the tag in the ancestor tags table. This is required for:
kono
parents:
diff changeset
477 -- Iface_CW in Typ'Class
kono
parents:
diff changeset
478
kono
parents:
diff changeset
479 for Id in 0 .. Descendant_TSD.Idepth loop
kono
parents:
diff changeset
480 if Descendant_TSD.Tags_Table (Id) = T then
kono
parents:
diff changeset
481 return True;
kono
parents:
diff changeset
482 end if;
kono
parents:
diff changeset
483 end loop;
kono
parents:
diff changeset
484
kono
parents:
diff changeset
485 return False;
kono
parents:
diff changeset
486 end IW_Membership;
kono
parents:
diff changeset
487
kono
parents:
diff changeset
488 -------------------
kono
parents:
diff changeset
489 -- IW_Membership --
kono
parents:
diff changeset
490 -------------------
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 -- Canonical implementation of Classwide Membership corresponding to:
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 -- Obj in Iface'Class
kono
parents:
diff changeset
495
kono
parents:
diff changeset
496 -- Each dispatch table contains a table with the tags of all the
kono
parents:
diff changeset
497 -- implemented interfaces.
kono
parents:
diff changeset
498
kono
parents:
diff changeset
499 -- Obj is in Iface'Class if Iface'Tag is found in the table of interfaces
kono
parents:
diff changeset
500 -- that are contained in the dispatch table referenced by Obj'Tag.
kono
parents:
diff changeset
501
kono
parents:
diff changeset
502 function IW_Membership (This : System.Address; T : Tag) return Boolean is
kono
parents:
diff changeset
503 Obj_Base : System.Address;
kono
parents:
diff changeset
504 Obj_DT : Dispatch_Table_Ptr;
kono
parents:
diff changeset
505 Obj_TSD : Type_Specific_Data_Ptr;
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 begin
kono
parents:
diff changeset
508 Obj_Base := Base_Address (This);
kono
parents:
diff changeset
509 Obj_DT := DT (To_Tag_Ptr (Obj_Base).all);
kono
parents:
diff changeset
510 Obj_TSD := To_Type_Specific_Data_Ptr (Obj_DT.TSD);
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 return IW_Membership (Obj_TSD, T);
kono
parents:
diff changeset
513 end IW_Membership;
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515 -------------------
kono
parents:
diff changeset
516 -- Expanded_Name --
kono
parents:
diff changeset
517 -------------------
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 function Expanded_Name (T : Tag) return String is
kono
parents:
diff changeset
520 Result : Cstring_Ptr;
kono
parents:
diff changeset
521 TSD_Ptr : Addr_Ptr;
kono
parents:
diff changeset
522 TSD : Type_Specific_Data_Ptr;
kono
parents:
diff changeset
523
kono
parents:
diff changeset
524 begin
kono
parents:
diff changeset
525 if T = No_Tag then
kono
parents:
diff changeset
526 raise Tag_Error;
kono
parents:
diff changeset
527 end if;
kono
parents:
diff changeset
528
kono
parents:
diff changeset
529 TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
530 TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
531 Result := TSD.Expanded_Name;
kono
parents:
diff changeset
532 return Result (1 .. Length (Result));
kono
parents:
diff changeset
533 end Expanded_Name;
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 ------------------
kono
parents:
diff changeset
536 -- External_Tag --
kono
parents:
diff changeset
537 ------------------
kono
parents:
diff changeset
538
kono
parents:
diff changeset
539 function External_Tag (T : Tag) return String is
kono
parents:
diff changeset
540 Result : Cstring_Ptr;
kono
parents:
diff changeset
541 TSD_Ptr : Addr_Ptr;
kono
parents:
diff changeset
542 TSD : Type_Specific_Data_Ptr;
kono
parents:
diff changeset
543
kono
parents:
diff changeset
544 begin
kono
parents:
diff changeset
545 if T = No_Tag then
kono
parents:
diff changeset
546 raise Tag_Error;
kono
parents:
diff changeset
547 end if;
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
550 TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
551 Result := TSD.External_Tag;
kono
parents:
diff changeset
552 return Result (1 .. Length (Result));
kono
parents:
diff changeset
553 end External_Tag;
kono
parents:
diff changeset
554
kono
parents:
diff changeset
555 ---------------------
kono
parents:
diff changeset
556 -- Get_Entry_Index --
kono
parents:
diff changeset
557 ---------------------
kono
parents:
diff changeset
558
kono
parents:
diff changeset
559 function Get_Entry_Index (T : Tag; Position : Positive) return Positive is
kono
parents:
diff changeset
560 begin
kono
parents:
diff changeset
561 return SSD (T).SSD_Table (Position).Index;
kono
parents:
diff changeset
562 end Get_Entry_Index;
kono
parents:
diff changeset
563
kono
parents:
diff changeset
564 ----------------------
kono
parents:
diff changeset
565 -- Get_Prim_Op_Kind --
kono
parents:
diff changeset
566 ----------------------
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 function Get_Prim_Op_Kind
kono
parents:
diff changeset
569 (T : Tag;
kono
parents:
diff changeset
570 Position : Positive) return Prim_Op_Kind
kono
parents:
diff changeset
571 is
kono
parents:
diff changeset
572 begin
kono
parents:
diff changeset
573 return SSD (T).SSD_Table (Position).Kind;
kono
parents:
diff changeset
574 end Get_Prim_Op_Kind;
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 ----------------------
kono
parents:
diff changeset
577 -- Get_Offset_Index --
kono
parents:
diff changeset
578 ----------------------
kono
parents:
diff changeset
579
kono
parents:
diff changeset
580 function Get_Offset_Index
kono
parents:
diff changeset
581 (T : Tag;
kono
parents:
diff changeset
582 Position : Positive) return Positive
kono
parents:
diff changeset
583 is
kono
parents:
diff changeset
584 begin
kono
parents:
diff changeset
585 if Is_Primary_DT (T) then
kono
parents:
diff changeset
586 return Position;
kono
parents:
diff changeset
587 else
kono
parents:
diff changeset
588 return OSD (T).OSD_Table (Position);
kono
parents:
diff changeset
589 end if;
kono
parents:
diff changeset
590 end Get_Offset_Index;
kono
parents:
diff changeset
591
kono
parents:
diff changeset
592 ---------------------
kono
parents:
diff changeset
593 -- Get_Tagged_Kind --
kono
parents:
diff changeset
594 ---------------------
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 function Get_Tagged_Kind (T : Tag) return Tagged_Kind is
kono
parents:
diff changeset
597 begin
kono
parents:
diff changeset
598 return DT (T).Tag_Kind;
kono
parents:
diff changeset
599 end Get_Tagged_Kind;
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 -----------------------------
kono
parents:
diff changeset
602 -- Interface_Ancestor_Tags --
kono
parents:
diff changeset
603 -----------------------------
kono
parents:
diff changeset
604
kono
parents:
diff changeset
605 function Interface_Ancestor_Tags (T : Tag) return Tag_Array is
kono
parents:
diff changeset
606 TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
607 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
608 TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
609 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
610 Iface_Table : constant Interface_Data_Ptr := TSD.Interfaces_Table;
kono
parents:
diff changeset
611
kono
parents:
diff changeset
612 begin
kono
parents:
diff changeset
613 if Iface_Table = null then
kono
parents:
diff changeset
614 declare
kono
parents:
diff changeset
615 Table : Tag_Array (1 .. 0);
kono
parents:
diff changeset
616 begin
kono
parents:
diff changeset
617 return Table;
kono
parents:
diff changeset
618 end;
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 else
kono
parents:
diff changeset
621 declare
kono
parents:
diff changeset
622 Table : Tag_Array (1 .. Iface_Table.Nb_Ifaces);
kono
parents:
diff changeset
623 begin
kono
parents:
diff changeset
624 for J in 1 .. Iface_Table.Nb_Ifaces loop
kono
parents:
diff changeset
625 Table (J) := Iface_Table.Ifaces_Table (J).Iface_Tag;
kono
parents:
diff changeset
626 end loop;
kono
parents:
diff changeset
627
kono
parents:
diff changeset
628 return Table;
kono
parents:
diff changeset
629 end;
kono
parents:
diff changeset
630 end if;
kono
parents:
diff changeset
631 end Interface_Ancestor_Tags;
kono
parents:
diff changeset
632
kono
parents:
diff changeset
633 ------------------
kono
parents:
diff changeset
634 -- Internal_Tag --
kono
parents:
diff changeset
635 ------------------
kono
parents:
diff changeset
636
kono
parents:
diff changeset
637 -- Internal tags have the following format:
kono
parents:
diff changeset
638 -- "Internal tag at 16#ADDRESS#: <full-name-of-tagged-type>"
kono
parents:
diff changeset
639
kono
parents:
diff changeset
640 Internal_Tag_Header : constant String := "Internal tag at ";
kono
parents:
diff changeset
641 Header_Separator : constant Character := '#';
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 function Internal_Tag (External : String) return Tag is
kono
parents:
diff changeset
644 pragma Unsuppress (All_Checks);
kono
parents:
diff changeset
645 -- To make T'Class'Input robust in the case of bad data
kono
parents:
diff changeset
646
kono
parents:
diff changeset
647 Res : Tag := null;
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 begin
kono
parents:
diff changeset
650 -- Raise Tag_Error for empty strings and very long strings. This makes
kono
parents:
diff changeset
651 -- T'Class'Input robust in the case of bad data, for example
kono
parents:
diff changeset
652 --
kono
parents:
diff changeset
653 -- String (123456789..1234)
kono
parents:
diff changeset
654 --
kono
parents:
diff changeset
655 -- The limit of 10,000 characters is arbitrary, but is unlikely to be
kono
parents:
diff changeset
656 -- exceeded by legitimate external tag names.
kono
parents:
diff changeset
657
kono
parents:
diff changeset
658 if External'Length not in 1 .. 10_000 then
kono
parents:
diff changeset
659 raise Tag_Error;
kono
parents:
diff changeset
660 end if;
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 -- Handle locally defined tagged types
kono
parents:
diff changeset
663
kono
parents:
diff changeset
664 if External'Length > Internal_Tag_Header'Length
kono
parents:
diff changeset
665 and then
kono
parents:
diff changeset
666 External (External'First ..
kono
parents:
diff changeset
667 External'First + Internal_Tag_Header'Length - 1) =
kono
parents:
diff changeset
668 Internal_Tag_Header
kono
parents:
diff changeset
669 then
kono
parents:
diff changeset
670 declare
kono
parents:
diff changeset
671 Addr_First : constant Natural :=
kono
parents:
diff changeset
672 External'First + Internal_Tag_Header'Length;
kono
parents:
diff changeset
673 Addr_Last : Natural;
kono
parents:
diff changeset
674 Addr : Integer_Address;
kono
parents:
diff changeset
675
kono
parents:
diff changeset
676 begin
kono
parents:
diff changeset
677 -- Search the second separator (#) to identify the address
kono
parents:
diff changeset
678
kono
parents:
diff changeset
679 Addr_Last := Addr_First;
kono
parents:
diff changeset
680
kono
parents:
diff changeset
681 for J in 1 .. 2 loop
kono
parents:
diff changeset
682 while Addr_Last <= External'Last
kono
parents:
diff changeset
683 and then External (Addr_Last) /= Header_Separator
kono
parents:
diff changeset
684 loop
kono
parents:
diff changeset
685 Addr_Last := Addr_Last + 1;
kono
parents:
diff changeset
686 end loop;
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 -- Skip the first separator
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 if J = 1 then
kono
parents:
diff changeset
691 Addr_Last := Addr_Last + 1;
kono
parents:
diff changeset
692 end if;
kono
parents:
diff changeset
693 end loop;
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 if Addr_Last <= External'Last then
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 -- Protect the run-time against wrong internal tags. We
kono
parents:
diff changeset
698 -- cannot use exception handlers here because it would
kono
parents:
diff changeset
699 -- disable the use of this run-time compiling with
kono
parents:
diff changeset
700 -- restriction No_Exception_Handler.
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 declare
kono
parents:
diff changeset
703 C : Character;
kono
parents:
diff changeset
704 Wrong_Tag : Boolean := False;
kono
parents:
diff changeset
705
kono
parents:
diff changeset
706 begin
kono
parents:
diff changeset
707 if External (Addr_First) /= '1'
kono
parents:
diff changeset
708 or else External (Addr_First + 1) /= '6'
kono
parents:
diff changeset
709 or else External (Addr_First + 2) /= '#'
kono
parents:
diff changeset
710 then
kono
parents:
diff changeset
711 Wrong_Tag := True;
kono
parents:
diff changeset
712
kono
parents:
diff changeset
713 else
kono
parents:
diff changeset
714 for J in Addr_First + 3 .. Addr_Last - 1 loop
kono
parents:
diff changeset
715 C := External (J);
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 if not (C in '0' .. '9')
kono
parents:
diff changeset
718 and then not (C in 'A' .. 'F')
kono
parents:
diff changeset
719 and then not (C in 'a' .. 'f')
kono
parents:
diff changeset
720 then
kono
parents:
diff changeset
721 Wrong_Tag := True;
kono
parents:
diff changeset
722 exit;
kono
parents:
diff changeset
723 end if;
kono
parents:
diff changeset
724 end loop;
kono
parents:
diff changeset
725 end if;
kono
parents:
diff changeset
726
kono
parents:
diff changeset
727 -- Convert the numeric value into a tag
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 if not Wrong_Tag then
kono
parents:
diff changeset
730 Addr := Integer_Address'Value
kono
parents:
diff changeset
731 (External (Addr_First .. Addr_Last));
kono
parents:
diff changeset
732
kono
parents:
diff changeset
733 -- Internal tags never have value 0
kono
parents:
diff changeset
734
kono
parents:
diff changeset
735 if Addr /= 0 then
kono
parents:
diff changeset
736 return To_Tag (Addr);
kono
parents:
diff changeset
737 end if;
kono
parents:
diff changeset
738 end if;
kono
parents:
diff changeset
739 end;
kono
parents:
diff changeset
740 end if;
kono
parents:
diff changeset
741 end;
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743 -- Handle library-level tagged types
kono
parents:
diff changeset
744
kono
parents:
diff changeset
745 else
kono
parents:
diff changeset
746 -- Make NUL-terminated copy of external tag string
kono
parents:
diff changeset
747
kono
parents:
diff changeset
748 declare
kono
parents:
diff changeset
749 Ext_Copy : aliased String (External'First .. External'Last + 1);
kono
parents:
diff changeset
750 pragma Assert (Ext_Copy'Length > 1); -- See Length check at top
kono
parents:
diff changeset
751 begin
kono
parents:
diff changeset
752 Ext_Copy (External'Range) := External;
kono
parents:
diff changeset
753 Ext_Copy (Ext_Copy'Last) := ASCII.NUL;
kono
parents:
diff changeset
754 Res := External_Tag_HTable.Get (Ext_Copy'Address);
kono
parents:
diff changeset
755 end;
kono
parents:
diff changeset
756 end if;
kono
parents:
diff changeset
757
kono
parents:
diff changeset
758 if Res = null then
kono
parents:
diff changeset
759 declare
kono
parents:
diff changeset
760 Msg1 : constant String := "unknown tagged type: ";
kono
parents:
diff changeset
761 Msg2 : String (1 .. Msg1'Length + External'Length);
kono
parents:
diff changeset
762
kono
parents:
diff changeset
763 begin
kono
parents:
diff changeset
764 Msg2 (1 .. Msg1'Length) := Msg1;
kono
parents:
diff changeset
765 Msg2 (Msg1'Length + 1 .. Msg1'Length + External'Length) :=
kono
parents:
diff changeset
766 External;
kono
parents:
diff changeset
767 Ada.Exceptions.Raise_Exception (Tag_Error'Identity, Msg2);
kono
parents:
diff changeset
768 end;
kono
parents:
diff changeset
769 end if;
kono
parents:
diff changeset
770
kono
parents:
diff changeset
771 return Res;
kono
parents:
diff changeset
772 end Internal_Tag;
kono
parents:
diff changeset
773
kono
parents:
diff changeset
774 ---------------------------------
kono
parents:
diff changeset
775 -- Is_Descendant_At_Same_Level --
kono
parents:
diff changeset
776 ---------------------------------
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 function Is_Descendant_At_Same_Level
kono
parents:
diff changeset
779 (Descendant : Tag;
kono
parents:
diff changeset
780 Ancestor : Tag) return Boolean
kono
parents:
diff changeset
781 is
kono
parents:
diff changeset
782 begin
kono
parents:
diff changeset
783 if Descendant = Ancestor then
kono
parents:
diff changeset
784 return True;
kono
parents:
diff changeset
785
kono
parents:
diff changeset
786 else
kono
parents:
diff changeset
787 declare
kono
parents:
diff changeset
788 D_TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
789 To_Addr_Ptr (To_Address (Descendant) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
790 A_TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
791 To_Addr_Ptr (To_Address (Ancestor) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
792 D_TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
793 To_Type_Specific_Data_Ptr (D_TSD_Ptr.all);
kono
parents:
diff changeset
794 A_TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
795 To_Type_Specific_Data_Ptr (A_TSD_Ptr.all);
kono
parents:
diff changeset
796 begin
kono
parents:
diff changeset
797 return
kono
parents:
diff changeset
798 D_TSD.Access_Level = A_TSD.Access_Level
kono
parents:
diff changeset
799 and then (CW_Membership (Descendant, Ancestor)
kono
parents:
diff changeset
800 or else IW_Membership (D_TSD, Ancestor));
kono
parents:
diff changeset
801 end;
kono
parents:
diff changeset
802 end if;
kono
parents:
diff changeset
803 end Is_Descendant_At_Same_Level;
kono
parents:
diff changeset
804
kono
parents:
diff changeset
805 ------------
kono
parents:
diff changeset
806 -- Length --
kono
parents:
diff changeset
807 ------------
kono
parents:
diff changeset
808
kono
parents:
diff changeset
809 -- Note: This unit is used in the Ravenscar runtime library, so it cannot
kono
parents:
diff changeset
810 -- depend on System.CTRL. Furthermore, this happens on CPUs where the GCC
kono
parents:
diff changeset
811 -- intrinsic strlen may not be available, so we need to recode our own Ada
kono
parents:
diff changeset
812 -- version here.
kono
parents:
diff changeset
813
kono
parents:
diff changeset
814 function Length (Str : Cstring_Ptr) return Natural is
kono
parents:
diff changeset
815 Len : Integer;
kono
parents:
diff changeset
816
kono
parents:
diff changeset
817 begin
kono
parents:
diff changeset
818 Len := 1;
kono
parents:
diff changeset
819 while Str (Len) /= ASCII.NUL loop
kono
parents:
diff changeset
820 Len := Len + 1;
kono
parents:
diff changeset
821 end loop;
kono
parents:
diff changeset
822
kono
parents:
diff changeset
823 return Len - 1;
kono
parents:
diff changeset
824 end Length;
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 -------------------
kono
parents:
diff changeset
827 -- Offset_To_Top --
kono
parents:
diff changeset
828 -------------------
kono
parents:
diff changeset
829
kono
parents:
diff changeset
830 function Offset_To_Top
kono
parents:
diff changeset
831 (This : System.Address) return SSE.Storage_Offset
kono
parents:
diff changeset
832 is
kono
parents:
diff changeset
833 Tag_Size : constant SSE.Storage_Count :=
kono
parents:
diff changeset
834 SSE.Storage_Count (1 * (Standard'Address_Size / System.Storage_Unit));
kono
parents:
diff changeset
835
kono
parents:
diff changeset
836 type Storage_Offset_Ptr is access SSE.Storage_Offset;
kono
parents:
diff changeset
837 function To_Storage_Offset_Ptr is
kono
parents:
diff changeset
838 new Unchecked_Conversion (System.Address, Storage_Offset_Ptr);
kono
parents:
diff changeset
839
kono
parents:
diff changeset
840 Curr_DT : Dispatch_Table_Ptr;
kono
parents:
diff changeset
841
kono
parents:
diff changeset
842 begin
kono
parents:
diff changeset
843 Curr_DT := DT (To_Tag_Ptr (This).all);
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 -- See the documentation of Dispatch_Table_Wrapper.Offset_To_Top
kono
parents:
diff changeset
846
kono
parents:
diff changeset
847 if Curr_DT.Offset_To_Top = SSE.Storage_Offset'Last then
kono
parents:
diff changeset
848
kono
parents:
diff changeset
849 -- The parent record type has variable-size components, so the
kono
parents:
diff changeset
850 -- instance-specific offset is stored in the tagged record, right
kono
parents:
diff changeset
851 -- after the reference to Curr_DT (which is a secondary dispatch
kono
parents:
diff changeset
852 -- table).
kono
parents:
diff changeset
853
kono
parents:
diff changeset
854 return To_Storage_Offset_Ptr (This + Tag_Size).all;
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 else
kono
parents:
diff changeset
857 -- The offset is compile-time known, so it is simply stored in the
kono
parents:
diff changeset
858 -- Offset_To_Top field.
kono
parents:
diff changeset
859
kono
parents:
diff changeset
860 return Curr_DT.Offset_To_Top;
kono
parents:
diff changeset
861 end if;
kono
parents:
diff changeset
862 end Offset_To_Top;
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 ------------------------
kono
parents:
diff changeset
865 -- Needs_Finalization --
kono
parents:
diff changeset
866 ------------------------
kono
parents:
diff changeset
867
kono
parents:
diff changeset
868 function Needs_Finalization (T : Tag) return Boolean is
kono
parents:
diff changeset
869 TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
870 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
871 TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
872 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
873 begin
kono
parents:
diff changeset
874 return TSD.Needs_Finalization;
kono
parents:
diff changeset
875 end Needs_Finalization;
kono
parents:
diff changeset
876
kono
parents:
diff changeset
877 -----------------
kono
parents:
diff changeset
878 -- Parent_Size --
kono
parents:
diff changeset
879 -----------------
kono
parents:
diff changeset
880
kono
parents:
diff changeset
881 function Parent_Size
kono
parents:
diff changeset
882 (Obj : System.Address;
kono
parents:
diff changeset
883 T : Tag) return SSE.Storage_Count
kono
parents:
diff changeset
884 is
kono
parents:
diff changeset
885 Parent_Slot : constant Positive := 1;
kono
parents:
diff changeset
886 -- The tag of the parent is always in the first slot of the table of
kono
parents:
diff changeset
887 -- ancestor tags.
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
890 To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
891 TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
892 To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
893 -- Pointer to the TSD
kono
parents:
diff changeset
894
kono
parents:
diff changeset
895 Parent_Tag : constant Tag := TSD.Tags_Table (Parent_Slot);
kono
parents:
diff changeset
896 Parent_TSD_Ptr : constant Addr_Ptr :=
kono
parents:
diff changeset
897 To_Addr_Ptr (To_Address (Parent_Tag) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
898 Parent_TSD : constant Type_Specific_Data_Ptr :=
kono
parents:
diff changeset
899 To_Type_Specific_Data_Ptr (Parent_TSD_Ptr.all);
kono
parents:
diff changeset
900
kono
parents:
diff changeset
901 begin
kono
parents:
diff changeset
902 -- Here we compute the size of the _parent field of the object
kono
parents:
diff changeset
903
kono
parents:
diff changeset
904 return SSE.Storage_Count (Parent_TSD.Size_Func.all (Obj));
kono
parents:
diff changeset
905 end Parent_Size;
kono
parents:
diff changeset
906
kono
parents:
diff changeset
907 ----------------
kono
parents:
diff changeset
908 -- Parent_Tag --
kono
parents:
diff changeset
909 ----------------
kono
parents:
diff changeset
910
kono
parents:
diff changeset
911 function Parent_Tag (T : Tag) return Tag is
kono
parents:
diff changeset
912 TSD_Ptr : Addr_Ptr;
kono
parents:
diff changeset
913 TSD : Type_Specific_Data_Ptr;
kono
parents:
diff changeset
914
kono
parents:
diff changeset
915 begin
kono
parents:
diff changeset
916 if T = No_Tag then
kono
parents:
diff changeset
917 raise Tag_Error;
kono
parents:
diff changeset
918 end if;
kono
parents:
diff changeset
919
kono
parents:
diff changeset
920 TSD_Ptr := To_Addr_Ptr (To_Address (T) - DT_Typeinfo_Ptr_Size);
kono
parents:
diff changeset
921 TSD := To_Type_Specific_Data_Ptr (TSD_Ptr.all);
kono
parents:
diff changeset
922
kono
parents:
diff changeset
923 -- The Parent_Tag of a root-level tagged type is defined to be No_Tag.
kono
parents:
diff changeset
924 -- The first entry in the Ancestors_Tags array will be null for such
kono
parents:
diff changeset
925 -- a type, but it's better to be explicit about returning No_Tag in
kono
parents:
diff changeset
926 -- this case.
kono
parents:
diff changeset
927
kono
parents:
diff changeset
928 if TSD.Idepth = 0 then
kono
parents:
diff changeset
929 return No_Tag;
kono
parents:
diff changeset
930 else
kono
parents:
diff changeset
931 return TSD.Tags_Table (1);
kono
parents:
diff changeset
932 end if;
kono
parents:
diff changeset
933 end Parent_Tag;
kono
parents:
diff changeset
934
kono
parents:
diff changeset
935 -------------------------------
kono
parents:
diff changeset
936 -- Register_Interface_Offset --
kono
parents:
diff changeset
937 -------------------------------
kono
parents:
diff changeset
938
kono
parents:
diff changeset
939 procedure Register_Interface_Offset
kono
parents:
diff changeset
940 (Prim_T : Tag;
kono
parents:
diff changeset
941 Interface_T : Tag;
kono
parents:
diff changeset
942 Is_Static : Boolean;
kono
parents:
diff changeset
943 Offset_Value : SSE.Storage_Offset;
kono
parents:
diff changeset
944 Offset_Func : Offset_To_Top_Function_Ptr)
kono
parents:
diff changeset
945 is
kono
parents:
diff changeset
946 Prim_DT : constant Dispatch_Table_Ptr := DT (Prim_T);
kono
parents:
diff changeset
947 Iface_Table : constant Interface_Data_Ptr :=
kono
parents:
diff changeset
948 To_Type_Specific_Data_Ptr (Prim_DT.TSD).Interfaces_Table;
kono
parents:
diff changeset
949
kono
parents:
diff changeset
950 begin
kono
parents:
diff changeset
951 -- Save Offset_Value in the table of interfaces of the primary DT.
kono
parents:
diff changeset
952 -- This data will be used by the subprogram "Displace" to give support
kono
parents:
diff changeset
953 -- to backward abstract interface type conversions.
kono
parents:
diff changeset
954
kono
parents:
diff changeset
955 -- Register the offset in the table of interfaces
kono
parents:
diff changeset
956
kono
parents:
diff changeset
957 if Iface_Table /= null then
kono
parents:
diff changeset
958 for Id in 1 .. Iface_Table.Nb_Ifaces loop
kono
parents:
diff changeset
959 if Iface_Table.Ifaces_Table (Id).Iface_Tag = Interface_T then
kono
parents:
diff changeset
960 if Is_Static or else Offset_Value = 0 then
kono
parents:
diff changeset
961 Iface_Table.Ifaces_Table (Id).Static_Offset_To_Top := True;
kono
parents:
diff changeset
962 Iface_Table.Ifaces_Table (Id).Offset_To_Top_Value :=
kono
parents:
diff changeset
963 Offset_Value;
kono
parents:
diff changeset
964 else
kono
parents:
diff changeset
965 Iface_Table.Ifaces_Table (Id).Static_Offset_To_Top := False;
kono
parents:
diff changeset
966 Iface_Table.Ifaces_Table (Id).Offset_To_Top_Func :=
kono
parents:
diff changeset
967 Offset_Func;
kono
parents:
diff changeset
968 end if;
kono
parents:
diff changeset
969
kono
parents:
diff changeset
970 return;
kono
parents:
diff changeset
971 end if;
kono
parents:
diff changeset
972 end loop;
kono
parents:
diff changeset
973 end if;
kono
parents:
diff changeset
974
kono
parents:
diff changeset
975 -- If we arrive here there is some error in the run-time data structure
kono
parents:
diff changeset
976
kono
parents:
diff changeset
977 raise Program_Error;
kono
parents:
diff changeset
978 end Register_Interface_Offset;
kono
parents:
diff changeset
979
kono
parents:
diff changeset
980 ------------------
kono
parents:
diff changeset
981 -- Register_Tag --
kono
parents:
diff changeset
982 ------------------
kono
parents:
diff changeset
983
kono
parents:
diff changeset
984 procedure Register_Tag (T : Tag) is
kono
parents:
diff changeset
985 begin
kono
parents:
diff changeset
986 External_Tag_HTable.Set (T);
kono
parents:
diff changeset
987 end Register_Tag;
kono
parents:
diff changeset
988
kono
parents:
diff changeset
989 -------------------
kono
parents:
diff changeset
990 -- Secondary_Tag --
kono
parents:
diff changeset
991 -------------------
kono
parents:
diff changeset
992
kono
parents:
diff changeset
993 function Secondary_Tag (T, Iface : Tag) return Tag is
kono
parents:
diff changeset
994 Iface_Table : Interface_Data_Ptr;
kono
parents:
diff changeset
995 Obj_DT : Dispatch_Table_Ptr;
kono
parents:
diff changeset
996
kono
parents:
diff changeset
997 begin
kono
parents:
diff changeset
998 if not Is_Primary_DT (T) then
kono
parents:
diff changeset
999 raise Program_Error;
kono
parents:
diff changeset
1000 end if;
kono
parents:
diff changeset
1001
kono
parents:
diff changeset
1002 Obj_DT := DT (T);
kono
parents:
diff changeset
1003 Iface_Table := To_Type_Specific_Data_Ptr (Obj_DT.TSD).Interfaces_Table;
kono
parents:
diff changeset
1004
kono
parents:
diff changeset
1005 if Iface_Table /= null then
kono
parents:
diff changeset
1006 for Id in 1 .. Iface_Table.Nb_Ifaces loop
kono
parents:
diff changeset
1007 if Iface_Table.Ifaces_Table (Id).Iface_Tag = Iface then
kono
parents:
diff changeset
1008 return Iface_Table.Ifaces_Table (Id).Secondary_DT;
kono
parents:
diff changeset
1009 end if;
kono
parents:
diff changeset
1010 end loop;
kono
parents:
diff changeset
1011 end if;
kono
parents:
diff changeset
1012
kono
parents:
diff changeset
1013 -- If the object does not implement the interface we must raise CE
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 raise Constraint_Error with "invalid interface conversion";
kono
parents:
diff changeset
1016 end Secondary_Tag;
kono
parents:
diff changeset
1017
kono
parents:
diff changeset
1018 ---------------------
kono
parents:
diff changeset
1019 -- Set_Entry_Index --
kono
parents:
diff changeset
1020 ---------------------
kono
parents:
diff changeset
1021
kono
parents:
diff changeset
1022 procedure Set_Entry_Index
kono
parents:
diff changeset
1023 (T : Tag;
kono
parents:
diff changeset
1024 Position : Positive;
kono
parents:
diff changeset
1025 Value : Positive)
kono
parents:
diff changeset
1026 is
kono
parents:
diff changeset
1027 begin
kono
parents:
diff changeset
1028 SSD (T).SSD_Table (Position).Index := Value;
kono
parents:
diff changeset
1029 end Set_Entry_Index;
kono
parents:
diff changeset
1030
kono
parents:
diff changeset
1031 -----------------------
kono
parents:
diff changeset
1032 -- Set_Offset_To_Top --
kono
parents:
diff changeset
1033 -----------------------
kono
parents:
diff changeset
1034
kono
parents:
diff changeset
1035 procedure Set_Dynamic_Offset_To_Top
kono
parents:
diff changeset
1036 (This : System.Address;
kono
parents:
diff changeset
1037 Prim_T : Tag;
kono
parents:
diff changeset
1038 Interface_T : Tag;
kono
parents:
diff changeset
1039 Offset_Value : SSE.Storage_Offset;
kono
parents:
diff changeset
1040 Offset_Func : Offset_To_Top_Function_Ptr)
kono
parents:
diff changeset
1041 is
kono
parents:
diff changeset
1042 Sec_Base : System.Address;
kono
parents:
diff changeset
1043 Sec_DT : Dispatch_Table_Ptr;
kono
parents:
diff changeset
1044
kono
parents:
diff changeset
1045 begin
kono
parents:
diff changeset
1046 -- Save the offset to top field in the secondary dispatch table
kono
parents:
diff changeset
1047
kono
parents:
diff changeset
1048 if Offset_Value /= 0 then
kono
parents:
diff changeset
1049 Sec_Base := This + Offset_Value;
kono
parents:
diff changeset
1050 Sec_DT := DT (To_Tag_Ptr (Sec_Base).all);
kono
parents:
diff changeset
1051 Sec_DT.Offset_To_Top := SSE.Storage_Offset'Last;
kono
parents:
diff changeset
1052 end if;
kono
parents:
diff changeset
1053
kono
parents:
diff changeset
1054 Register_Interface_Offset
kono
parents:
diff changeset
1055 (Prim_T, Interface_T, False, Offset_Value, Offset_Func);
kono
parents:
diff changeset
1056 end Set_Dynamic_Offset_To_Top;
kono
parents:
diff changeset
1057
kono
parents:
diff changeset
1058 ----------------------
kono
parents:
diff changeset
1059 -- Set_Prim_Op_Kind --
kono
parents:
diff changeset
1060 ----------------------
kono
parents:
diff changeset
1061
kono
parents:
diff changeset
1062 procedure Set_Prim_Op_Kind
kono
parents:
diff changeset
1063 (T : Tag;
kono
parents:
diff changeset
1064 Position : Positive;
kono
parents:
diff changeset
1065 Value : Prim_Op_Kind)
kono
parents:
diff changeset
1066 is
kono
parents:
diff changeset
1067 begin
kono
parents:
diff changeset
1068 SSD (T).SSD_Table (Position).Kind := Value;
kono
parents:
diff changeset
1069 end Set_Prim_Op_Kind;
kono
parents:
diff changeset
1070
kono
parents:
diff changeset
1071 --------------------
kono
parents:
diff changeset
1072 -- Unregister_Tag --
kono
parents:
diff changeset
1073 --------------------
kono
parents:
diff changeset
1074
kono
parents:
diff changeset
1075 procedure Unregister_Tag (T : Tag) is
kono
parents:
diff changeset
1076 begin
kono
parents:
diff changeset
1077 External_Tag_HTable.Remove (Get_External_Tag (T));
kono
parents:
diff changeset
1078 end Unregister_Tag;
kono
parents:
diff changeset
1079
kono
parents:
diff changeset
1080 ------------------------
kono
parents:
diff changeset
1081 -- Wide_Expanded_Name --
kono
parents:
diff changeset
1082 ------------------------
kono
parents:
diff changeset
1083
kono
parents:
diff changeset
1084 WC_Encoding : Character;
kono
parents:
diff changeset
1085 pragma Import (C, WC_Encoding, "__gl_wc_encoding");
kono
parents:
diff changeset
1086 -- Encoding method for source, as exported by binder
kono
parents:
diff changeset
1087
kono
parents:
diff changeset
1088 function Wide_Expanded_Name (T : Tag) return Wide_String is
kono
parents:
diff changeset
1089 S : constant String := Expanded_Name (T);
kono
parents:
diff changeset
1090 W : Wide_String (1 .. S'Length);
kono
parents:
diff changeset
1091 L : Natural;
kono
parents:
diff changeset
1092 begin
kono
parents:
diff changeset
1093 String_To_Wide_String
kono
parents:
diff changeset
1094 (S, W, L, Get_WC_Encoding_Method (WC_Encoding));
kono
parents:
diff changeset
1095 return W (1 .. L);
kono
parents:
diff changeset
1096 end Wide_Expanded_Name;
kono
parents:
diff changeset
1097
kono
parents:
diff changeset
1098 -----------------------------
kono
parents:
diff changeset
1099 -- Wide_Wide_Expanded_Name --
kono
parents:
diff changeset
1100 -----------------------------
kono
parents:
diff changeset
1101
kono
parents:
diff changeset
1102 function Wide_Wide_Expanded_Name (T : Tag) return Wide_Wide_String is
kono
parents:
diff changeset
1103 S : constant String := Expanded_Name (T);
kono
parents:
diff changeset
1104 W : Wide_Wide_String (1 .. S'Length);
kono
parents:
diff changeset
1105 L : Natural;
kono
parents:
diff changeset
1106 begin
kono
parents:
diff changeset
1107 String_To_Wide_Wide_String
kono
parents:
diff changeset
1108 (S, W, L, Get_WC_Encoding_Method (WC_Encoding));
kono
parents:
diff changeset
1109 return W (1 .. L);
kono
parents:
diff changeset
1110 end Wide_Wide_Expanded_Name;
kono
parents:
diff changeset
1111
kono
parents:
diff changeset
1112 end Ada.Tags;