]>
Commit | Line | Data |
---|---|---|
19235870 RK |
1 | ------------------------------------------------------------------------------ |
2 | -- -- | |
3 | -- GNAT COMPILER COMPONENTS -- | |
4 | -- -- | |
5 | -- R E P I N F O -- | |
6 | -- -- | |
7 | -- B o d y -- | |
8 | -- -- | |
06c565cc | 9 | -- Copyright (C) 1999-2024, Free Software Foundation, Inc. -- |
19235870 RK |
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- -- | |
748086b7 | 13 | -- ware Foundation; either version 3, or (at your option) any later ver- -- |
19235870 RK |
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 -- | |
536c271c AC |
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 COPYING3. If not, go to -- | |
19 | -- http://www.gnu.org/licenses for a complete copy of the license. -- | |
748086b7 | 20 | -- -- |
19235870 | 21 | -- GNAT was originally developed by the GNAT team at New York University. -- |
71ff80dc | 22 | -- Extensive contributions were provided by Ada Core Technologies Inc. -- |
19235870 RK |
23 | -- -- |
24 | ------------------------------------------------------------------------------ | |
25 | ||
851e9f19 | 26 | with Alloc; |
104f58db BD |
27 | with Atree; use Atree; |
28 | with Casing; use Casing; | |
29 | with Debug; use Debug; | |
30 | with Einfo; use Einfo; | |
76f9c7f4 | 31 | with Einfo.Entities; use Einfo.Entities; |
104f58db BD |
32 | with Einfo.Utils; use Einfo.Utils; |
33 | with Lib; use Lib; | |
34 | with Namet; use Namet; | |
35 | with Nlists; use Nlists; | |
36 | with Opt; use Opt; | |
37 | with Output; use Output; | |
4b54d939 | 38 | with Osint.C; use Osint.C; |
104f58db BD |
39 | with Sem_Aux; use Sem_Aux; |
40 | with Sem_Eval; use Sem_Eval; | |
db778c70 | 41 | with Sem_Util; |
104f58db BD |
42 | with Sinfo; use Sinfo; |
43 | with Sinfo.Nodes; use Sinfo.Nodes; | |
44 | with Sinfo.Utils; use Sinfo.Utils; | |
45 | with Sinput; use Sinput; | |
46 | with Snames; use Snames; | |
ebbe4801 | 47 | with Stand; use Stand; |
104f58db | 48 | with Stringt; use Stringt; |
851e9f19 | 49 | with Table; |
3aeb5ebe | 50 | with Ttypes; |
104f58db BD |
51 | with Uname; use Uname; |
52 | with Urealp; use Urealp; | |
19235870 | 53 | |
5e61ef09 TQ |
54 | with Ada.Unchecked_Conversion; |
55 | ||
b5f581cd EB |
56 | with GNAT.HTable; |
57 | ||
19235870 RK |
58 | package body Repinfo is |
59 | ||
3aeb5ebe AC |
60 | SSU : Pos renames Ttypes.System_Storage_Unit; |
61 | -- Value for Storage_Unit | |
fbf5a39b | 62 | |
19235870 | 63 | --------------------------------------- |
e45f84a5 | 64 | -- Representation of GCC Expressions -- |
19235870 RK |
65 | --------------------------------------- |
66 | ||
5e61ef09 | 67 | -- A table internal to this unit is used to hold the values of back |
ba203461 | 68 | -- annotated expressions. |
19235870 | 69 | |
5e61ef09 TQ |
70 | -- Node values are stored as Uint values using the negative of the node |
71 | -- index in this table. Constants appear as non-negative Uint values. | |
19235870 RK |
72 | |
73 | type Exp_Node is record | |
74 | Expr : TCode; | |
75 | Op1 : Node_Ref_Or_Val; | |
76 | Op2 : Node_Ref_Or_Val; | |
77 | Op3 : Node_Ref_Or_Val; | |
78 | end record; | |
79 | ||
1c28fe3a RD |
80 | -- The following representation clause ensures that the above record |
81 | -- has no holes. We do this so that when instances of this record are | |
ba203461 | 82 | -- written, we do not write uninitialized values to the file. |
1c28fe3a RD |
83 | |
84 | for Exp_Node use record | |
85 | Expr at 0 range 0 .. 31; | |
86 | Op1 at 4 range 0 .. 31; | |
87 | Op2 at 8 range 0 .. 31; | |
88 | Op3 at 12 range 0 .. 31; | |
89 | end record; | |
90 | ||
91 | for Exp_Node'Size use 16 * 8; | |
92 | -- This ensures that we did not leave out any fields | |
93 | ||
19235870 RK |
94 | package Rep_Table is new Table.Table ( |
95 | Table_Component_Type => Exp_Node, | |
96 | Table_Index_Type => Nat, | |
97 | Table_Low_Bound => 1, | |
98 | Table_Initial => Alloc.Rep_Table_Initial, | |
99 | Table_Increment => Alloc.Rep_Table_Increment, | |
100 | Table_Name => "BE_Rep_Table"); | |
101 | ||
3fbf81a2 AC |
102 | -------------------------------------------------------------- |
103 | -- Representation of Front-End Dynamic Size/Offset Entities -- | |
104 | -------------------------------------------------------------- | |
105 | ||
106 | package Dynamic_SO_Entity_Table is new Table.Table ( | |
107 | Table_Component_Type => Entity_Id, | |
108 | Table_Index_Type => Nat, | |
109 | Table_Low_Bound => 1, | |
110 | Table_Initial => Alloc.Rep_Table_Initial, | |
111 | Table_Increment => Alloc.Rep_Table_Increment, | |
112 | Table_Name => "FE_Rep_Table"); | |
113 | ||
19235870 | 114 | Unit_Casing : Casing_Type; |
d436b30d AC |
115 | -- Identifier casing for current unit. This is set by List_Rep_Info for |
116 | -- each unit, before calling subprograms which may read it. | |
19235870 | 117 | |
b5d3d113 EB |
118 | Need_Separator : Boolean; |
119 | -- Set True if a separator is needed before outputting any information for | |
120 | -- the current entity. | |
fbf5a39b | 121 | |
89beb653 HK |
122 | ------------------------------ |
123 | -- Set of Relevant Entities -- | |
124 | ------------------------------ | |
b5f581cd EB |
125 | |
126 | Relevant_Entities_Size : constant := 4093; | |
127 | -- Number of headers in hash table | |
128 | ||
129 | subtype Entity_Header_Num is Integer range 0 .. Relevant_Entities_Size - 1; | |
130 | -- Range of headers in hash table | |
131 | ||
132 | function Entity_Hash (Id : Entity_Id) return Entity_Header_Num; | |
133 | -- Simple hash function for Entity_Ids | |
134 | ||
135 | package Relevant_Entities is new GNAT.Htable.Simple_HTable | |
136 | (Header_Num => Entity_Header_Num, | |
137 | Element => Boolean, | |
138 | No_Element => False, | |
139 | Key => Entity_Id, | |
140 | Hash => Entity_Hash, | |
141 | Equal => "="); | |
142 | -- Hash table to record which compiler-generated entities are relevant | |
143 | ||
fbf5a39b AC |
144 | ----------------------- |
145 | -- Local Subprograms -- | |
146 | ----------------------- | |
19235870 | 147 | |
1e60643a | 148 | procedure List_Entities |
558fbeb0 | 149 | (Ent : Entity_Id; |
1e60643a AC |
150 | Bytes_Big_Endian : Boolean; |
151 | In_Subprogram : Boolean := False); | |
5e61ef09 TQ |
152 | -- This procedure lists the entities associated with the entity E, starting |
153 | -- with the First_Entity and using the Next_Entity link. If a nested | |
154 | -- package is found, entities within the package are recursively processed. | |
1e60643a AC |
155 | -- When recursing within a subprogram body, Is_Subprogram suppresses |
156 | -- duplicate information about signature. | |
19235870 RK |
157 | |
158 | procedure List_Name (Ent : Entity_Id); | |
159 | -- List name of entity Ent in appropriate case. The name is listed with | |
160 | -- full qualification up to but not including the compilation unit name. | |
161 | ||
d9f8616e | 162 | procedure List_Array_Info (Ent : Entity_Id; Bytes_Big_Endian : Boolean); |
19235870 RK |
163 | -- List representation info for array type Ent |
164 | ||
6f65c7ee EB |
165 | procedure List_Common_Type_Info (Ent : Entity_Id); |
166 | -- List common type info (name, size, alignment) for type Ent | |
167 | ||
19992053 AC |
168 | procedure List_Linker_Section (Ent : Entity_Id); |
169 | -- List linker section for Ent (caller has checked that Ent is an entity | |
170 | -- for which the Linker_Section_Pragma field is defined). | |
171 | ||
1e7629b8 EB |
172 | procedure List_Location (Ent : Entity_Id); |
173 | -- List location information for Ent | |
174 | ||
19235870 RK |
175 | procedure List_Object_Info (Ent : Entity_Id); |
176 | -- List representation info for object Ent | |
177 | ||
d9f8616e | 178 | procedure List_Record_Info (Ent : Entity_Id; Bytes_Big_Endian : Boolean); |
19235870 RK |
179 | -- List representation info for record type Ent |
180 | ||
d9f8616e AC |
181 | procedure List_Scalar_Storage_Order |
182 | (Ent : Entity_Id; | |
183 | Bytes_Big_Endian : Boolean); | |
7ed57189 AC |
184 | -- List scalar storage order information for record or array type Ent. |
185 | -- Also includes bit order information for record types, if necessary. | |
d9f8616e | 186 | |
6f65c7ee EB |
187 | procedure List_Subprogram_Info (Ent : Entity_Id); |
188 | -- List subprogram info for subprogram Ent | |
189 | ||
19235870 RK |
190 | procedure List_Type_Info (Ent : Entity_Id); |
191 | -- List type info for type Ent | |
192 | ||
d7ca4dfe BD |
193 | function Compile_Time_Known_Rep (Val : Node_Ref_Or_Val) return Boolean; |
194 | -- Returns True if Val represents a representation value that is known at | |
195 | -- compile time. | |
19235870 | 196 | |
fbf5a39b AC |
197 | procedure Spaces (N : Natural); |
198 | -- Output given number of spaces | |
199 | ||
07fc65c4 | 200 | procedure Write_Info_Line (S : String); |
5e61ef09 TQ |
201 | -- Routine to write a line to Repinfo output file. This routine is passed |
202 | -- as a special output procedure to Output.Set_Special_Output. Note that | |
203 | -- Write_Info_Line is called with an EOL character at the end of each line, | |
204 | -- as per the Output spec, but the internal call to the appropriate routine | |
205 | -- in Osint requires that the end of line sequence be stripped off. | |
07fc65c4 | 206 | |
fbf5a39b AC |
207 | procedure Write_Mechanism (M : Mechanism_Type); |
208 | -- Writes symbolic string for mechanism represented by M | |
209 | ||
b5d3d113 EB |
210 | procedure Write_Separator; |
211 | -- Called before outputting anything for an entity. Ensures that | |
212 | -- a separator precedes the output for a particular entity. | |
213 | ||
76b382d9 EB |
214 | procedure Write_Unknown_Val; |
215 | -- Writes symbolic string for an unknown or non-representable value | |
216 | ||
19235870 RK |
217 | procedure Write_Val (Val : Node_Ref_Or_Val; Paren : Boolean := False); |
218 | -- Given a representation value, write it out. No_Uint values or values | |
219 | -- dependent on discriminants are written as two question marks. If the | |
5e61ef09 TQ |
220 | -- flag Paren is set, then the output is surrounded in parentheses if it is |
221 | -- other than a simple value. | |
19235870 | 222 | |
19235870 RK |
223 | ------------------------ |
224 | -- Create_Discrim_Ref -- | |
225 | ------------------------ | |
226 | ||
a4c1cd80 | 227 | function Create_Discrim_Ref (Discr : Entity_Id) return Node_Ref is |
19235870 | 228 | begin |
1d6f10a1 TQ |
229 | return Create_Node |
230 | (Expr => Discrim_Val, | |
231 | Op1 => Discriminant_Number (Discr)); | |
19235870 RK |
232 | end Create_Discrim_Ref; |
233 | ||
3fbf81a2 AC |
234 | --------------------------- |
235 | -- Create_Dynamic_SO_Ref -- | |
236 | --------------------------- | |
237 | ||
238 | function Create_Dynamic_SO_Ref (E : Entity_Id) return Dynamic_SO_Ref is | |
239 | begin | |
240 | Dynamic_SO_Entity_Table.Append (E); | |
241 | return UI_From_Int (-Dynamic_SO_Entity_Table.Last); | |
242 | end Create_Dynamic_SO_Ref; | |
243 | ||
19235870 RK |
244 | ----------------- |
245 | -- Create_Node -- | |
246 | ----------------- | |
247 | ||
248 | function Create_Node | |
249 | (Expr : TCode; | |
250 | Op1 : Node_Ref_Or_Val; | |
251 | Op2 : Node_Ref_Or_Val := No_Uint; | |
a4c1cd80 | 252 | Op3 : Node_Ref_Or_Val := No_Uint) return Node_Ref |
19235870 | 253 | is |
19235870 | 254 | begin |
1d6f10a1 TQ |
255 | Rep_Table.Append ( |
256 | (Expr => Expr, | |
257 | Op1 => Op1, | |
258 | Op2 => Op2, | |
259 | Op3 => Op3)); | |
260 | return UI_From_Int (-Rep_Table.Last); | |
19235870 RK |
261 | end Create_Node; |
262 | ||
b5f581cd EB |
263 | ----------------- |
264 | -- Entity_Hash -- | |
265 | ----------------- | |
266 | ||
267 | function Entity_Hash (Id : Entity_Id) return Entity_Header_Num is | |
268 | begin | |
269 | return Entity_Header_Num (Id mod Relevant_Entities_Size); | |
270 | end Entity_Hash; | |
271 | ||
3fbf81a2 AC |
272 | --------------------------- |
273 | -- Get_Dynamic_SO_Entity -- | |
274 | --------------------------- | |
275 | ||
276 | function Get_Dynamic_SO_Entity (U : Dynamic_SO_Ref) return Entity_Id is | |
277 | begin | |
278 | return Dynamic_SO_Entity_Table.Table (-UI_To_Int (U)); | |
279 | end Get_Dynamic_SO_Entity; | |
280 | ||
281 | ----------------------- | |
282 | -- Is_Dynamic_SO_Ref -- | |
283 | ----------------------- | |
284 | ||
285 | function Is_Dynamic_SO_Ref (U : SO_Ref) return Boolean is | |
286 | begin | |
287 | return U < Uint_0; | |
288 | end Is_Dynamic_SO_Ref; | |
289 | ||
290 | ---------------------- | |
291 | -- Is_Static_SO_Ref -- | |
292 | ---------------------- | |
293 | ||
294 | function Is_Static_SO_Ref (U : SO_Ref) return Boolean is | |
295 | begin | |
296 | return U >= Uint_0; | |
297 | end Is_Static_SO_Ref; | |
298 | ||
19235870 RK |
299 | --------- |
300 | -- lgx -- | |
301 | --------- | |
302 | ||
303 | procedure lgx (U : Node_Ref_Or_Val) is | |
304 | begin | |
305 | List_GCC_Expression (U); | |
306 | Write_Eol; | |
307 | end lgx; | |
308 | ||
309 | ---------------------- | |
310 | -- List_Array_Info -- | |
311 | ---------------------- | |
312 | ||
d9f8616e | 313 | procedure List_Array_Info (Ent : Entity_Id; Bytes_Big_Endian : Boolean) is |
19235870 | 314 | begin |
b5d3d113 | 315 | Write_Separator; |
1e7629b8 EB |
316 | |
317 | if List_Representation_Info_To_JSON then | |
318 | Write_Line ("{"); | |
319 | end if; | |
320 | ||
6f65c7ee | 321 | List_Common_Type_Info (Ent); |
7672ab42 | 322 | |
1e7629b8 EB |
323 | if List_Representation_Info_To_JSON then |
324 | Write_Line (","); | |
325 | Write_Str (" ""Component_Size"": "); | |
326 | Write_Val (Component_Size (Ent)); | |
327 | else | |
328 | Write_Str ("for "); | |
329 | List_Name (Ent); | |
330 | Write_Str ("'Component_Size use "); | |
331 | Write_Val (Component_Size (Ent)); | |
332 | Write_Line (";"); | |
333 | end if; | |
d9f8616e AC |
334 | |
335 | List_Scalar_Storage_Order (Ent, Bytes_Big_Endian); | |
7672ab42 EB |
336 | |
337 | List_Linker_Section (Ent); | |
1e7629b8 EB |
338 | |
339 | if List_Representation_Info_To_JSON then | |
340 | Write_Eol; | |
341 | Write_Line ("}"); | |
342 | end if; | |
3c488e6c EB |
343 | |
344 | -- The component type is relevant for an array | |
345 | ||
346 | if List_Representation_Info = 4 | |
347 | and then Is_Itype (Component_Type (Base_Type (Ent))) | |
348 | then | |
349 | Relevant_Entities.Set (Component_Type (Base_Type (Ent)), True); | |
350 | end if; | |
19235870 RK |
351 | end List_Array_Info; |
352 | ||
6f65c7ee EB |
353 | --------------------------- |
354 | -- List_Common_Type_Info -- | |
355 | --------------------------- | |
356 | ||
357 | procedure List_Common_Type_Info (Ent : Entity_Id) is | |
358 | begin | |
359 | if List_Representation_Info_To_JSON then | |
360 | Write_Str (" ""name"": """); | |
361 | List_Name (Ent); | |
362 | Write_Line (""","); | |
363 | List_Location (Ent); | |
364 | end if; | |
365 | ||
366 | -- Do not list size info for unconstrained arrays, not meaningful | |
367 | ||
368 | if Is_Array_Type (Ent) and then not Is_Constrained (Ent) then | |
369 | null; | |
370 | ||
371 | else | |
36e38022 BD |
372 | if Known_Esize (Ent) and then Known_RM_Size (Ent) then |
373 | -- If Esize and RM_Size are the same, list as Size. This is a | |
374 | -- common case, which we may as well list in simple form. | |
375 | ||
376 | if Esize (Ent) = RM_Size (Ent) then | |
377 | if List_Representation_Info_To_JSON then | |
378 | Write_Str (" ""Size"": "); | |
379 | Write_Val (Esize (Ent)); | |
380 | Write_Line (","); | |
381 | else | |
382 | Write_Str ("for "); | |
383 | List_Name (Ent); | |
384 | Write_Str ("'Size use "); | |
385 | Write_Val (Esize (Ent)); | |
386 | Write_Line (";"); | |
387 | end if; | |
388 | ||
389 | -- Otherwise list size values separately | |
6f65c7ee EB |
390 | |
391 | else | |
36e38022 BD |
392 | if List_Representation_Info_To_JSON then |
393 | Write_Str (" ""Object_Size"": "); | |
394 | Write_Val (Esize (Ent)); | |
395 | Write_Line (","); | |
396 | ||
397 | Write_Str (" ""Value_Size"": "); | |
398 | Write_Val (RM_Size (Ent)); | |
399 | Write_Line (","); | |
400 | ||
401 | else | |
402 | Write_Str ("for "); | |
403 | List_Name (Ent); | |
404 | Write_Str ("'Object_Size use "); | |
405 | Write_Val (Esize (Ent)); | |
406 | Write_Line (";"); | |
407 | ||
408 | Write_Str ("for "); | |
409 | List_Name (Ent); | |
410 | Write_Str ("'Value_Size use "); | |
411 | Write_Val (RM_Size (Ent)); | |
412 | Write_Line (";"); | |
413 | end if; | |
6f65c7ee EB |
414 | end if; |
415 | end if; | |
416 | end if; | |
417 | ||
0c8ff35e BD |
418 | if Known_Alignment (Ent) then |
419 | if List_Representation_Info_To_JSON then | |
420 | Write_Str (" ""Alignment"": "); | |
421 | Write_Val (Alignment (Ent)); | |
422 | else | |
423 | Write_Str ("for "); | |
424 | List_Name (Ent); | |
425 | Write_Str ("'Alignment use "); | |
426 | Write_Val (Alignment (Ent)); | |
427 | Write_Line (";"); | |
428 | end if; | |
429 | ||
b8d31ebc | 430 | -- Alignment is not always set for task, protected, and class-wide |
f9b03ef7 YM |
431 | -- types, or when doing semantic analysis only. Representation aspects |
432 | -- are not computed for types in a generic unit. | |
0c8ff35e | 433 | |
6f65c7ee | 434 | else |
f9b03ef7 YM |
435 | -- Add unknown alignment entry in JSON format to ensure the format is |
436 | -- valid, as a comma is added by the caller before another field. | |
437 | ||
438 | if List_Representation_Info_To_JSON then | |
439 | Write_Str (" ""Alignment"": "); | |
440 | Write_Unknown_Val; | |
441 | end if; | |
442 | ||
0c8ff35e | 443 | pragma Assert |
f9b03ef7 YM |
444 | (not Expander_Active or else |
445 | Is_Concurrent_Type (Ent) or else | |
db778c70 BD |
446 | Is_Class_Wide_Type (Ent) or else |
447 | Sem_Util.In_Generic_Scope (Ent)); | |
6f65c7ee EB |
448 | end if; |
449 | end List_Common_Type_Info; | |
450 | ||
19235870 RK |
451 | ------------------- |
452 | -- List_Entities -- | |
453 | ------------------- | |
454 | ||
1e60643a | 455 | procedure List_Entities |
558fbeb0 | 456 | (Ent : Entity_Id; |
1e60643a AC |
457 | Bytes_Big_Endian : Boolean; |
458 | In_Subprogram : Boolean := False) | |
459 | is | |
fbf5a39b AC |
460 | Body_E : Entity_Id; |
461 | E : Entity_Id; | |
462 | ||
463 | function Find_Declaration (E : Entity_Id) return Node_Id; | |
464 | -- Utility to retrieve declaration node for entity in the | |
465 | -- case of package bodies and subprograms. | |
466 | ||
467 | ---------------------- | |
468 | -- Find_Declaration -- | |
469 | ---------------------- | |
470 | ||
471 | function Find_Declaration (E : Entity_Id) return Node_Id is | |
472 | Decl : Node_Id; | |
a4c1cd80 | 473 | |
fbf5a39b AC |
474 | begin |
475 | Decl := Parent (E); | |
fbf5a39b | 476 | while Present (Decl) |
1155ae01 | 477 | and then Nkind (Decl) /= N_Package_Body |
fbf5a39b AC |
478 | and then Nkind (Decl) /= N_Subprogram_Declaration |
479 | and then Nkind (Decl) /= N_Subprogram_Body | |
480 | loop | |
481 | Decl := Parent (Decl); | |
482 | end loop; | |
483 | ||
484 | return Decl; | |
485 | end Find_Declaration; | |
486 | ||
487 | -- Start of processing for List_Entities | |
19235870 RK |
488 | |
489 | begin | |
d3879a5a RD |
490 | -- List entity if we have one, and it is not a renaming declaration. |
491 | -- For renamings, we don't get proper information, and really it makes | |
492 | -- sense to restrict the output to the renamed entity. | |
fbf5a39b | 493 | |
d3879a5a RD |
494 | if Present (Ent) |
495 | and then Nkind (Declaration_Node (Ent)) not in N_Renaming_Declaration | |
022c9dfe | 496 | and then not Is_Ignored_Ghost_Entity (Ent) |
d3879a5a | 497 | then |
fbf5a39b | 498 | -- If entity is a subprogram and we are listing mechanisms, |
1e60643a AC |
499 | -- then we need to list mechanisms for this entity. We skip this |
500 | -- if it is a nested subprogram, as the information has already | |
501 | -- been produced when listing the enclosing scope. | |
fbf5a39b AC |
502 | |
503 | if List_Representation_Info_Mechanisms | |
f05f68bc | 504 | and then Is_Subprogram_Or_Entry (Ent) |
1e60643a | 505 | and then not In_Subprogram |
fbf5a39b | 506 | then |
6f65c7ee | 507 | List_Subprogram_Info (Ent); |
fbf5a39b AC |
508 | end if; |
509 | ||
19235870 RK |
510 | E := First_Entity (Ent); |
511 | while Present (E) loop | |
5e61ef09 | 512 | -- We list entities that come from source (excluding private or |
b5f581cd EB |
513 | -- incomplete types or deferred constants, for which we will list |
514 | -- the information for the full view). If requested, we also list | |
515 | -- relevant entities that have been generated when processing the | |
516 | -- original entities coming from source. But if debug flag A is | |
517 | -- set, then all entities are listed. | |
fbf5a39b | 518 | |
944e24a3 EB |
519 | if ((Comes_From_Source (E) |
520 | or else (Ekind (E) = E_Block | |
521 | and then | |
522 | Nkind (Parent (E)) = N_Implicit_Label_Declaration | |
523 | and then | |
524 | Comes_From_Source (Label_Construct (Parent (E))))) | |
fbf5a39b AC |
525 | and then not Is_Incomplete_Or_Private_Type (E) |
526 | and then not (Ekind (E) = E_Constant | |
527 | and then Present (Full_View (E)))) | |
b5f581cd EB |
528 | or else (List_Representation_Info = 4 |
529 | and then Relevant_Entities.Get (E)) | |
07fc65c4 GB |
530 | or else Debug_Flag_AA |
531 | then | |
19992053 | 532 | if Is_Subprogram (E) then |
19992053 | 533 | if List_Representation_Info_Mechanisms then |
6f65c7ee | 534 | List_Subprogram_Info (E); |
19992053 AC |
535 | end if; |
536 | ||
1e60643a AC |
537 | -- Recurse into entities local to subprogram |
538 | ||
539 | List_Entities (E, Bytes_Big_Endian, True); | |
540 | ||
4a08c95c AC |
541 | elsif Ekind (E) in E_Entry |
542 | | E_Entry_Family | |
543 | | E_Subprogram_Type | |
fbf5a39b AC |
544 | then |
545 | if List_Representation_Info_Mechanisms then | |
6f65c7ee | 546 | List_Subprogram_Info (E); |
fbf5a39b AC |
547 | end if; |
548 | ||
549 | elsif Is_Record_Type (E) then | |
550 | if List_Representation_Info >= 1 then | |
d9f8616e | 551 | List_Record_Info (E, Bytes_Big_Endian); |
19235870 | 552 | |
f05f68bc | 553 | -- Recurse into entities local to a record type |
3c488e6c | 554 | |
f05f68bc PT |
555 | if List_Representation_Info = 4 then |
556 | List_Entities (E, Bytes_Big_Endian, False); | |
557 | end if; | |
3c488e6c EB |
558 | end if; |
559 | ||
19235870 | 560 | elsif Is_Array_Type (E) then |
fbf5a39b | 561 | if List_Representation_Info >= 1 then |
d9f8616e | 562 | List_Array_Info (E, Bytes_Big_Endian); |
fbf5a39b | 563 | end if; |
19235870 | 564 | |
fbf5a39b AC |
565 | elsif Is_Type (E) then |
566 | if List_Representation_Info >= 2 then | |
19235870 | 567 | List_Type_Info (E); |
fbf5a39b | 568 | end if; |
19235870 | 569 | |
fb95bfcc | 570 | -- Note that formals are not annotated so we skip them here |
19992053 | 571 | |
4a08c95c AC |
572 | elsif Ekind (E) in E_Constant |
573 | | E_Loop_Parameter | |
574 | | E_Variable | |
fb95bfcc | 575 | then |
fbf5a39b | 576 | if List_Representation_Info >= 2 then |
19235870 RK |
577 | List_Object_Info (E); |
578 | end if; | |
579 | end if; | |
580 | ||
f3799ac5 BD |
581 | -- Recurse into nested package, but not child packages, and not |
582 | -- nested package renamings (in particular renamings of the | |
583 | -- enclosing package, as for some Java bindings and for generic | |
584 | -- instances). | |
19235870 | 585 | |
07fc65c4 | 586 | if Ekind (E) = E_Package then |
f3799ac5 BD |
587 | if No (Renamed_Entity (E)) and then not Is_Child_Unit (E) |
588 | then | |
d9f8616e | 589 | List_Entities (E, Bytes_Big_Endian); |
07fc65c4 GB |
590 | end if; |
591 | ||
592 | -- Recurse into bodies | |
593 | ||
4a08c95c AC |
594 | elsif Ekind (E) in E_Package_Body |
595 | | E_Protected_Body | |
596 | | E_Protected_Type | |
597 | | E_Subprogram_Body | |
598 | | E_Task_Body | |
599 | | E_Task_Type | |
19235870 | 600 | then |
d9f8616e | 601 | List_Entities (E, Bytes_Big_Endian); |
07fc65c4 GB |
602 | |
603 | -- Recurse into blocks | |
604 | ||
605 | elsif Ekind (E) = E_Block then | |
d9f8616e | 606 | List_Entities (E, Bytes_Big_Endian); |
19235870 RK |
607 | end if; |
608 | end if; | |
609 | ||
99859ea7 | 610 | Next_Entity (E); |
19235870 | 611 | end loop; |
fbf5a39b | 612 | |
5e61ef09 TQ |
613 | -- For a package body, the entities of the visible subprograms are |
614 | -- declared in the corresponding spec. Iterate over its entities in | |
615 | -- order to handle properly the subprogram bodies. Skip bodies in | |
616 | -- subunits, which are listed independently. | |
fbf5a39b AC |
617 | |
618 | if Ekind (Ent) = E_Package_Body | |
619 | and then Present (Corresponding_Spec (Find_Declaration (Ent))) | |
620 | then | |
621 | E := First_Entity (Corresponding_Spec (Find_Declaration (Ent))); | |
fbf5a39b AC |
622 | while Present (E) loop |
623 | if Is_Subprogram (E) | |
624 | and then | |
625 | Nkind (Find_Declaration (E)) = N_Subprogram_Declaration | |
626 | then | |
627 | Body_E := Corresponding_Body (Find_Declaration (E)); | |
628 | ||
629 | if Present (Body_E) | |
630 | and then | |
631 | Nkind (Parent (Find_Declaration (Body_E))) /= N_Subunit | |
632 | then | |
d9f8616e | 633 | List_Entities (Body_E, Bytes_Big_Endian); |
fbf5a39b AC |
634 | end if; |
635 | end if; | |
636 | ||
637 | Next_Entity (E); | |
638 | end loop; | |
639 | end if; | |
19235870 RK |
640 | end if; |
641 | end List_Entities; | |
642 | ||
643 | ------------------------- | |
644 | -- List_GCC_Expression -- | |
645 | ------------------------- | |
646 | ||
647 | procedure List_GCC_Expression (U : Node_Ref_Or_Val) is | |
648 | ||
fbf5a39b | 649 | procedure Print_Expr (Val : Node_Ref_Or_Val); |
19235870 RK |
650 | -- Internal recursive procedure to print expression |
651 | ||
fbf5a39b AC |
652 | ---------------- |
653 | -- Print_Expr -- | |
654 | ---------------- | |
655 | ||
656 | procedure Print_Expr (Val : Node_Ref_Or_Val) is | |
19235870 RK |
657 | begin |
658 | if Val >= 0 then | |
659 | UI_Write (Val, Decimal); | |
660 | ||
661 | else | |
662 | declare | |
663 | Node : Exp_Node renames Rep_Table.Table (-UI_To_Int (Val)); | |
664 | ||
7672ab42 EB |
665 | procedure Unop (S : String); |
666 | -- Output text for unary operator with S being operator name | |
667 | ||
19235870 RK |
668 | procedure Binop (S : String); |
669 | -- Output text for binary operator with S being operator name | |
670 | ||
7672ab42 EB |
671 | ---------- |
672 | -- Unop -- | |
673 | ---------- | |
674 | ||
675 | procedure Unop (S : String) is | |
676 | begin | |
1e7629b8 EB |
677 | if List_Representation_Info_To_JSON then |
678 | Write_Str ("{ ""code"": """); | |
679 | if S (S'Last) = ' ' then | |
680 | Write_Str (S (S'First .. S'Last - 1)); | |
681 | else | |
682 | Write_Str (S); | |
683 | end if; | |
684 | Write_Str (""", ""operands"": [ "); | |
685 | Print_Expr (Node.Op1); | |
686 | Write_Str (" ] }"); | |
687 | else | |
688 | Write_Str (S); | |
689 | Print_Expr (Node.Op1); | |
690 | end if; | |
7672ab42 EB |
691 | end Unop; |
692 | ||
fbf5a39b AC |
693 | ----------- |
694 | -- Binop -- | |
695 | ----------- | |
696 | ||
19235870 RK |
697 | procedure Binop (S : String) is |
698 | begin | |
1e7629b8 EB |
699 | if List_Representation_Info_To_JSON then |
700 | Write_Str ("{ ""code"": """); | |
701 | Write_Str (S (S'First + 1 .. S'Last - 1)); | |
702 | Write_Str (""", ""operands"": [ "); | |
703 | Print_Expr (Node.Op1); | |
704 | Write_Str (", "); | |
705 | Print_Expr (Node.Op2); | |
706 | Write_Str (" ] }"); | |
707 | else | |
708 | Write_Char ('('); | |
709 | Print_Expr (Node.Op1); | |
710 | Write_Str (S); | |
711 | Print_Expr (Node.Op2); | |
712 | Write_Char (')'); | |
713 | end if; | |
19235870 RK |
714 | end Binop; |
715 | ||
fbf5a39b | 716 | -- Start of processing for Print_Expr |
19235870 RK |
717 | |
718 | begin | |
719 | case Node.Expr is | |
720 | when Cond_Expr => | |
1e7629b8 EB |
721 | if List_Representation_Info_To_JSON then |
722 | Write_Str ("{ ""code"": ""?<>"""); | |
723 | Write_Str (", ""operands"": [ "); | |
724 | Print_Expr (Node.Op1); | |
725 | Write_Str (", "); | |
726 | Print_Expr (Node.Op2); | |
727 | Write_Str (", "); | |
728 | Print_Expr (Node.Op3); | |
729 | Write_Str (" ] }"); | |
730 | else | |
731 | Write_Str ("(if "); | |
732 | Print_Expr (Node.Op1); | |
733 | Write_Str (" then "); | |
734 | Print_Expr (Node.Op2); | |
735 | Write_Str (" else "); | |
736 | Print_Expr (Node.Op3); | |
737 | Write_Str (" end)"); | |
738 | end if; | |
19235870 RK |
739 | |
740 | when Plus_Expr => | |
741 | Binop (" + "); | |
742 | ||
743 | when Minus_Expr => | |
744 | Binop (" - "); | |
745 | ||
746 | when Mult_Expr => | |
747 | Binop (" * "); | |
748 | ||
749 | when Trunc_Div_Expr => | |
750 | Binop (" /t "); | |
751 | ||
752 | when Ceil_Div_Expr => | |
753 | Binop (" /c "); | |
754 | ||
755 | when Floor_Div_Expr => | |
756 | Binop (" /f "); | |
757 | ||
758 | when Trunc_Mod_Expr => | |
759 | Binop (" modt "); | |
760 | ||
19235870 RK |
761 | when Ceil_Mod_Expr => |
762 | Binop (" modc "); | |
763 | ||
7672ab42 EB |
764 | when Floor_Mod_Expr => |
765 | Binop (" modf "); | |
766 | ||
19235870 RK |
767 | when Exact_Div_Expr => |
768 | Binop (" /e "); | |
769 | ||
770 | when Negate_Expr => | |
7672ab42 | 771 | Unop ("-"); |
19235870 RK |
772 | |
773 | when Min_Expr => | |
774 | Binop (" min "); | |
775 | ||
776 | when Max_Expr => | |
777 | Binop (" max "); | |
778 | ||
779 | when Abs_Expr => | |
7672ab42 | 780 | Unop ("abs "); |
19235870 | 781 | |
19235870 RK |
782 | when Truth_And_Expr => |
783 | Binop (" and "); | |
784 | ||
785 | when Truth_Or_Expr => | |
786 | Binop (" or "); | |
787 | ||
788 | when Truth_Xor_Expr => | |
789 | Binop (" xor "); | |
790 | ||
791 | when Truth_Not_Expr => | |
7672ab42 | 792 | Unop ("not "); |
5e61ef09 | 793 | |
19235870 RK |
794 | when Lt_Expr => |
795 | Binop (" < "); | |
796 | ||
797 | when Le_Expr => | |
798 | Binop (" <= "); | |
799 | ||
800 | when Gt_Expr => | |
801 | Binop (" > "); | |
802 | ||
803 | when Ge_Expr => | |
804 | Binop (" >= "); | |
805 | ||
806 | when Eq_Expr => | |
807 | Binop (" == "); | |
808 | ||
809 | when Ne_Expr => | |
810 | Binop (" != "); | |
811 | ||
7672ab42 EB |
812 | when Bit_And_Expr => |
813 | Binop (" & "); | |
814 | ||
19235870 | 815 | when Discrim_Val => |
575e47bf | 816 | Unop ("#"); |
e45f84a5 EB |
817 | |
818 | when Dynamic_Val => | |
575e47bf | 819 | Unop ("var"); |
19235870 RK |
820 | end case; |
821 | end; | |
822 | end if; | |
fbf5a39b | 823 | end Print_Expr; |
19235870 RK |
824 | |
825 | -- Start of processing for List_GCC_Expression | |
826 | ||
827 | begin | |
2175b50b | 828 | if No (U) then |
76b382d9 | 829 | Write_Unknown_Val; |
19235870 | 830 | else |
fbf5a39b | 831 | Print_Expr (U); |
19235870 RK |
832 | end if; |
833 | end List_GCC_Expression; | |
834 | ||
19992053 AC |
835 | ------------------------- |
836 | -- List_Linker_Section -- | |
837 | ------------------------- | |
838 | ||
839 | procedure List_Linker_Section (Ent : Entity_Id) is | |
24161618 HK |
840 | Args : List_Id; |
841 | Sect : Node_Id; | |
842 | ||
19992053 AC |
843 | begin |
844 | if Present (Linker_Section_Pragma (Ent)) then | |
24161618 HK |
845 | Args := Pragma_Argument_Associations (Linker_Section_Pragma (Ent)); |
846 | Sect := Expr_Value_S (Get_Pragma_Arg (Last (Args))); | |
847 | ||
1e7629b8 EB |
848 | if List_Representation_Info_To_JSON then |
849 | Write_Line (","); | |
850 | Write_Str (" ""Linker_Section"": """); | |
851 | else | |
852 | Write_Str ("pragma Linker_Section ("); | |
853 | List_Name (Ent); | |
854 | Write_Str (", """); | |
855 | end if; | |
19992053 | 856 | |
24161618 HK |
857 | pragma Assert (Nkind (Sect) = N_String_Literal); |
858 | String_To_Name_Buffer (Strval (Sect)); | |
19992053 | 859 | Write_Str (Name_Buffer (1 .. Name_Len)); |
1e7629b8 EB |
860 | Write_Str (""""); |
861 | if not List_Representation_Info_To_JSON then | |
862 | Write_Line (");"); | |
863 | end if; | |
19992053 AC |
864 | end if; |
865 | end List_Linker_Section; | |
866 | ||
1e7629b8 EB |
867 | ------------------- |
868 | -- List_Location -- | |
869 | ------------------- | |
870 | ||
871 | procedure List_Location (Ent : Entity_Id) is | |
872 | begin | |
873 | pragma Assert (List_Representation_Info_To_JSON); | |
874 | Write_Str (" ""location"": """); | |
875 | Write_Location (Sloc (Ent)); | |
876 | Write_Line (""","); | |
877 | end List_Location; | |
878 | ||
19235870 RK |
879 | --------------- |
880 | -- List_Name -- | |
881 | --------------- | |
882 | ||
883 | procedure List_Name (Ent : Entity_Id) is | |
fb95bfcc EB |
884 | C : Character; |
885 | ||
19235870 | 886 | begin |
ebbe4801 ES |
887 | -- In JSON mode, we recurse up to Standard. This is also valid in |
888 | -- default mode where we recurse up to the first compilation unit and | |
889 | -- should not get to Standard. | |
1e7629b8 | 890 | |
ebbe4801 | 891 | if Scope (Ent) = Standard_Standard then |
1e7629b8 EB |
892 | null; |
893 | elsif not Is_Compilation_Unit (Scope (Ent)) | |
894 | or else List_Representation_Info_To_JSON | |
895 | then | |
19235870 RK |
896 | List_Name (Scope (Ent)); |
897 | Write_Char ('.'); | |
898 | end if; | |
899 | ||
900 | Get_Unqualified_Decoded_Name_String (Chars (Ent)); | |
901 | Set_Casing (Unit_Casing); | |
fb95bfcc EB |
902 | |
903 | -- The name of operators needs to be properly escaped for JSON | |
904 | ||
905 | for J in 1 .. Name_Len loop | |
906 | C := Name_Buffer (J); | |
907 | if C = '"' and then List_Representation_Info_To_JSON then | |
908 | Write_Char ('\'); | |
909 | end if; | |
910 | Write_Char (C); | |
911 | end loop; | |
19235870 RK |
912 | end List_Name; |
913 | ||
914 | --------------------- | |
915 | -- List_Object_Info -- | |
916 | --------------------- | |
917 | ||
918 | procedure List_Object_Info (Ent : Entity_Id) is | |
919 | begin | |
d7ca4dfe BD |
920 | -- If size and alignment have not been computed (e.g. if we are in a |
921 | -- generic unit, or if the back end is not being run), don't try to | |
922 | -- print them. | |
db778c70 | 923 | |
d7ca4dfe BD |
924 | pragma Assert (Known_Esize (Ent) = Known_Alignment (Ent)); |
925 | if not Known_Alignment (Ent) then | |
db778c70 BD |
926 | return; |
927 | end if; | |
928 | ||
b5d3d113 | 929 | Write_Separator; |
19235870 | 930 | |
1e7629b8 EB |
931 | if List_Representation_Info_To_JSON then |
932 | Write_Line ("{"); | |
933 | ||
934 | Write_Str (" ""name"": """); | |
935 | List_Name (Ent); | |
936 | Write_Line (""","); | |
937 | List_Location (Ent); | |
19235870 | 938 | |
1e7629b8 EB |
939 | Write_Str (" ""Size"": "); |
940 | Write_Val (Esize (Ent)); | |
941 | Write_Line (","); | |
7672ab42 | 942 | |
1e7629b8 EB |
943 | Write_Str (" ""Alignment"": "); |
944 | Write_Val (Alignment (Ent)); | |
945 | ||
946 | List_Linker_Section (Ent); | |
947 | ||
948 | Write_Eol; | |
949 | Write_Line ("}"); | |
950 | else | |
951 | Write_Str ("for "); | |
952 | List_Name (Ent); | |
953 | Write_Str ("'Size use "); | |
954 | Write_Val (Esize (Ent)); | |
955 | Write_Line (";"); | |
956 | ||
957 | Write_Str ("for "); | |
958 | List_Name (Ent); | |
959 | Write_Str ("'Alignment use "); | |
960 | Write_Val (Alignment (Ent)); | |
961 | Write_Line (";"); | |
962 | ||
963 | List_Linker_Section (Ent); | |
964 | end if; | |
3c488e6c EB |
965 | |
966 | -- The type is relevant for an object | |
967 | ||
968 | if List_Representation_Info = 4 and then Is_Itype (Etype (Ent)) then | |
969 | Relevant_Entities.Set (Etype (Ent), True); | |
970 | end if; | |
19235870 RK |
971 | end List_Object_Info; |
972 | ||
973 | ---------------------- | |
974 | -- List_Record_Info -- | |
975 | ---------------------- | |
976 | ||
d9f8616e | 977 | procedure List_Record_Info (Ent : Entity_Id; Bytes_Big_Endian : Boolean) is |
1c912574 AC |
978 | procedure Compute_Max_Length |
979 | (Ent : Entity_Id; | |
980 | Starting_Position : Uint := Uint_0; | |
981 | Starting_First_Bit : Uint := Uint_0; | |
982 | Prefix_Length : Natural := 0); | |
983 | -- Internal recursive procedure to compute the max length | |
984 | ||
7883c42e EB |
985 | procedure List_Component_Layout |
986 | (Ent : Entity_Id; | |
987 | Starting_Position : Uint := Uint_0; | |
988 | Starting_First_Bit : Uint := Uint_0; | |
1e7629b8 EB |
989 | Prefix : String := ""; |
990 | Indent : Natural := 0); | |
7883c42e EB |
991 | -- Procedure to display the layout of a single component |
992 | ||
1c912574 AC |
993 | procedure List_Record_Layout |
994 | (Ent : Entity_Id; | |
995 | Starting_Position : Uint := Uint_0; | |
996 | Starting_First_Bit : Uint := Uint_0; | |
997 | Prefix : String := ""); | |
998 | -- Internal recursive procedure to display the layout | |
999 | ||
1e7629b8 | 1000 | procedure List_Structural_Record_Layout |
0f9ca030 | 1001 | (Ent : Entity_Id; |
2390451e | 1002 | Ext_Ent : Entity_Id; |
a372273b | 1003 | Ext_Level : Integer := 0; |
0f9ca030 EB |
1004 | Variant : Node_Id := Empty; |
1005 | Indent : Natural := 0); | |
2390451e EB |
1006 | -- Internal recursive procedure to display the structural layout. |
1007 | -- If Ext_Ent is not equal to Ent, it is an extension of Ent and | |
a372273b EB |
1008 | -- Ext_Level is the number of successive extensions between them, |
1009 | -- with the convention that this number is positive when we are | |
1010 | -- called from the fixed part of Ext_Ent and negative when we are | |
1011 | -- called from the variant part of Ext_Ent, if any; this is needed | |
1012 | -- because the fixed and variant parts of a parent of an extension | |
1013 | -- cannot be listed contiguously from this extension's viewpoint. | |
2390451e EB |
1014 | -- If Variant is present, it's for a variant in the variant part |
1015 | -- instead of the common part of Ent. Indent is the indentation. | |
1e7629b8 | 1016 | |
abbc4546 EB |
1017 | Incomplete_Layout : exception; |
1018 | -- Exception raised if the layout is incomplete in -gnatc mode | |
1019 | ||
1020 | Not_In_Extended_Main : exception; | |
1021 | -- Exception raised when an ancestor is not declared in the main unit | |
1022 | ||
1c912574 AC |
1023 | Max_Name_Length : Natural := 0; |
1024 | Max_Spos_Length : Natural := 0; | |
1025 | ||
1026 | ------------------------ | |
1027 | -- Compute_Max_Length -- | |
1028 | ------------------------ | |
1029 | ||
1030 | procedure Compute_Max_Length | |
1031 | (Ent : Entity_Id; | |
1032 | Starting_Position : Uint := Uint_0; | |
1033 | Starting_First_Bit : Uint := Uint_0; | |
1034 | Prefix_Length : Natural := 0) | |
1035 | is | |
3815f967 | 1036 | Comp : Entity_Id; |
19235870 | 1037 | |
1c912574 AC |
1038 | begin |
1039 | Comp := First_Component_Or_Discriminant (Ent); | |
1040 | while Present (Comp) loop | |
19235870 | 1041 | |
0f2d27e5 EB |
1042 | -- Skip a completely hidden discriminant or a discriminant in an |
1043 | -- unchecked union (since it is not there). | |
19235870 | 1044 | |
1c912574 | 1045 | if Ekind (Comp) = E_Discriminant |
0f2d27e5 EB |
1046 | and then (Is_Completely_Hidden (Comp) |
1047 | or else Is_Unchecked_Union (Ent)) | |
1c912574 AC |
1048 | then |
1049 | goto Continue; | |
1050 | end if; | |
19235870 | 1051 | |
c8e95568 EB |
1052 | -- Skip _Parent component in extension (to avoid overlap) |
1053 | ||
1054 | if Chars (Comp) = Name_uParent then | |
1055 | goto Continue; | |
1056 | end if; | |
1057 | ||
1c912574 | 1058 | -- All other cases |
19235870 | 1059 | |
1c912574 AC |
1060 | declare |
1061 | Ctyp : constant Entity_Id := Underlying_Type (Etype (Comp)); | |
1062 | Bofs : constant Uint := Component_Bit_Offset (Comp); | |
1063 | Npos : Uint; | |
1064 | Fbit : Uint; | |
1065 | Spos : Uint; | |
1066 | Sbit : Uint; | |
3815f967 | 1067 | |
1c912574 | 1068 | Name_Length : Natural; |
3815f967 | 1069 | |
1c912574 AC |
1070 | begin |
1071 | Get_Decoded_Name_String (Chars (Comp)); | |
1072 | Name_Length := Prefix_Length + Name_Len; | |
19235870 | 1073 | |
d7ca4dfe | 1074 | if Compile_Time_Known_Rep (Bofs) then |
1c912574 AC |
1075 | Npos := Bofs / SSU; |
1076 | Fbit := Bofs mod SSU; | |
19235870 | 1077 | |
1c912574 | 1078 | -- Complete annotation in case not done |
19235870 | 1079 | |
8de68eb3 | 1080 | if not Known_Normalized_First_Bit (Comp) then |
1c912574 AC |
1081 | Set_Normalized_Position (Comp, Npos); |
1082 | Set_Normalized_First_Bit (Comp, Fbit); | |
1083 | end if; | |
cc3a2986 | 1084 | |
1c912574 AC |
1085 | Spos := Starting_Position + Npos; |
1086 | Sbit := Starting_First_Bit + Fbit; | |
3815f967 | 1087 | |
1c912574 AC |
1088 | if Sbit >= SSU then |
1089 | Spos := Spos + 1; | |
1090 | Sbit := Sbit - SSU; | |
1091 | end if; | |
07fc65c4 | 1092 | |
1c912574 AC |
1093 | -- If extended information is requested, recurse fully into |
1094 | -- record components, i.e. skip the outer level. | |
74a78a4f | 1095 | |
1c912574 AC |
1096 | if List_Representation_Info_Extended |
1097 | and then Is_Record_Type (Ctyp) | |
1098 | then | |
1099 | Compute_Max_Length (Ctyp, Spos, Sbit, Name_Length + 1); | |
1100 | goto Continue; | |
1101 | end if; | |
19235870 | 1102 | |
9a36d1d1 | 1103 | UI_Image (Spos, Format => Decimal); |
d7ca4dfe BD |
1104 | else |
1105 | -- If the record is not packed, then we know that all fields | |
1106 | -- whose position is not specified have starting normalized | |
1107 | -- bit position of zero. | |
1108 | ||
1109 | if not Known_Normalized_First_Bit (Comp) | |
1110 | and then not Is_Packed (Ent) | |
1111 | then | |
1112 | Set_Normalized_First_Bit (Comp, Uint_0); | |
1113 | end if; | |
1114 | ||
1115 | UI_Image_Length := 2; -- For "??" marker | |
74a78a4f | 1116 | end if; |
3fbbbd1e | 1117 | |
1c912574 AC |
1118 | Max_Name_Length := Natural'Max (Max_Name_Length, Name_Length); |
1119 | Max_Spos_Length := | |
1120 | Natural'Max (Max_Spos_Length, UI_Image_Length); | |
1121 | end; | |
19235870 | 1122 | |
1c912574 AC |
1123 | <<Continue>> |
1124 | Next_Component_Or_Discriminant (Comp); | |
1125 | end loop; | |
1126 | end Compute_Max_Length; | |
a9a5b8ac | 1127 | |
7883c42e EB |
1128 | --------------------------- |
1129 | -- List_Component_Layout -- | |
1130 | --------------------------- | |
1131 | ||
1132 | procedure List_Component_Layout | |
1133 | (Ent : Entity_Id; | |
1134 | Starting_Position : Uint := Uint_0; | |
1135 | Starting_First_Bit : Uint := Uint_0; | |
1e7629b8 EB |
1136 | Prefix : String := ""; |
1137 | Indent : Natural := 0) | |
7883c42e EB |
1138 | is |
1139 | Esiz : constant Uint := Esize (Ent); | |
1140 | Npos : constant Uint := Normalized_Position (Ent); | |
1141 | Fbit : constant Uint := Normalized_First_Bit (Ent); | |
1142 | Spos : Uint; | |
76a71469 | 1143 | Sbit : Uint := No_Uint; |
7883c42e EB |
1144 | Lbit : Uint; |
1145 | ||
1146 | begin | |
1e7629b8 EB |
1147 | if List_Representation_Info_To_JSON then |
1148 | Spaces (Indent); | |
1149 | Write_Line (" {"); | |
1150 | Spaces (Indent); | |
1151 | Write_Str (" ""name"": """); | |
1152 | Write_Str (Prefix); | |
1153 | Write_Str (Name_Buffer (1 .. Name_Len)); | |
1154 | Write_Line (""","); | |
0f9ca030 EB |
1155 | if Ekind (Ent) = E_Discriminant then |
1156 | Spaces (Indent); | |
1157 | Write_Str (" ""discriminant"": "); | |
f9534f4b | 1158 | UI_Write (Discriminant_Number (Ent), Decimal); |
0f9ca030 EB |
1159 | Write_Line (","); |
1160 | end if; | |
1e7629b8 EB |
1161 | Spaces (Indent); |
1162 | Write_Str (" ""Position"": "); | |
1163 | else | |
1164 | Write_Str (" "); | |
1165 | Write_Str (Prefix); | |
1166 | Write_Str (Name_Buffer (1 .. Name_Len)); | |
1167 | Spaces (Max_Name_Length - Prefix'Length - Name_Len); | |
1168 | Write_Str (" at "); | |
1169 | end if; | |
7883c42e EB |
1170 | |
1171 | if Known_Static_Normalized_Position (Ent) then | |
1172 | Spos := Starting_Position + Npos; | |
1173 | Sbit := Starting_First_Bit + Fbit; | |
1174 | ||
1175 | if Sbit >= SSU then | |
1176 | Spos := Spos + 1; | |
1177 | end if; | |
1178 | ||
9a36d1d1 | 1179 | UI_Image (Spos, Format => Decimal); |
7883c42e EB |
1180 | Spaces (Max_Spos_Length - UI_Image_Length); |
1181 | Write_Str (UI_Image_Buffer (1 .. UI_Image_Length)); | |
1182 | ||
1183 | elsif Known_Normalized_Position (Ent) | |
b5f581cd | 1184 | and then List_Representation_Info >= 3 |
7883c42e EB |
1185 | then |
1186 | Spaces (Max_Spos_Length - 2); | |
1187 | ||
1188 | if Starting_Position /= Uint_0 then | |
f9534f4b | 1189 | UI_Write (Starting_Position, Decimal); |
7883c42e EB |
1190 | Write_Str (" + "); |
1191 | end if; | |
1192 | ||
1193 | Write_Val (Npos); | |
1194 | ||
1195 | else | |
1196 | Write_Unknown_Val; | |
1197 | end if; | |
1198 | ||
1e7629b8 EB |
1199 | if List_Representation_Info_To_JSON then |
1200 | Write_Line (","); | |
1201 | Spaces (Indent); | |
1202 | Write_Str (" ""First_Bit"": "); | |
1203 | else | |
1204 | Write_Str (" range "); | |
1205 | end if; | |
1206 | ||
db778c70 BD |
1207 | if Known_Static_Normalized_First_Bit (Ent) then |
1208 | Sbit := Starting_First_Bit + Fbit; | |
7883c42e | 1209 | |
db778c70 BD |
1210 | if Sbit >= SSU then |
1211 | Sbit := Sbit - SSU; | |
1212 | end if; | |
7883c42e | 1213 | |
db778c70 BD |
1214 | UI_Write (Sbit, Decimal); |
1215 | else | |
1216 | Write_Unknown_Val; | |
1217 | end if; | |
1e7629b8 EB |
1218 | |
1219 | if List_Representation_Info_To_JSON then | |
1220 | Write_Line (", "); | |
1221 | Spaces (Indent); | |
1222 | Write_Str (" ""Size"": "); | |
1223 | else | |
1224 | Write_Str (" .. "); | |
1225 | end if; | |
7883c42e | 1226 | |
b23cdc01 | 1227 | if Known_Static_Esize (Ent) |
7883c42e EB |
1228 | and then Known_Static_Normalized_First_Bit (Ent) |
1229 | then | |
1230 | Lbit := Sbit + Esiz - 1; | |
1231 | ||
1e7629b8 | 1232 | if List_Representation_Info_To_JSON then |
f9534f4b | 1233 | UI_Write (Esiz, Decimal); |
1e7629b8 | 1234 | else |
683ccd05 | 1235 | if Lbit >= 0 and then Lbit < 10 then |
1e7629b8 EB |
1236 | Write_Char (' '); |
1237 | end if; | |
7883c42e | 1238 | |
f9534f4b | 1239 | UI_Write (Lbit, Decimal); |
1e7629b8 | 1240 | end if; |
7883c42e | 1241 | |
b23cdc01 | 1242 | elsif List_Representation_Info < 3 or else not Known_Esize (Ent) then |
7883c42e EB |
1243 | Write_Unknown_Val; |
1244 | ||
1245 | -- List_Representation >= 3 and Known_Esize (Ent) | |
1246 | ||
1247 | else | |
1e7629b8 | 1248 | Write_Val (Esiz, Paren => not List_Representation_Info_To_JSON); |
7883c42e | 1249 | |
7883c42e EB |
1250 | -- Add appropriate first bit offset |
1251 | ||
1e7629b8 EB |
1252 | if not List_Representation_Info_To_JSON then |
1253 | if Sbit = 0 then | |
1254 | Write_Str (" - 1"); | |
7883c42e | 1255 | |
1e7629b8 EB |
1256 | elsif Sbit = 1 then |
1257 | null; | |
7883c42e | 1258 | |
1e7629b8 EB |
1259 | else |
1260 | Write_Str (" + "); | |
1261 | Write_Int (UI_To_Int (Sbit) - 1); | |
1262 | end if; | |
7883c42e EB |
1263 | end if; |
1264 | end if; | |
1265 | ||
1e7629b8 EB |
1266 | if List_Representation_Info_To_JSON then |
1267 | Write_Eol; | |
1268 | Spaces (Indent); | |
1269 | Write_Str (" }"); | |
1270 | else | |
1271 | Write_Line (";"); | |
1272 | end if; | |
3c488e6c EB |
1273 | |
1274 | -- The type is relevant for a component | |
1275 | ||
1276 | if List_Representation_Info = 4 and then Is_Itype (Etype (Ent)) then | |
1277 | Relevant_Entities.Set (Etype (Ent), True); | |
1278 | end if; | |
7883c42e EB |
1279 | end List_Component_Layout; |
1280 | ||
1c912574 AC |
1281 | ------------------------ |
1282 | -- List_Record_Layout -- | |
1283 | ------------------------ | |
19235870 | 1284 | |
1c912574 AC |
1285 | procedure List_Record_Layout |
1286 | (Ent : Entity_Id; | |
1287 | Starting_Position : Uint := Uint_0; | |
1288 | Starting_First_Bit : Uint := Uint_0; | |
1289 | Prefix : String := "") | |
1290 | is | |
81d85d4b EB |
1291 | Comp : Entity_Id; |
1292 | First : Boolean := True; | |
19235870 | 1293 | |
1c912574 AC |
1294 | begin |
1295 | Comp := First_Component_Or_Discriminant (Ent); | |
1296 | while Present (Comp) loop | |
3fbbbd1e | 1297 | |
0f2d27e5 EB |
1298 | -- Skip a completely hidden discriminant or a discriminant in an |
1299 | -- unchecked union (since it is not there). | |
3fbbbd1e | 1300 | |
1c912574 | 1301 | if Ekind (Comp) = E_Discriminant |
0f2d27e5 EB |
1302 | and then (Is_Completely_Hidden (Comp) |
1303 | or else Is_Unchecked_Union (Ent)) | |
1c912574 AC |
1304 | then |
1305 | goto Continue; | |
1306 | end if; | |
3fbbbd1e | 1307 | |
c8e95568 EB |
1308 | -- Skip _Parent component in extension (to avoid overlap) |
1309 | ||
1310 | if Chars (Comp) = Name_uParent then | |
1311 | goto Continue; | |
1312 | end if; | |
1313 | ||
1c912574 | 1314 | -- All other cases |
3fbbbd1e | 1315 | |
1c912574 AC |
1316 | declare |
1317 | Ctyp : constant Entity_Id := Underlying_Type (Etype (Comp)); | |
1c912574 AC |
1318 | Npos : constant Uint := Normalized_Position (Comp); |
1319 | Fbit : constant Uint := Normalized_First_Bit (Comp); | |
1320 | Spos : Uint; | |
1321 | Sbit : Uint; | |
a9a5b8ac | 1322 | |
1c912574 AC |
1323 | begin |
1324 | Get_Decoded_Name_String (Chars (Comp)); | |
1325 | Set_Casing (Unit_Casing); | |
19235870 | 1326 | |
1c912574 AC |
1327 | -- If extended information is requested, recurse fully into |
1328 | -- record components, i.e. skip the outer level. | |
19235870 | 1329 | |
1c912574 AC |
1330 | if List_Representation_Info_Extended |
1331 | and then Is_Record_Type (Ctyp) | |
1332 | and then Known_Static_Normalized_Position (Comp) | |
1333 | and then Known_Static_Normalized_First_Bit (Comp) | |
1334 | then | |
1335 | Spos := Starting_Position + Npos; | |
1336 | Sbit := Starting_First_Bit + Fbit; | |
3815f967 | 1337 | |
1c912574 AC |
1338 | if Sbit >= SSU then |
1339 | Spos := Spos + 1; | |
1340 | Sbit := Sbit - SSU; | |
1341 | end if; | |
3815f967 | 1342 | |
1c912574 AC |
1343 | List_Record_Layout (Ctyp, |
1344 | Spos, Sbit, Prefix & Name_Buffer (1 .. Name_Len) & "."); | |
3815f967 | 1345 | |
1c912574 AC |
1346 | goto Continue; |
1347 | end if; | |
19235870 | 1348 | |
81d85d4b EB |
1349 | if List_Representation_Info_To_JSON then |
1350 | if First then | |
1351 | Write_Eol; | |
1352 | First := False; | |
1353 | else | |
1354 | Write_Line (","); | |
1355 | end if; | |
1356 | end if; | |
1357 | ||
2390451e EB |
1358 | -- The Parent_Subtype in an extension is not back-annotated |
1359 | ||
1360 | List_Component_Layout ( | |
1361 | (if Known_Normalized_Position (Comp) | |
1362 | then Comp | |
1363 | else Original_Record_Component (Comp)), | |
7883c42e | 1364 | Starting_Position, Starting_First_Bit, Prefix); |
1c912574 | 1365 | end; |
19235870 | 1366 | |
1c912574 AC |
1367 | <<Continue>> |
1368 | Next_Component_Or_Discriminant (Comp); | |
1369 | end loop; | |
1370 | end List_Record_Layout; | |
1371 | ||
1e7629b8 EB |
1372 | ----------------------------------- |
1373 | -- List_Structural_Record_Layout -- | |
1374 | ----------------------------------- | |
1375 | ||
1376 | procedure List_Structural_Record_Layout | |
0f9ca030 | 1377 | (Ent : Entity_Id; |
2390451e | 1378 | Ext_Ent : Entity_Id; |
a372273b | 1379 | Ext_Level : Integer := 0; |
0f9ca030 EB |
1380 | Variant : Node_Id := Empty; |
1381 | Indent : Natural := 0) | |
1e7629b8 | 1382 | is |
0f9ca030 | 1383 | function Derived_Discriminant (Disc : Entity_Id) return Entity_Id; |
2390451e | 1384 | -- This function assumes that Ext_Ent is an extension of Ent. |
0f9ca030 EB |
1385 | -- Disc is a discriminant of Ent that does not itself constrain a |
1386 | -- discriminant of the parent type of Ent. Return the discriminant | |
2390451e | 1387 | -- of Ext_Ent that ultimately constrains Disc, if any. |
0f9ca030 EB |
1388 | |
1389 | ---------------------------- | |
1390 | -- Derived_Discriminant -- | |
1391 | ---------------------------- | |
1392 | ||
1393 | function Derived_Discriminant (Disc : Entity_Id) return Entity_Id is | |
f537fc00 HK |
1394 | Corr_Disc : Entity_Id; |
1395 | Derived_Disc : Entity_Id; | |
0f9ca030 EB |
1396 | |
1397 | begin | |
a372273b EB |
1398 | -- Deal with an extension of a type with unknown discriminants |
1399 | ||
1400 | if Has_Unknown_Discriminants (Ext_Ent) | |
1401 | and then Present (Underlying_Record_View (Ext_Ent)) | |
1402 | then | |
1403 | Derived_Disc := | |
1404 | First_Discriminant (Underlying_Record_View (Ext_Ent)); | |
1405 | else | |
1406 | Derived_Disc := First_Discriminant (Ext_Ent); | |
1407 | end if; | |
0f9ca030 EB |
1408 | |
1409 | -- Loop over the discriminants of the extension | |
1410 | ||
1411 | while Present (Derived_Disc) loop | |
1412 | ||
1413 | -- Check if this discriminant constrains another discriminant. | |
1414 | -- If so, find the ultimately constrained discriminant and | |
1415 | -- compare with the original components in the base type. | |
1416 | ||
1417 | if Present (Corresponding_Discriminant (Derived_Disc)) then | |
1418 | Corr_Disc := Corresponding_Discriminant (Derived_Disc); | |
1419 | ||
1420 | while Present (Corresponding_Discriminant (Corr_Disc)) loop | |
1421 | Corr_Disc := Corresponding_Discriminant (Corr_Disc); | |
1422 | end loop; | |
1423 | ||
f537fc00 HK |
1424 | if Original_Record_Component (Corr_Disc) = |
1425 | Original_Record_Component (Disc) | |
0f9ca030 EB |
1426 | then |
1427 | return Derived_Disc; | |
1428 | end if; | |
1429 | end if; | |
1430 | ||
0f2d27e5 | 1431 | Next_Discriminant (Derived_Disc); |
0f9ca030 EB |
1432 | end loop; |
1433 | ||
2390451e | 1434 | -- Disc is not constrained by a discriminant of Ext_Ent |
0f9ca030 EB |
1435 | |
1436 | return Empty; | |
1437 | end Derived_Discriminant; | |
1438 | ||
1439 | -- Local declarations | |
1440 | ||
1e7629b8 EB |
1441 | Comp : Node_Id; |
1442 | Comp_List : Node_Id; | |
1e7629b8 | 1443 | First : Boolean := True; |
a372273b | 1444 | Parent_Ent : Entity_Id := Empty; |
f537fc00 | 1445 | Var : Node_Id; |
1e7629b8 | 1446 | |
0f9ca030 EB |
1447 | -- Start of processing for List_Structural_Record_Layout |
1448 | ||
1e7629b8 EB |
1449 | begin |
1450 | -- If we are dealing with a variant, just process the components | |
1451 | ||
1452 | if Present (Variant) then | |
1453 | Comp_List := Component_List (Variant); | |
1454 | ||
1455 | -- Otherwise, we are dealing with the full record and need to get | |
1456 | -- to its definition in order to retrieve its structural layout. | |
1457 | ||
1458 | else | |
1459 | declare | |
1460 | Definition : Node_Id := | |
f537fc00 HK |
1461 | Type_Definition (Declaration_Node (Ent)); |
1462 | ||
1e7629b8 | 1463 | Is_Extension : constant Boolean := |
f537fc00 HK |
1464 | Is_Tagged_Type (Ent) |
1465 | and then Nkind (Definition) = | |
1466 | N_Derived_Type_Definition; | |
1467 | ||
1468 | Disc : Entity_Id; | |
1469 | Listed_Disc : Entity_Id; | |
abbc4546 | 1470 | Parent_Type : Entity_Id; |
0f9ca030 | 1471 | |
1e7629b8 EB |
1472 | begin |
1473 | -- If this is an extension, first list the layout of the parent | |
1474 | -- and then proceed to the extension part, if any. | |
1475 | ||
1476 | if Is_Extension then | |
abbc4546 EB |
1477 | Parent_Type := Parent_Subtype (Ent); |
1478 | if No (Parent_Type) then | |
1479 | raise Incomplete_Layout; | |
1480 | end if; | |
1481 | ||
1482 | if Is_Private_Type (Parent_Type) then | |
1483 | Parent_Type := Full_View (Parent_Type); | |
1484 | pragma Assert (Present (Parent_Type)); | |
1485 | end if; | |
1486 | ||
2390451e EB |
1487 | -- Do not list variants if one of them has been selected |
1488 | ||
1489 | if Has_Static_Discriminants (Parent_Type) then | |
1490 | List_Record_Layout (Parent_Type); | |
1491 | ||
1492 | else | |
1493 | Parent_Type := Base_Type (Parent_Type); | |
6fa5f508 EB |
1494 | |
1495 | if Is_Private_Type (Parent_Type) then | |
1496 | Parent_Type := Full_View (Parent_Type); | |
1497 | pragma Assert (Present (Parent_Type)); | |
1498 | end if; | |
1499 | ||
2390451e EB |
1500 | if not In_Extended_Main_Source_Unit (Parent_Type) then |
1501 | raise Not_In_Extended_Main; | |
1502 | end if; | |
1503 | ||
a372273b EB |
1504 | Parent_Ent := Parent_Type; |
1505 | if Ext_Level >= 0 then | |
1506 | List_Structural_Record_Layout | |
1507 | (Parent_Ent, Ext_Ent, Ext_Level + 1); | |
1508 | end if; | |
abbc4546 EB |
1509 | end if; |
1510 | ||
9104d201 | 1511 | First := False; |
1e7629b8 EB |
1512 | |
1513 | if Present (Record_Extension_Part (Definition)) then | |
1514 | Definition := Record_Extension_Part (Definition); | |
1515 | end if; | |
1516 | end if; | |
1517 | ||
1518 | -- If the record has discriminants and is not an unchecked | |
0f2d27e5 EB |
1519 | -- union, then display them now. Note that, even if this is |
1520 | -- a structural layout, we list the visible discriminants. | |
1e7629b8 EB |
1521 | |
1522 | if Has_Discriminants (Ent) | |
1523 | and then not Is_Unchecked_Union (Ent) | |
a372273b | 1524 | and then Ext_Level >= 0 |
1e7629b8 | 1525 | then |
0f2d27e5 | 1526 | Disc := First_Discriminant (Ent); |
1e7629b8 EB |
1527 | while Present (Disc) loop |
1528 | ||
1529 | -- If this is a record extension and the discriminant is | |
1530 | -- the renaming of another discriminant, skip it. | |
1531 | ||
1532 | if Is_Extension | |
1533 | and then Present (Corresponding_Discriminant (Disc)) | |
1534 | then | |
1535 | goto Continue_Disc; | |
1536 | end if; | |
1537 | ||
0f9ca030 EB |
1538 | -- If this is the parent type of an extension, retrieve |
1539 | -- the derived discriminant from the extension, if any. | |
1540 | ||
2390451e | 1541 | if Ent /= Ext_Ent then |
0f9ca030 EB |
1542 | Listed_Disc := Derived_Discriminant (Disc); |
1543 | ||
1544 | if No (Listed_Disc) then | |
1545 | goto Continue_Disc; | |
a372273b EB |
1546 | |
1547 | elsif not Known_Normalized_Position (Listed_Disc) then | |
1548 | Listed_Disc := | |
1549 | Original_Record_Component (Listed_Disc); | |
0f9ca030 | 1550 | end if; |
a372273b | 1551 | |
0f9ca030 EB |
1552 | else |
1553 | Listed_Disc := Disc; | |
1554 | end if; | |
1555 | ||
1556 | Get_Decoded_Name_String (Chars (Listed_Disc)); | |
1e7629b8 EB |
1557 | Set_Casing (Unit_Casing); |
1558 | ||
1559 | if First then | |
1560 | Write_Eol; | |
1561 | First := False; | |
1562 | else | |
1563 | Write_Line (","); | |
1564 | end if; | |
1565 | ||
0f9ca030 | 1566 | List_Component_Layout (Listed_Disc, Indent => Indent); |
1e7629b8 EB |
1567 | |
1568 | <<Continue_Disc>> | |
0f2d27e5 | 1569 | Next_Discriminant (Disc); |
1e7629b8 EB |
1570 | end loop; |
1571 | end if; | |
1572 | ||
1573 | Comp_List := Component_List (Definition); | |
1574 | end; | |
1575 | end if; | |
1576 | ||
1577 | -- Bail out for the null record | |
1578 | ||
1579 | if No (Comp_List) then | |
1580 | return; | |
1581 | end if; | |
1582 | ||
1583 | -- Now deal with the regular components, if any | |
1584 | ||
a372273b EB |
1585 | if Present (Component_Items (Comp_List)) |
1586 | and then (Present (Variant) or else Ext_Level >= 0) | |
1587 | then | |
1e7629b8 EB |
1588 | Comp := First_Non_Pragma (Component_Items (Comp_List)); |
1589 | while Present (Comp) loop | |
1590 | ||
1591 | -- Skip _Parent component in extension (to avoid overlap) | |
1592 | ||
1593 | if Chars (Defining_Identifier (Comp)) = Name_uParent then | |
1594 | goto Continue_Comp; | |
1595 | end if; | |
1596 | ||
1597 | Get_Decoded_Name_String (Chars (Defining_Identifier (Comp))); | |
1598 | Set_Casing (Unit_Casing); | |
1599 | ||
1600 | if First then | |
1601 | Write_Eol; | |
1602 | First := False; | |
1603 | else | |
1604 | Write_Line (","); | |
1605 | end if; | |
1606 | ||
1607 | List_Component_Layout | |
1608 | (Defining_Identifier (Comp), Indent => Indent); | |
1609 | ||
1610 | <<Continue_Comp>> | |
1611 | Next_Non_Pragma (Comp); | |
1612 | end loop; | |
1613 | end if; | |
1614 | ||
a372273b EB |
1615 | -- Stop there if we are called from the fixed part of Ext_Ent, |
1616 | -- we'll do the variant part when called from its variant part. | |
1617 | ||
1618 | if Ext_Level > 0 then | |
1619 | return; | |
1620 | end if; | |
1621 | ||
1622 | -- List the layout of the variant part of the parent, if any | |
1623 | ||
1624 | if Present (Parent_Ent) then | |
1625 | List_Structural_Record_Layout | |
1626 | (Parent_Ent, Ext_Ent, Ext_Level - 1); | |
1627 | end if; | |
1628 | ||
1e7629b8 EB |
1629 | -- We are done if there is no variant part |
1630 | ||
1631 | if No (Variant_Part (Comp_List)) then | |
1632 | return; | |
1633 | end if; | |
1634 | ||
1635 | Write_Eol; | |
1636 | Spaces (Indent); | |
1637 | Write_Line (" ],"); | |
1638 | Spaces (Indent); | |
2390451e | 1639 | Write_Str (" """); |
a372273b | 1640 | for J in Ext_Level .. -1 loop |
2390451e EB |
1641 | Write_Str ("parent_"); |
1642 | end loop; | |
1643 | Write_Str ("variant"" : ["); | |
1e7629b8 EB |
1644 | |
1645 | -- Otherwise we recurse on each variant | |
1646 | ||
1647 | Var := First_Non_Pragma (Variants (Variant_Part (Comp_List))); | |
1648 | First := True; | |
1649 | while Present (Var) loop | |
1650 | if First then | |
1651 | Write_Eol; | |
1652 | First := False; | |
1653 | else | |
1654 | Write_Line (","); | |
1655 | end if; | |
1656 | ||
1657 | Spaces (Indent); | |
1658 | Write_Line (" {"); | |
1659 | Spaces (Indent); | |
1660 | Write_Str (" ""present"": "); | |
1661 | Write_Val (Present_Expr (Var)); | |
1662 | Write_Line (","); | |
1663 | Spaces (Indent); | |
1664 | Write_Str (" ""record"": ["); | |
1665 | ||
2390451e EB |
1666 | List_Structural_Record_Layout |
1667 | (Ent, Ext_Ent, Ext_Level, Var, Indent + 4); | |
1e7629b8 EB |
1668 | |
1669 | Write_Eol; | |
1670 | Spaces (Indent); | |
1671 | Write_Line (" ]"); | |
1672 | Spaces (Indent); | |
1673 | Write_Str (" }"); | |
1674 | Next_Non_Pragma (Var); | |
1675 | end loop; | |
1676 | end List_Structural_Record_Layout; | |
1677 | ||
3815f967 AC |
1678 | -- Start of processing for List_Record_Info |
1679 | ||
1c912574 | 1680 | begin |
b5d3d113 | 1681 | Write_Separator; |
1c912574 | 1682 | |
1e7629b8 EB |
1683 | if List_Representation_Info_To_JSON then |
1684 | Write_Line ("{"); | |
1685 | end if; | |
1686 | ||
6f65c7ee | 1687 | List_Common_Type_Info (Ent); |
1c912574 AC |
1688 | |
1689 | -- First find out max line length and max starting position | |
1690 | -- length, for the purpose of lining things up nicely. | |
1691 | ||
1692 | Compute_Max_Length (Ent); | |
1693 | ||
1694 | -- Then do actual output based on those values | |
1695 | ||
1e7629b8 EB |
1696 | if List_Representation_Info_To_JSON then |
1697 | Write_Line (","); | |
1698 | Write_Str (" ""record"": ["); | |
1699 | ||
abbc4546 EB |
1700 | -- ??? We can output structural layout only for base types fully |
1701 | -- declared in the extended main source unit for the time being, | |
1702 | -- because otherwise declarations might not be processed at all. | |
1703 | ||
81d85d4b | 1704 | if Is_Base_Type (Ent) then |
abbc4546 EB |
1705 | begin |
1706 | List_Structural_Record_Layout (Ent, Ent); | |
1707 | ||
1708 | exception | |
1709 | when Incomplete_Layout | |
1710 | | Not_In_Extended_Main | |
1711 | => | |
1712 | List_Record_Layout (Ent); | |
1713 | ||
1714 | when others => | |
1715 | raise Program_Error; | |
1716 | end; | |
81d85d4b EB |
1717 | else |
1718 | List_Record_Layout (Ent); | |
1719 | end if; | |
1e7629b8 EB |
1720 | |
1721 | Write_Eol; | |
1722 | Write_Str (" ]"); | |
1723 | else | |
1724 | Write_Str ("for "); | |
1725 | List_Name (Ent); | |
1726 | Write_Line (" use record"); | |
1727 | ||
1728 | List_Record_Layout (Ent); | |
19235870 | 1729 | |
1e7629b8 EB |
1730 | Write_Line ("end record;"); |
1731 | end if; | |
d9f8616e AC |
1732 | |
1733 | List_Scalar_Storage_Order (Ent, Bytes_Big_Endian); | |
7672ab42 EB |
1734 | |
1735 | List_Linker_Section (Ent); | |
1e7629b8 EB |
1736 | |
1737 | if List_Representation_Info_To_JSON then | |
1738 | Write_Eol; | |
1739 | Write_Line ("}"); | |
1740 | end if; | |
76ccee8f EB |
1741 | |
1742 | -- The type is relevant for a record subtype | |
1743 | ||
1744 | if List_Representation_Info = 4 | |
1745 | and then not Is_Base_Type (Ent) | |
1746 | and then Is_Itype (Etype (Ent)) | |
1747 | then | |
1748 | Relevant_Entities.Set (Etype (Ent), True); | |
1749 | end if; | |
19235870 RK |
1750 | end List_Record_Info; |
1751 | ||
1752 | ------------------- | |
1753 | -- List_Rep_Info -- | |
1754 | ------------------- | |
1755 | ||
d9f8616e | 1756 | procedure List_Rep_Info (Bytes_Big_Endian : Boolean) is |
19235870 RK |
1757 | Col : Nat; |
1758 | ||
1759 | begin | |
fbf5a39b AC |
1760 | if List_Representation_Info /= 0 |
1761 | or else List_Representation_Info_Mechanisms | |
1762 | then | |
b5d3d113 EB |
1763 | -- For the normal case, we output a single JSON stream |
1764 | ||
1765 | if not List_Representation_Info_To_File | |
1766 | and then List_Representation_Info_To_JSON | |
1767 | then | |
1768 | Write_Line ("["); | |
1769 | Need_Separator := False; | |
1770 | end if; | |
1771 | ||
fbf5a39b AC |
1772 | for U in Main_Unit .. Last_Unit loop |
1773 | if In_Extended_Main_Source_Unit (Cunit_Entity (U)) then | |
d436b30d | 1774 | Unit_Casing := Identifier_Casing (Source_Index (U)); |
07fc65c4 | 1775 | |
b5f581cd EB |
1776 | if List_Representation_Info = 4 then |
1777 | Relevant_Entities.Reset; | |
1778 | end if; | |
1779 | ||
fbf5a39b | 1780 | -- Normal case, list to standard output |
07fc65c4 | 1781 | |
de9b2a96 EB |
1782 | if not List_Representation_Info_To_File then |
1783 | if not List_Representation_Info_To_JSON then | |
1784 | Write_Eol; | |
1785 | Write_Str ("Representation information for unit "); | |
1786 | Write_Unit_Name (Unit_Name (U)); | |
1787 | Col := Column; | |
1788 | Write_Eol; | |
1789 | ||
1790 | for J in 1 .. Col - 1 loop | |
1791 | Write_Char ('-'); | |
1792 | end loop; | |
1793 | ||
1794 | Write_Eol; | |
b5d3d113 | 1795 | Need_Separator := True; |
de9b2a96 | 1796 | end if; |
07fc65c4 | 1797 | |
d9f8616e | 1798 | List_Entities (Cunit_Entity (U), Bytes_Big_Endian); |
07fc65c4 | 1799 | |
fbf5a39b | 1800 | -- List representation information to file |
07fc65c4 | 1801 | |
fbf5a39b | 1802 | else |
4b54d939 | 1803 | Create_Repinfo_File |
1c28fe3a | 1804 | (Get_Name_String (File_Name (Source_Index (U)))); |
fbf5a39b | 1805 | Set_Special_Output (Write_Info_Line'Access); |
b5d3d113 EB |
1806 | if List_Representation_Info_To_JSON then |
1807 | Write_Line ("["); | |
1808 | end if; | |
1809 | Need_Separator := False; | |
d9f8616e | 1810 | List_Entities (Cunit_Entity (U), Bytes_Big_Endian); |
b5d3d113 EB |
1811 | if List_Representation_Info_To_JSON then |
1812 | Write_Line ("]"); | |
1813 | end if; | |
e3548b69 | 1814 | Cancel_Special_Output; |
4b54d939 | 1815 | Close_Repinfo_File; |
fbf5a39b | 1816 | end if; |
07fc65c4 | 1817 | end if; |
fbf5a39b | 1818 | end loop; |
b5d3d113 EB |
1819 | |
1820 | if not List_Representation_Info_To_File | |
1821 | and then List_Representation_Info_To_JSON | |
1822 | then | |
1823 | Write_Line ("]"); | |
1824 | end if; | |
fbf5a39b | 1825 | end if; |
19235870 RK |
1826 | end List_Rep_Info; |
1827 | ||
d9f8616e AC |
1828 | ------------------------------- |
1829 | -- List_Scalar_Storage_Order -- | |
1830 | ------------------------------- | |
1831 | ||
1832 | procedure List_Scalar_Storage_Order | |
1833 | (Ent : Entity_Id; | |
1834 | Bytes_Big_Endian : Boolean) | |
1835 | is | |
7ed57189 AC |
1836 | procedure List_Attr (Attr_Name : String; Is_Reversed : Boolean); |
1837 | -- Show attribute definition clause for Attr_Name (an endianness | |
1838 | -- attribute), depending on whether or not the endianness is reversed | |
1839 | -- compared to native endianness. | |
d9f8616e AC |
1840 | |
1841 | --------------- | |
1842 | -- List_Attr -- | |
1843 | --------------- | |
1844 | ||
7ed57189 | 1845 | procedure List_Attr (Attr_Name : String; Is_Reversed : Boolean) is |
d9f8616e | 1846 | begin |
1e7629b8 EB |
1847 | if List_Representation_Info_To_JSON then |
1848 | Write_Line (","); | |
972d2984 EB |
1849 | Write_Str (" """); |
1850 | Write_Str (Attr_Name); | |
1851 | Write_Str (""": ""System."); | |
1e7629b8 EB |
1852 | else |
1853 | Write_Str ("for "); | |
1854 | List_Name (Ent); | |
972d2984 EB |
1855 | Write_Char ('''); |
1856 | Write_Str (Attr_Name); | |
1857 | Write_Str (" use System."); | |
1e7629b8 | 1858 | end if; |
489c6e19 | 1859 | |
7ed57189 | 1860 | if Bytes_Big_Endian xor Is_Reversed then |
d9f8616e AC |
1861 | Write_Str ("High"); |
1862 | else | |
1863 | Write_Str ("Low"); | |
1864 | end if; | |
489c6e19 | 1865 | |
1e7629b8 EB |
1866 | Write_Str ("_Order_First"); |
1867 | if List_Representation_Info_To_JSON then | |
1868 | Write_Str (""""); | |
1869 | else | |
1870 | Write_Line (";"); | |
1871 | end if; | |
d9f8616e AC |
1872 | end List_Attr; |
1873 | ||
7ed57189 AC |
1874 | List_SSO : constant Boolean := |
1875 | Has_Rep_Item (Ent, Name_Scalar_Storage_Order) | |
1876 | or else SSO_Set_Low_By_Default (Ent) | |
1877 | or else SSO_Set_High_By_Default (Ent); | |
31fde973 GD |
1878 | -- Scalar_Storage_Order is displayed if specified explicitly or set by |
1879 | -- Default_Scalar_Storage_Order. | |
7ed57189 | 1880 | |
d9f8616e AC |
1881 | -- Start of processing for List_Scalar_Storage_Order |
1882 | ||
1883 | begin | |
7ed57189 | 1884 | -- For record types, list Bit_Order if not default, or if SSO is shown |
d9f8616e | 1885 | |
6aaab508 JS |
1886 | -- Also, when -gnatR4 is in effect always list bit order and scalar |
1887 | -- storage order explicitly, so that you don't need to know the native | |
1888 | -- endianness of the target for which the output was produced in order | |
1889 | -- to interpret it. | |
1890 | ||
7ed57189 | 1891 | if Is_Record_Type (Ent) |
6aaab508 JS |
1892 | and then (List_SSO |
1893 | or else Reverse_Bit_Order (Ent) | |
1894 | or else List_Representation_Info = 4) | |
220d1fd9 | 1895 | then |
7ed57189 AC |
1896 | List_Attr ("Bit_Order", Reverse_Bit_Order (Ent)); |
1897 | end if; | |
d9f8616e | 1898 | |
7ed57189 AC |
1899 | -- List SSO if required. If not, then storage is supposed to be in |
1900 | -- native order. | |
489c6e19 | 1901 | |
6aaab508 | 1902 | if List_SSO or else List_Representation_Info = 4 then |
7ed57189 AC |
1903 | List_Attr ("Scalar_Storage_Order", Reverse_Storage_Order (Ent)); |
1904 | else | |
1905 | pragma Assert (not Reverse_Storage_Order (Ent)); | |
1906 | null; | |
d9f8616e AC |
1907 | end if; |
1908 | end List_Scalar_Storage_Order; | |
1909 | ||
6f65c7ee EB |
1910 | -------------------------- |
1911 | -- List_Subprogram_Info -- | |
1912 | -------------------------- | |
1913 | ||
1914 | procedure List_Subprogram_Info (Ent : Entity_Id) is | |
1915 | First : Boolean := True; | |
1916 | Plen : Natural; | |
1917 | Form : Entity_Id; | |
19235870 | 1918 | |
19235870 | 1919 | begin |
b5d3d113 | 1920 | Write_Separator; |
6f65c7ee | 1921 | |
1e7629b8 | 1922 | if List_Representation_Info_To_JSON then |
6f65c7ee | 1923 | Write_Line ("{"); |
1e7629b8 EB |
1924 | Write_Str (" ""name"": """); |
1925 | List_Name (Ent); | |
1926 | Write_Line (""","); | |
1927 | List_Location (Ent); | |
6f65c7ee EB |
1928 | |
1929 | Write_Str (" ""Convention"": """); | |
1930 | else | |
1931 | case Ekind (Ent) is | |
1932 | when E_Function => | |
1933 | Write_Str ("function "); | |
1934 | ||
1935 | when E_Operator => | |
1936 | Write_Str ("operator "); | |
1937 | ||
1938 | when E_Procedure => | |
1939 | Write_Str ("procedure "); | |
1940 | ||
1941 | when E_Subprogram_Type => | |
1942 | Write_Str ("type "); | |
1943 | ||
1944 | when E_Entry | |
1945 | | E_Entry_Family | |
1946 | => | |
1947 | Write_Str ("entry "); | |
1948 | ||
1949 | when others => | |
1950 | raise Program_Error; | |
1951 | end case; | |
1952 | ||
1953 | List_Name (Ent); | |
1954 | Write_Str (" declared at "); | |
1955 | Write_Location (Sloc (Ent)); | |
1956 | Write_Eol; | |
1957 | ||
1958 | Write_Str ("convention : "); | |
1e7629b8 EB |
1959 | end if; |
1960 | ||
6f65c7ee EB |
1961 | case Convention (Ent) is |
1962 | when Convention_Ada => | |
1963 | Write_Str ("Ada"); | |
07fc65c4 | 1964 | |
6f65c7ee EB |
1965 | when Convention_Ada_Pass_By_Copy => |
1966 | Write_Str ("Ada_Pass_By_Copy"); | |
1967 | ||
1968 | when Convention_Ada_Pass_By_Reference => | |
1969 | Write_Str ("Ada_Pass_By_Reference"); | |
1970 | ||
1971 | when Convention_Intrinsic => | |
1972 | Write_Str ("Intrinsic"); | |
1973 | ||
1974 | when Convention_Entry => | |
1975 | Write_Str ("Entry"); | |
1976 | ||
1977 | when Convention_Protected => | |
1978 | Write_Str ("Protected"); | |
07fc65c4 | 1979 | |
6f65c7ee EB |
1980 | when Convention_Assembler => |
1981 | Write_Str ("Assembler"); | |
1982 | ||
1983 | when Convention_C => | |
1984 | Write_Str ("C"); | |
1985 | ||
fd664071 EB |
1986 | when Convention_C_Variadic => |
1987 | declare | |
1988 | N : Nat := | |
1989 | Convention_Id'Pos (Convention (Ent)) - | |
1990 | Convention_Id'Pos (Convention_C_Variadic_0); | |
1991 | begin | |
1992 | Write_Str ("C_Variadic_"); | |
1993 | if N >= 10 then | |
1994 | Write_Char ('1'); | |
1995 | N := N - 10; | |
1996 | end if; | |
1997 | pragma Assert (N < 10); | |
1998 | Write_Char (Character'Val (Character'Pos ('0') + N)); | |
1999 | end; | |
2000 | ||
6f65c7ee EB |
2001 | when Convention_COBOL => |
2002 | Write_Str ("COBOL"); | |
2003 | ||
2004 | when Convention_CPP => | |
2005 | Write_Str ("C++"); | |
2006 | ||
2007 | when Convention_Fortran => | |
2008 | Write_Str ("Fortran"); | |
2009 | ||
2010 | when Convention_Stdcall => | |
2011 | Write_Str ("Stdcall"); | |
2012 | ||
2013 | when Convention_Stubbed => | |
2014 | Write_Str ("Stubbed"); | |
2015 | end case; | |
2016 | ||
2017 | if List_Representation_Info_To_JSON then | |
2018 | Write_Line (""","); | |
2019 | Write_Str (" ""formal"": ["); | |
07fc65c4 | 2020 | else |
6f65c7ee EB |
2021 | Write_Eol; |
2022 | end if; | |
19235870 | 2023 | |
6f65c7ee EB |
2024 | -- Find max length of formal name |
2025 | ||
2026 | Plen := 0; | |
2027 | Form := First_Formal (Ent); | |
2028 | while Present (Form) loop | |
2029 | Get_Unqualified_Decoded_Name_String (Chars (Form)); | |
2030 | ||
2031 | if Name_Len > Plen then | |
2032 | Plen := Name_Len; | |
2033 | end if; | |
2034 | ||
2035 | Next_Formal (Form); | |
2036 | end loop; | |
2037 | ||
2038 | -- Output formals and mechanisms | |
2039 | ||
2040 | Form := First_Formal (Ent); | |
2041 | while Present (Form) loop | |
2042 | Get_Unqualified_Decoded_Name_String (Chars (Form)); | |
2043 | Set_Casing (Unit_Casing); | |
2044 | ||
2045 | if List_Representation_Info_To_JSON then | |
2046 | if First then | |
2047 | Write_Eol; | |
2048 | First := False; | |
1e7629b8 | 2049 | else |
6f65c7ee | 2050 | Write_Line (","); |
1e7629b8 | 2051 | end if; |
19235870 | 2052 | |
6f65c7ee EB |
2053 | Write_Line (" {"); |
2054 | Write_Str (" ""name"": """); | |
2055 | Write_Str (Name_Buffer (1 .. Name_Len)); | |
2056 | Write_Line (""","); | |
19235870 | 2057 | |
6f65c7ee EB |
2058 | Write_Str (" ""mechanism"": """); |
2059 | Write_Mechanism (Mechanism (Form)); | |
2060 | Write_Line (""""); | |
2061 | Write_Str (" }"); | |
07fc65c4 | 2062 | else |
6f65c7ee EB |
2063 | while Name_Len <= Plen loop |
2064 | Name_Len := Name_Len + 1; | |
2065 | Name_Buffer (Name_Len) := ' '; | |
2066 | end loop; | |
19235870 | 2067 | |
6f65c7ee EB |
2068 | Write_Str (" "); |
2069 | Write_Str (Name_Buffer (1 .. Plen + 1)); | |
2070 | Write_Str (": passed by "); | |
1e7629b8 | 2071 | |
6f65c7ee EB |
2072 | Write_Mechanism (Mechanism (Form)); |
2073 | Write_Eol; | |
2074 | end if; | |
1e7629b8 | 2075 | |
6f65c7ee EB |
2076 | Next_Formal (Form); |
2077 | end loop; | |
2078 | ||
2079 | if List_Representation_Info_To_JSON then | |
2080 | Write_Eol; | |
2081 | Write_Str (" ]"); | |
2082 | end if; | |
2083 | ||
2084 | if Ekind (Ent) = E_Function then | |
2085 | if List_Representation_Info_To_JSON then | |
2086 | Write_Line (","); | |
2087 | Write_Str (" ""mechanism"": """); | |
2088 | Write_Mechanism (Mechanism (Ent)); | |
2089 | Write_Str (""""); | |
2090 | else | |
2091 | Write_Str ("returns by "); | |
2092 | Write_Mechanism (Mechanism (Ent)); | |
2093 | Write_Eol; | |
19235870 RK |
2094 | end if; |
2095 | end if; | |
2096 | ||
6f65c7ee EB |
2097 | if not Is_Entry (Ent) then |
2098 | List_Linker_Section (Ent); | |
2099 | end if; | |
2100 | ||
1e7629b8 | 2101 | if List_Representation_Info_To_JSON then |
6f65c7ee EB |
2102 | Write_Eol; |
2103 | Write_Line ("}"); | |
1e7629b8 | 2104 | end if; |
6f65c7ee EB |
2105 | end List_Subprogram_Info; |
2106 | ||
2107 | -------------------- | |
2108 | -- List_Type_Info -- | |
2109 | -------------------- | |
2110 | ||
2111 | procedure List_Type_Info (Ent : Entity_Id) is | |
2112 | begin | |
b5d3d113 | 2113 | Write_Separator; |
6f65c7ee EB |
2114 | |
2115 | if List_Representation_Info_To_JSON then | |
2116 | Write_Line ("{"); | |
2117 | end if; | |
2118 | ||
2119 | List_Common_Type_Info (Ent); | |
0d57c6f4 RD |
2120 | |
2121 | -- Special stuff for fixed-point | |
2122 | ||
2123 | if Is_Fixed_Point_Type (Ent) then | |
2124 | ||
2125 | -- Write small (always a static constant) | |
2126 | ||
1e7629b8 EB |
2127 | if List_Representation_Info_To_JSON then |
2128 | Write_Line (","); | |
2129 | Write_Str (" ""Small"": "); | |
08c9ef08 | 2130 | UR_Write_To_JSON (Small_Value (Ent)); |
1e7629b8 EB |
2131 | else |
2132 | Write_Str ("for "); | |
2133 | List_Name (Ent); | |
2134 | Write_Str ("'Small use "); | |
2135 | UR_Write (Small_Value (Ent)); | |
2136 | Write_Line (";"); | |
2137 | end if; | |
0d57c6f4 RD |
2138 | |
2139 | -- Write range if static | |
2140 | ||
2141 | declare | |
2142 | R : constant Node_Id := Scalar_Range (Ent); | |
2143 | ||
2144 | begin | |
2145 | if Nkind (Low_Bound (R)) = N_Real_Literal | |
2146 | and then | |
2147 | Nkind (High_Bound (R)) = N_Real_Literal | |
2148 | then | |
1e7629b8 EB |
2149 | if List_Representation_Info_To_JSON then |
2150 | Write_Line (","); | |
2151 | Write_Str (" ""Range"": [ "); | |
08c9ef08 | 2152 | UR_Write_To_JSON (Realval (Low_Bound (R))); |
1e7629b8 | 2153 | Write_Str (", "); |
08c9ef08 | 2154 | UR_Write_To_JSON (Realval (High_Bound (R))); |
1e7629b8 EB |
2155 | Write_Str (" ]"); |
2156 | else | |
2157 | Write_Str ("for "); | |
2158 | List_Name (Ent); | |
2159 | Write_Str ("'Range use "); | |
2160 | UR_Write (Realval (Low_Bound (R))); | |
2161 | Write_Str (" .. "); | |
2162 | UR_Write (Realval (High_Bound (R))); | |
2163 | Write_Line (";"); | |
2164 | end if; | |
0d57c6f4 RD |
2165 | end if; |
2166 | end; | |
2167 | end if; | |
6f65c7ee EB |
2168 | |
2169 | List_Linker_Section (Ent); | |
2170 | ||
2171 | if List_Representation_Info_To_JSON then | |
2172 | Write_Eol; | |
2173 | Write_Line ("}"); | |
2174 | end if; | |
19235870 RK |
2175 | end List_Type_Info; |
2176 | ||
d7ca4dfe BD |
2177 | ---------------------------- |
2178 | -- Compile_Time_Known_Rep -- | |
2179 | ---------------------------- | |
19235870 | 2180 | |
d7ca4dfe | 2181 | function Compile_Time_Known_Rep (Val : Node_Ref_Or_Val) return Boolean is |
19235870 | 2182 | begin |
d7ca4dfe BD |
2183 | return Present (Val) and then Val >= 0; |
2184 | end Compile_Time_Known_Rep; | |
19235870 RK |
2185 | |
2186 | --------------- | |
2187 | -- Rep_Value -- | |
2188 | --------------- | |
2189 | ||
972d2984 EB |
2190 | function Rep_Value (Val : Node_Ref_Or_Val; D : Discrim_List) return Uint is |
2191 | ||
42b39995 | 2192 | function B (Val : Boolean) return Ubool; |
19235870 RK |
2193 | -- Returns Uint_0 for False, Uint_1 for True |
2194 | ||
2195 | function T (Val : Node_Ref_Or_Val) return Boolean; | |
2196 | -- Returns True for 0, False for any non-zero (i.e. True) | |
2197 | ||
2198 | function V (Val : Node_Ref_Or_Val) return Uint; | |
2199 | -- Internal recursive routine to evaluate tree | |
2200 | ||
5e61ef09 | 2201 | function W (Val : Uint) return Word; |
0d57c6f4 RD |
2202 | -- Convert Val to Word, assuming Val is always in the Int range. This |
2203 | -- is a helper function for the evaluation of bitwise expressions like | |
5e61ef09 TQ |
2204 | -- Bit_And_Expr, for which there is no direct support in uintp. Uint |
2205 | -- values out of the Int range are expected to be seen in such | |
2206 | -- expressions only with overflowing byte sizes around, introducing | |
276e95ca | 2207 | -- inherent unreliabilities in computations anyway. |
5e61ef09 | 2208 | |
19235870 RK |
2209 | ------- |
2210 | -- B -- | |
2211 | ------- | |
2212 | ||
42b39995 | 2213 | function B (Val : Boolean) return Ubool is |
19235870 RK |
2214 | begin |
2215 | if Val then | |
2216 | return Uint_1; | |
2217 | else | |
2218 | return Uint_0; | |
2219 | end if; | |
2220 | end B; | |
2221 | ||
2222 | ------- | |
2223 | -- T -- | |
2224 | ------- | |
2225 | ||
2226 | function T (Val : Node_Ref_Or_Val) return Boolean is | |
2227 | begin | |
2228 | if V (Val) = 0 then | |
2229 | return False; | |
2230 | else | |
2231 | return True; | |
2232 | end if; | |
2233 | end T; | |
2234 | ||
2235 | ------- | |
2236 | -- V -- | |
2237 | ------- | |
2238 | ||
2239 | function V (Val : Node_Ref_Or_Val) return Uint is | |
2240 | L, R, Q : Uint; | |
2241 | ||
2242 | begin | |
2243 | if Val >= 0 then | |
2244 | return Val; | |
2245 | ||
2246 | else | |
2247 | declare | |
2248 | Node : Exp_Node renames Rep_Table.Table (-UI_To_Int (Val)); | |
2249 | ||
2250 | begin | |
2251 | case Node.Expr is | |
2252 | when Cond_Expr => | |
2253 | if T (Node.Op1) then | |
2254 | return V (Node.Op2); | |
2255 | else | |
2256 | return V (Node.Op3); | |
2257 | end if; | |
2258 | ||
2259 | when Plus_Expr => | |
2260 | return V (Node.Op1) + V (Node.Op2); | |
2261 | ||
2262 | when Minus_Expr => | |
2263 | return V (Node.Op1) - V (Node.Op2); | |
2264 | ||
2265 | when Mult_Expr => | |
2266 | return V (Node.Op1) * V (Node.Op2); | |
2267 | ||
2268 | when Trunc_Div_Expr => | |
2269 | return V (Node.Op1) / V (Node.Op2); | |
2270 | ||
2271 | when Ceil_Div_Expr => | |
2272 | return | |
2273 | UR_Ceiling | |
2274 | (V (Node.Op1) / UR_From_Uint (V (Node.Op2))); | |
2275 | ||
2276 | when Floor_Div_Expr => | |
2277 | return | |
2278 | UR_Floor | |
2279 | (V (Node.Op1) / UR_From_Uint (V (Node.Op2))); | |
2280 | ||
2281 | when Trunc_Mod_Expr => | |
2282 | return V (Node.Op1) rem V (Node.Op2); | |
2283 | ||
2284 | when Floor_Mod_Expr => | |
2285 | return V (Node.Op1) mod V (Node.Op2); | |
2286 | ||
2287 | when Ceil_Mod_Expr => | |
2288 | L := V (Node.Op1); | |
2289 | R := V (Node.Op2); | |
2290 | Q := UR_Ceiling (L / UR_From_Uint (R)); | |
2291 | return L - R * Q; | |
2292 | ||
2293 | when Exact_Div_Expr => | |
2294 | return V (Node.Op1) / V (Node.Op2); | |
2295 | ||
2296 | when Negate_Expr => | |
2297 | return -V (Node.Op1); | |
2298 | ||
2299 | when Min_Expr => | |
2300 | return UI_Min (V (Node.Op1), V (Node.Op2)); | |
2301 | ||
2302 | when Max_Expr => | |
2303 | return UI_Max (V (Node.Op1), V (Node.Op2)); | |
2304 | ||
2305 | when Abs_Expr => | |
2306 | return UI_Abs (V (Node.Op1)); | |
2307 | ||
19235870 | 2308 | when Truth_And_Expr => |
d1ced162 | 2309 | return B (T (Node.Op1) and then T (Node.Op2)); |
19235870 RK |
2310 | |
2311 | when Truth_Or_Expr => | |
d1ced162 | 2312 | return B (T (Node.Op1) or else T (Node.Op2)); |
19235870 RK |
2313 | |
2314 | when Truth_Xor_Expr => | |
2315 | return B (T (Node.Op1) xor T (Node.Op2)); | |
2316 | ||
2317 | when Truth_Not_Expr => | |
2318 | return B (not T (Node.Op1)); | |
2319 | ||
5e61ef09 TQ |
2320 | when Bit_And_Expr => |
2321 | L := V (Node.Op1); | |
2322 | R := V (Node.Op2); | |
2323 | return UI_From_Int (Int (W (L) and W (R))); | |
2324 | ||
19235870 RK |
2325 | when Lt_Expr => |
2326 | return B (V (Node.Op1) < V (Node.Op2)); | |
2327 | ||
2328 | when Le_Expr => | |
2329 | return B (V (Node.Op1) <= V (Node.Op2)); | |
2330 | ||
2331 | when Gt_Expr => | |
2332 | return B (V (Node.Op1) > V (Node.Op2)); | |
2333 | ||
2334 | when Ge_Expr => | |
2335 | return B (V (Node.Op1) >= V (Node.Op2)); | |
2336 | ||
2337 | when Eq_Expr => | |
2338 | return B (V (Node.Op1) = V (Node.Op2)); | |
2339 | ||
2340 | when Ne_Expr => | |
2341 | return B (V (Node.Op1) /= V (Node.Op2)); | |
2342 | ||
2343 | when Discrim_Val => | |
2344 | declare | |
2345 | Sub : constant Int := UI_To_Int (Node.Op1); | |
19235870 RK |
2346 | begin |
2347 | pragma Assert (Sub in D'Range); | |
2348 | return D (Sub); | |
2349 | end; | |
e45f84a5 EB |
2350 | |
2351 | when Dynamic_Val => | |
2352 | return No_Uint; | |
19235870 RK |
2353 | end case; |
2354 | end; | |
2355 | end if; | |
2356 | end V; | |
2357 | ||
d3879a5a RD |
2358 | ------- |
2359 | -- W -- | |
2360 | ------- | |
2361 | ||
2362 | -- We use an unchecked conversion to map Int values to their Word | |
2363 | -- bitwise equivalent, which we could not achieve with a normal type | |
2364 | -- conversion for negative Ints. We want bitwise equivalents because W | |
2365 | -- is used as a helper for bit operators like Bit_And_Expr, and can be | |
2366 | -- called for negative Ints in the context of aligning expressions like | |
2367 | -- X+Align & -Align. | |
2368 | ||
2369 | function W (Val : Uint) return Word is | |
2370 | function To_Word is new Ada.Unchecked_Conversion (Int, Word); | |
2371 | begin | |
2372 | return To_Word (UI_To_Int (Val)); | |
2373 | end W; | |
2374 | ||
19235870 RK |
2375 | -- Start of processing for Rep_Value |
2376 | ||
2377 | begin | |
2175b50b | 2378 | if No (Val) then |
19235870 RK |
2379 | return No_Uint; |
2380 | ||
2381 | else | |
2382 | return V (Val); | |
2383 | end if; | |
2384 | end Rep_Value; | |
2385 | ||
2386 | ------------ | |
2387 | -- Spaces -- | |
2388 | ------------ | |
2389 | ||
2390 | procedure Spaces (N : Natural) is | |
2391 | begin | |
2392 | for J in 1 .. N loop | |
2393 | Write_Char (' '); | |
2394 | end loop; | |
2395 | end Spaces; | |
2396 | ||
fbf5a39b AC |
2397 | --------------------- |
2398 | -- Write_Info_Line -- | |
2399 | --------------------- | |
2400 | ||
2401 | procedure Write_Info_Line (S : String) is | |
2402 | begin | |
4b54d939 | 2403 | Write_Repinfo_Line (S (S'First .. S'Last - 1)); |
fbf5a39b AC |
2404 | end Write_Info_Line; |
2405 | ||
2406 | --------------------- | |
2407 | -- Write_Mechanism -- | |
2408 | --------------------- | |
2409 | ||
2410 | procedure Write_Mechanism (M : Mechanism_Type) is | |
2411 | begin | |
2412 | case M is | |
2413 | when 0 => | |
2414 | Write_Str ("default"); | |
2415 | ||
2416 | when -1 => | |
2417 | Write_Str ("copy"); | |
2418 | ||
2419 | when -2 => | |
2420 | Write_Str ("reference"); | |
2421 | ||
fbf5a39b AC |
2422 | when others => |
2423 | raise Program_Error; | |
2424 | end case; | |
2425 | end Write_Mechanism; | |
2426 | ||
b5d3d113 EB |
2427 | --------------------- |
2428 | -- Write_Separator -- | |
2429 | --------------------- | |
2430 | ||
2431 | procedure Write_Separator is | |
2432 | begin | |
2433 | if Need_Separator then | |
2434 | if List_Representation_Info_To_JSON then | |
2435 | Write_Line (","); | |
2436 | else | |
2437 | Write_Eol; | |
2438 | end if; | |
2439 | else | |
2440 | Need_Separator := True; | |
2441 | end if; | |
2442 | end Write_Separator; | |
2443 | ||
76b382d9 EB |
2444 | ----------------------- |
2445 | -- Write_Unknown_Val -- | |
2446 | ----------------------- | |
2447 | ||
2448 | procedure Write_Unknown_Val is | |
2449 | begin | |
1e7629b8 EB |
2450 | if List_Representation_Info_To_JSON then |
2451 | Write_Str ("""??"""); | |
2452 | else | |
2453 | Write_Str ("??"); | |
2454 | end if; | |
76b382d9 EB |
2455 | end Write_Unknown_Val; |
2456 | ||
19235870 RK |
2457 | --------------- |
2458 | -- Write_Val -- | |
2459 | --------------- | |
2460 | ||
2461 | procedure Write_Val (Val : Node_Ref_Or_Val; Paren : Boolean := False) is | |
2462 | begin | |
d7ca4dfe BD |
2463 | if Compile_Time_Known_Rep (Val) then |
2464 | UI_Write (Val, Decimal); | |
2465 | elsif List_Representation_Info < 3 or else No (Val) then | |
2466 | Write_Unknown_Val; | |
2467 | else | |
2468 | if Paren then | |
2469 | Write_Char ('('); | |
2470 | end if; | |
07fc65c4 | 2471 | |
d7ca4dfe | 2472 | List_GCC_Expression (Val); |
98b779ae | 2473 | |
d7ca4dfe BD |
2474 | if Paren then |
2475 | Write_Char (')'); | |
19235870 | 2476 | end if; |
19235870 RK |
2477 | end if; |
2478 | end Write_Val; | |
2479 | ||
2480 | end Repinfo; |