Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / ada / repinfo.adb
blob2ce0d661fc8d88908ac4e9b7f2ce526b0b4abe50
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- R E P I N F O --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1999-2004 Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
21 -- --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
32 ------------------------------------------------------------------------------
34 with Alloc; use Alloc;
35 with Atree; use Atree;
36 with Casing; use Casing;
37 with Debug; use Debug;
38 with Einfo; use Einfo;
39 with Lib; use Lib;
40 with Namet; use Namet;
41 with Opt; use Opt;
42 with Output; use Output;
43 with Sinfo; use Sinfo;
44 with Sinput; use Sinput;
45 with Snames; use Snames;
46 with Stand; use Stand;
47 with Table; use Table;
48 with Uname; use Uname;
49 with Urealp; use Urealp;
51 package body Repinfo is
53 SSU : constant := 8;
54 -- Value for Storage_Unit, we do not want to get this from TTypes, since
55 -- this introduces problematic dependencies in ASIS, and in any case this
56 -- value is assumed to be 8 for the implementation of the DDA.
58 -- This is wrong for AAMP???
60 ---------------------------------------
61 -- Representation of gcc Expressions --
62 ---------------------------------------
64 -- This table is used only if Frontend_Layout_On_Target is False,
65 -- so that gigi lays out dynamic size/offset fields using encoded
66 -- gcc expressions.
68 -- A table internal to this unit is used to hold the values of
69 -- back annotated expressions. This table is written out by -gnatt
70 -- and read back in for ASIS processing.
72 -- Node values are stored as Uint values which are the negative of
73 -- the node index in this table. Constants appear as non-negative
74 -- Uint values.
76 type Exp_Node is record
77 Expr : TCode;
78 Op1 : Node_Ref_Or_Val;
79 Op2 : Node_Ref_Or_Val;
80 Op3 : Node_Ref_Or_Val;
81 end record;
83 package Rep_Table is new Table.Table (
84 Table_Component_Type => Exp_Node,
85 Table_Index_Type => Nat,
86 Table_Low_Bound => 1,
87 Table_Initial => Alloc.Rep_Table_Initial,
88 Table_Increment => Alloc.Rep_Table_Increment,
89 Table_Name => "BE_Rep_Table");
91 --------------------------------------------------------------
92 -- Representation of Front-End Dynamic Size/Offset Entities --
93 --------------------------------------------------------------
95 package Dynamic_SO_Entity_Table is new Table.Table (
96 Table_Component_Type => Entity_Id,
97 Table_Index_Type => Nat,
98 Table_Low_Bound => 1,
99 Table_Initial => Alloc.Rep_Table_Initial,
100 Table_Increment => Alloc.Rep_Table_Increment,
101 Table_Name => "FE_Rep_Table");
103 Unit_Casing : Casing_Type;
104 -- Identifier casing for current unit
106 Need_Blank_Line : Boolean;
107 -- Set True if a blank line is needed before outputting any
108 -- information for the current entity. Set True when a new
109 -- entity is processed, and false when the blank line is output.
111 -----------------------
112 -- Local Subprograms --
113 -----------------------
115 function Back_End_Layout return Boolean;
116 -- Test for layout mode, True = back end, False = front end. This
117 -- function is used rather than checking the configuration parameter
118 -- because we do not want Repinfo to depend on Targparm (for ASIS)
120 procedure Blank_Line;
121 -- Called before outputting anything for an entity. Ensures that
122 -- a blank line precedes the output for a particular entity.
124 procedure List_Entities (Ent : Entity_Id);
125 -- This procedure lists the entities associated with the entity E,
126 -- starting with the First_Entity and using the Next_Entity link.
127 -- If a nested package is found, entities within the package are
128 -- recursively processed.
130 procedure List_Name (Ent : Entity_Id);
131 -- List name of entity Ent in appropriate case. The name is listed with
132 -- full qualification up to but not including the compilation unit name.
134 procedure List_Array_Info (Ent : Entity_Id);
135 -- List representation info for array type Ent
137 procedure List_Mechanisms (Ent : Entity_Id);
138 -- List mechanism information for parameters of Ent, which is a
139 -- subprogram, subprogram type, or an entry or entry family.
141 procedure List_Object_Info (Ent : Entity_Id);
142 -- List representation info for object Ent
144 procedure List_Record_Info (Ent : Entity_Id);
145 -- List representation info for record type Ent
147 procedure List_Type_Info (Ent : Entity_Id);
148 -- List type info for type Ent
150 function Rep_Not_Constant (Val : Node_Ref_Or_Val) return Boolean;
151 -- Returns True if Val represents a variable value, and False if it
152 -- represents a value that is fixed at compile time.
154 procedure Spaces (N : Natural);
155 -- Output given number of spaces
157 procedure Write_Info_Line (S : String);
158 -- Routine to write a line to Repinfo output file. This routine is
159 -- passed as a special output procedure to Output.Set_Special_Output.
160 -- Note that Write_Info_Line is called with an EOL character at the
161 -- end of each line, as per the Output spec, but the internal call
162 -- to the appropriate routine in Osint requires that the end of line
163 -- sequence be stripped off.
165 procedure Write_Mechanism (M : Mechanism_Type);
166 -- Writes symbolic string for mechanism represented by M
168 procedure Write_Val (Val : Node_Ref_Or_Val; Paren : Boolean := False);
169 -- Given a representation value, write it out. No_Uint values or values
170 -- dependent on discriminants are written as two question marks. If the
171 -- flag Paren is set, then the output is surrounded in parentheses if
172 -- it is other than a simple value.
174 ---------------------
175 -- Back_End_Layout --
176 ---------------------
178 function Back_End_Layout return Boolean is
179 begin
180 -- We have back end layout if the back end has made any entries in
181 -- the table of GCC expressions, otherwise we have front end layout.
183 return Rep_Table.Last > 0;
184 end Back_End_Layout;
186 ----------------
187 -- Blank_Line --
188 ----------------
190 procedure Blank_Line is
191 begin
192 if Need_Blank_Line then
193 Write_Eol;
194 Need_Blank_Line := False;
195 end if;
196 end Blank_Line;
198 ------------------------
199 -- Create_Discrim_Ref --
200 ------------------------
202 function Create_Discrim_Ref (Discr : Entity_Id) return Node_Ref is
203 N : constant Uint := Discriminant_Number (Discr);
204 T : Nat;
205 begin
206 Rep_Table.Increment_Last;
207 T := Rep_Table.Last;
208 Rep_Table.Table (T).Expr := Discrim_Val;
209 Rep_Table.Table (T).Op1 := N;
210 Rep_Table.Table (T).Op2 := No_Uint;
211 Rep_Table.Table (T).Op3 := No_Uint;
212 return UI_From_Int (-T);
213 end Create_Discrim_Ref;
215 ---------------------------
216 -- Create_Dynamic_SO_Ref --
217 ---------------------------
219 function Create_Dynamic_SO_Ref (E : Entity_Id) return Dynamic_SO_Ref is
220 T : Nat;
221 begin
222 Dynamic_SO_Entity_Table.Increment_Last;
223 T := Dynamic_SO_Entity_Table.Last;
224 Dynamic_SO_Entity_Table.Table (T) := E;
225 return UI_From_Int (-T);
226 end Create_Dynamic_SO_Ref;
228 -----------------
229 -- Create_Node --
230 -----------------
232 function Create_Node
233 (Expr : TCode;
234 Op1 : Node_Ref_Or_Val;
235 Op2 : Node_Ref_Or_Val := No_Uint;
236 Op3 : Node_Ref_Or_Val := No_Uint) return Node_Ref
238 T : Nat;
239 begin
240 Rep_Table.Increment_Last;
241 T := Rep_Table.Last;
242 Rep_Table.Table (T).Expr := Expr;
243 Rep_Table.Table (T).Op1 := Op1;
244 Rep_Table.Table (T).Op2 := Op2;
245 Rep_Table.Table (T).Op3 := Op3;
246 return UI_From_Int (-T);
247 end Create_Node;
249 ---------------------------
250 -- Get_Dynamic_SO_Entity --
251 ---------------------------
253 function Get_Dynamic_SO_Entity (U : Dynamic_SO_Ref) return Entity_Id is
254 begin
255 return Dynamic_SO_Entity_Table.Table (-UI_To_Int (U));
256 end Get_Dynamic_SO_Entity;
258 -----------------------
259 -- Is_Dynamic_SO_Ref --
260 -----------------------
262 function Is_Dynamic_SO_Ref (U : SO_Ref) return Boolean is
263 begin
264 return U < Uint_0;
265 end Is_Dynamic_SO_Ref;
267 ----------------------
268 -- Is_Static_SO_Ref --
269 ----------------------
271 function Is_Static_SO_Ref (U : SO_Ref) return Boolean is
272 begin
273 return U >= Uint_0;
274 end Is_Static_SO_Ref;
276 ---------
277 -- lgx --
278 ---------
280 procedure lgx (U : Node_Ref_Or_Val) is
281 begin
282 List_GCC_Expression (U);
283 Write_Eol;
284 end lgx;
286 ----------------------
287 -- List_Array_Info --
288 ----------------------
290 procedure List_Array_Info (Ent : Entity_Id) is
291 begin
292 List_Type_Info (Ent);
293 Write_Str ("for ");
294 List_Name (Ent);
295 Write_Str ("'Component_Size use ");
296 Write_Val (Component_Size (Ent));
297 Write_Line (";");
298 end List_Array_Info;
300 -------------------
301 -- List_Entities --
302 -------------------
304 procedure List_Entities (Ent : Entity_Id) is
305 Body_E : Entity_Id;
306 E : Entity_Id;
308 function Find_Declaration (E : Entity_Id) return Node_Id;
309 -- Utility to retrieve declaration node for entity in the
310 -- case of package bodies and subprograms.
312 ----------------------
313 -- Find_Declaration --
314 ----------------------
316 function Find_Declaration (E : Entity_Id) return Node_Id is
317 Decl : Node_Id;
319 begin
320 Decl := Parent (E);
321 while Present (Decl)
322 and then Nkind (Decl) /= N_Package_Body
323 and then Nkind (Decl) /= N_Subprogram_Declaration
324 and then Nkind (Decl) /= N_Subprogram_Body
325 loop
326 Decl := Parent (Decl);
327 end loop;
329 return Decl;
330 end Find_Declaration;
332 -- Start of processing for List_Entities
334 begin
335 if Present (Ent) then
337 -- If entity is a subprogram and we are listing mechanisms,
338 -- then we need to list mechanisms for this entity.
340 if List_Representation_Info_Mechanisms
341 and then (Is_Subprogram (Ent)
342 or else Ekind (Ent) = E_Entry
343 or else Ekind (Ent) = E_Entry_Family)
344 then
345 Need_Blank_Line := True;
346 List_Mechanisms (Ent);
347 end if;
349 E := First_Entity (Ent);
350 while Present (E) loop
351 Need_Blank_Line := True;
353 -- We list entities that come from source (excluding private
354 -- or incomplete types or deferred constants, where we will
355 -- list the info for the full view). If debug flag A is set,
356 -- then all entities are listed
358 if (Comes_From_Source (E)
359 and then not Is_Incomplete_Or_Private_Type (E)
360 and then not (Ekind (E) = E_Constant
361 and then Present (Full_View (E))))
362 or else Debug_Flag_AA
363 then
364 if Is_Subprogram (E)
365 or else
366 Ekind (E) = E_Entry
367 or else
368 Ekind (E) = E_Entry_Family
369 or else
370 Ekind (E) = E_Subprogram_Type
371 then
372 if List_Representation_Info_Mechanisms then
373 List_Mechanisms (E);
374 end if;
376 elsif Is_Record_Type (E) then
377 if List_Representation_Info >= 1 then
378 List_Record_Info (E);
379 end if;
381 elsif Is_Array_Type (E) then
382 if List_Representation_Info >= 1 then
383 List_Array_Info (E);
384 end if;
386 elsif Is_Type (E) then
387 if List_Representation_Info >= 2 then
388 List_Type_Info (E);
389 end if;
391 elsif Ekind (E) = E_Variable
392 or else
393 Ekind (E) = E_Constant
394 or else
395 Ekind (E) = E_Loop_Parameter
396 or else
397 Is_Formal (E)
398 then
399 if List_Representation_Info >= 2 then
400 List_Object_Info (E);
401 end if;
403 end if;
405 -- Recurse into nested package, but not if they are
406 -- package renamings (in particular renamings of the
407 -- enclosing package, as for some Java bindings and
408 -- for generic instances).
410 if Ekind (E) = E_Package then
411 if No (Renamed_Object (E)) then
412 List_Entities (E);
413 end if;
415 -- Recurse into bodies
417 elsif Ekind (E) = E_Protected_Type
418 or else
419 Ekind (E) = E_Task_Type
420 or else
421 Ekind (E) = E_Subprogram_Body
422 or else
423 Ekind (E) = E_Package_Body
424 or else
425 Ekind (E) = E_Task_Body
426 or else
427 Ekind (E) = E_Protected_Body
428 then
429 List_Entities (E);
431 -- Recurse into blocks
433 elsif Ekind (E) = E_Block then
434 List_Entities (E);
435 end if;
436 end if;
438 E := Next_Entity (E);
439 end loop;
441 -- For a package body, the entities of the visible subprograms
442 -- are declared in the corresponding spec. Iterate over its
443 -- entities in order to handle properly the subprogram bodies.
444 -- Skip bodies in subunits, which are listed independently.
446 if Ekind (Ent) = E_Package_Body
447 and then Present (Corresponding_Spec (Find_Declaration (Ent)))
448 then
449 E := First_Entity (Corresponding_Spec (Find_Declaration (Ent)));
451 while Present (E) loop
452 if Is_Subprogram (E)
453 and then
454 Nkind (Find_Declaration (E)) = N_Subprogram_Declaration
455 then
456 Body_E := Corresponding_Body (Find_Declaration (E));
458 if Present (Body_E)
459 and then
460 Nkind (Parent (Find_Declaration (Body_E))) /= N_Subunit
461 then
462 List_Entities (Body_E);
463 end if;
464 end if;
466 Next_Entity (E);
467 end loop;
468 end if;
469 end if;
470 end List_Entities;
472 -------------------------
473 -- List_GCC_Expression --
474 -------------------------
476 procedure List_GCC_Expression (U : Node_Ref_Or_Val) is
478 procedure Print_Expr (Val : Node_Ref_Or_Val);
479 -- Internal recursive procedure to print expression
481 ----------------
482 -- Print_Expr --
483 ----------------
485 procedure Print_Expr (Val : Node_Ref_Or_Val) is
486 begin
487 if Val >= 0 then
488 UI_Write (Val, Decimal);
490 else
491 declare
492 Node : Exp_Node renames Rep_Table.Table (-UI_To_Int (Val));
494 procedure Binop (S : String);
495 -- Output text for binary operator with S being operator name
497 -----------
498 -- Binop --
499 -----------
501 procedure Binop (S : String) is
502 begin
503 Write_Char ('(');
504 Print_Expr (Node.Op1);
505 Write_Str (S);
506 Print_Expr (Node.Op2);
507 Write_Char (')');
508 end Binop;
510 -- Start of processing for Print_Expr
512 begin
513 case Node.Expr is
514 when Cond_Expr =>
515 Write_Str ("(if ");
516 Print_Expr (Node.Op1);
517 Write_Str (" then ");
518 Print_Expr (Node.Op2);
519 Write_Str (" else ");
520 Print_Expr (Node.Op3);
521 Write_Str (" end)");
523 when Plus_Expr =>
524 Binop (" + ");
526 when Minus_Expr =>
527 Binop (" - ");
529 when Mult_Expr =>
530 Binop (" * ");
532 when Trunc_Div_Expr =>
533 Binop (" /t ");
535 when Ceil_Div_Expr =>
536 Binop (" /c ");
538 when Floor_Div_Expr =>
539 Binop (" /f ");
541 when Trunc_Mod_Expr =>
542 Binop (" modt ");
544 when Floor_Mod_Expr =>
545 Binop (" modf ");
547 when Ceil_Mod_Expr =>
548 Binop (" modc ");
550 when Exact_Div_Expr =>
551 Binop (" /e ");
553 when Negate_Expr =>
554 Write_Char ('-');
555 Print_Expr (Node.Op1);
557 when Min_Expr =>
558 Binop (" min ");
560 when Max_Expr =>
561 Binop (" max ");
563 when Abs_Expr =>
564 Write_Str ("abs ");
565 Print_Expr (Node.Op1);
567 when Truth_Andif_Expr =>
568 Binop (" and if ");
570 when Truth_Orif_Expr =>
571 Binop (" or if ");
573 when Truth_And_Expr =>
574 Binop (" and ");
576 when Truth_Or_Expr =>
577 Binop (" or ");
579 when Truth_Xor_Expr =>
580 Binop (" xor ");
582 when Truth_Not_Expr =>
583 Write_Str ("not ");
584 Print_Expr (Node.Op1);
586 when Lt_Expr =>
587 Binop (" < ");
589 when Le_Expr =>
590 Binop (" <= ");
592 when Gt_Expr =>
593 Binop (" > ");
595 when Ge_Expr =>
596 Binop (" >= ");
598 when Eq_Expr =>
599 Binop (" == ");
601 when Ne_Expr =>
602 Binop (" != ");
604 when Discrim_Val =>
605 Write_Char ('#');
606 UI_Write (Node.Op1);
608 end case;
609 end;
610 end if;
611 end Print_Expr;
613 -- Start of processing for List_GCC_Expression
615 begin
616 if U = No_Uint then
617 Write_Str ("??");
618 else
619 Print_Expr (U);
620 end if;
621 end List_GCC_Expression;
623 ---------------------
624 -- List_Mechanisms --
625 ---------------------
627 procedure List_Mechanisms (Ent : Entity_Id) is
628 Plen : Natural;
629 Form : Entity_Id;
631 begin
632 Blank_Line;
634 case Ekind (Ent) is
635 when E_Function =>
636 Write_Str ("function ");
638 when E_Operator =>
639 Write_Str ("operator ");
641 when E_Procedure =>
642 Write_Str ("procedure ");
644 when E_Subprogram_Type =>
645 Write_Str ("type ");
647 when E_Entry | E_Entry_Family =>
648 Write_Str ("entry ");
650 when others =>
651 raise Program_Error;
652 end case;
654 Get_Unqualified_Decoded_Name_String (Chars (Ent));
655 Write_Str (Name_Buffer (1 .. Name_Len));
656 Write_Str (" declared at ");
657 Write_Location (Sloc (Ent));
658 Write_Eol;
660 Write_Str (" convention : ");
662 case Convention (Ent) is
663 when Convention_Ada => Write_Line ("Ada");
664 when Convention_Intrinsic => Write_Line ("InLineinsic");
665 when Convention_Entry => Write_Line ("Entry");
666 when Convention_Protected => Write_Line ("Protected");
667 when Convention_Assembler => Write_Line ("Assembler");
668 when Convention_C => Write_Line ("C");
669 when Convention_COBOL => Write_Line ("COBOL");
670 when Convention_CPP => Write_Line ("C++");
671 when Convention_Fortran => Write_Line ("Fortran");
672 when Convention_Java => Write_Line ("Java");
673 when Convention_Stdcall => Write_Line ("Stdcall");
674 when Convention_Stubbed => Write_Line ("Stubbed");
675 end case;
677 -- Find max length of formal name
679 Plen := 0;
680 Form := First_Formal (Ent);
681 while Present (Form) loop
682 Get_Unqualified_Decoded_Name_String (Chars (Form));
684 if Name_Len > Plen then
685 Plen := Name_Len;
686 end if;
688 Next_Formal (Form);
689 end loop;
691 -- Output formals and mechanisms
693 Form := First_Formal (Ent);
694 while Present (Form) loop
695 Get_Unqualified_Decoded_Name_String (Chars (Form));
697 while Name_Len <= Plen loop
698 Name_Len := Name_Len + 1;
699 Name_Buffer (Name_Len) := ' ';
700 end loop;
702 Write_Str (" ");
703 Write_Str (Name_Buffer (1 .. Plen + 1));
704 Write_Str (": passed by ");
706 Write_Mechanism (Mechanism (Form));
707 Write_Eol;
708 Next_Formal (Form);
709 end loop;
711 if Etype (Ent) /= Standard_Void_Type then
712 Write_Str (" returns by ");
713 Write_Mechanism (Mechanism (Ent));
714 Write_Eol;
715 end if;
716 end List_Mechanisms;
718 ---------------
719 -- List_Name --
720 ---------------
722 procedure List_Name (Ent : Entity_Id) is
723 begin
724 if not Is_Compilation_Unit (Scope (Ent)) then
725 List_Name (Scope (Ent));
726 Write_Char ('.');
727 end if;
729 Get_Unqualified_Decoded_Name_String (Chars (Ent));
730 Set_Casing (Unit_Casing);
731 Write_Str (Name_Buffer (1 .. Name_Len));
732 end List_Name;
734 ---------------------
735 -- List_Object_Info --
736 ---------------------
738 procedure List_Object_Info (Ent : Entity_Id) is
739 begin
740 Blank_Line;
742 Write_Str ("for ");
743 List_Name (Ent);
744 Write_Str ("'Size use ");
745 Write_Val (Esize (Ent));
746 Write_Line (";");
748 Write_Str ("for ");
749 List_Name (Ent);
750 Write_Str ("'Alignment use ");
751 Write_Val (Alignment (Ent));
752 Write_Line (";");
753 end List_Object_Info;
755 ----------------------
756 -- List_Record_Info --
757 ----------------------
759 procedure List_Record_Info (Ent : Entity_Id) is
760 Comp : Entity_Id;
761 Cfbit : Uint;
762 Sunit : Uint;
764 Max_Name_Length : Natural;
765 Max_Suni_Length : Natural;
767 begin
768 Blank_Line;
769 List_Type_Info (Ent);
771 Write_Str ("for ");
772 List_Name (Ent);
773 Write_Line (" use record");
775 -- First loop finds out max line length and max starting position
776 -- length, for the purpose of lining things up nicely.
778 Max_Name_Length := 0;
779 Max_Suni_Length := 0;
781 Comp := First_Entity (Ent);
782 while Present (Comp) loop
783 if Ekind (Comp) = E_Component
784 or else Ekind (Comp) = E_Discriminant
785 then
786 Get_Decoded_Name_String (Chars (Comp));
787 Max_Name_Length := Natural'Max (Max_Name_Length, Name_Len);
789 Cfbit := Component_Bit_Offset (Comp);
791 if Rep_Not_Constant (Cfbit) then
792 UI_Image_Length := 2;
794 else
795 -- Complete annotation in case not done
797 Set_Normalized_Position (Comp, Cfbit / SSU);
798 Set_Normalized_First_Bit (Comp, Cfbit mod SSU);
800 Sunit := Cfbit / SSU;
801 UI_Image (Sunit);
802 end if;
804 -- If the record is not packed, then we know that all
805 -- fields whose position is not specified have a starting
806 -- normalized bit position of zero
808 if Unknown_Normalized_First_Bit (Comp)
809 and then not Is_Packed (Ent)
810 then
811 Set_Normalized_First_Bit (Comp, Uint_0);
812 end if;
814 Max_Suni_Length :=
815 Natural'Max (Max_Suni_Length, UI_Image_Length);
816 end if;
818 Comp := Next_Entity (Comp);
819 end loop;
821 -- Second loop does actual output based on those values
823 Comp := First_Entity (Ent);
824 while Present (Comp) loop
825 if Ekind (Comp) = E_Component
826 or else Ekind (Comp) = E_Discriminant
827 then
828 declare
829 Esiz : constant Uint := Esize (Comp);
830 Bofs : constant Uint := Component_Bit_Offset (Comp);
831 Npos : constant Uint := Normalized_Position (Comp);
832 Fbit : constant Uint := Normalized_First_Bit (Comp);
833 Lbit : Uint;
835 begin
836 Write_Str (" ");
837 Get_Decoded_Name_String (Chars (Comp));
838 Set_Casing (Unit_Casing);
839 Write_Str (Name_Buffer (1 .. Name_Len));
841 for J in 1 .. Max_Name_Length - Name_Len loop
842 Write_Char (' ');
843 end loop;
845 Write_Str (" at ");
847 if Known_Static_Normalized_Position (Comp) then
848 UI_Image (Npos);
849 Spaces (Max_Suni_Length - UI_Image_Length);
850 Write_Str (UI_Image_Buffer (1 .. UI_Image_Length));
852 elsif Known_Component_Bit_Offset (Comp)
853 and then List_Representation_Info = 3
854 then
855 Spaces (Max_Suni_Length - 2);
856 Write_Str ("bit offset");
857 Write_Val (Bofs, Paren => True);
858 Write_Str (" size in bits = ");
859 Write_Val (Esiz, Paren => True);
860 Write_Eol;
861 goto Continue;
863 elsif Known_Normalized_Position (Comp)
864 and then List_Representation_Info = 3
865 then
866 Spaces (Max_Suni_Length - 2);
867 Write_Val (Npos);
869 else
870 -- For the packed case, we don't know the bit positions
871 -- if we don't know the starting position!
873 if Is_Packed (Ent) then
874 Write_Line ("?? range ? .. ??;");
875 goto Continue;
877 -- Otherwise we can continue
879 else
880 Write_Str ("??");
881 end if;
882 end if;
884 Write_Str (" range ");
885 UI_Write (Fbit);
886 Write_Str (" .. ");
888 -- Allowing Uint_0 here is a kludge, really this should be
889 -- a fine Esize value but currently it means unknown, except
890 -- that we know after gigi has back annotated that a size of
891 -- zero is real, since otherwise gigi back annotates using
892 -- No_Uint as the value to indicate unknown).
894 if (Esize (Comp) = Uint_0 or else Known_Static_Esize (Comp))
895 and then Known_Static_Normalized_First_Bit (Comp)
896 then
897 Lbit := Fbit + Esiz - 1;
899 if Lbit < 10 then
900 Write_Char (' ');
901 end if;
903 UI_Write (Lbit);
905 -- The test for Esize (Comp) not being Uint_0 here is a kludge.
906 -- Officially a value of zero for Esize means unknown, but here
907 -- we use the fact that we know that gigi annotates Esize with
908 -- No_Uint, not Uint_0. Really everyone should use No_Uint???
910 elsif List_Representation_Info < 3
911 or else (Esize (Comp) /= Uint_0 and then Unknown_Esize (Comp))
912 then
913 Write_Str ("??");
915 else -- List_Representation >= 3 and Known_Esize (Comp)
917 Write_Val (Esiz, Paren => True);
919 -- If in front end layout mode, then dynamic size is
920 -- stored in storage units, so renormalize for output
922 if not Back_End_Layout then
923 Write_Str (" * ");
924 Write_Int (SSU);
925 end if;
927 -- Add appropriate first bit offset
929 if Fbit = 0 then
930 Write_Str (" - 1");
932 elsif Fbit = 1 then
933 null;
935 else
936 Write_Str (" + ");
937 Write_Int (UI_To_Int (Fbit) - 1);
938 end if;
939 end if;
941 Write_Line (";");
942 end;
943 end if;
945 <<Continue>>
946 Comp := Next_Entity (Comp);
947 end loop;
949 Write_Line ("end record;");
950 end List_Record_Info;
952 -------------------
953 -- List_Rep_Info --
954 -------------------
956 procedure List_Rep_Info is
957 Col : Nat;
959 begin
960 if List_Representation_Info /= 0
961 or else List_Representation_Info_Mechanisms
962 then
963 for U in Main_Unit .. Last_Unit loop
964 if In_Extended_Main_Source_Unit (Cunit_Entity (U)) then
966 -- Normal case, list to standard output
968 if not List_Representation_Info_To_File then
969 Unit_Casing := Identifier_Casing (Source_Index (U));
970 Write_Eol;
971 Write_Str ("Representation information for unit ");
972 Write_Unit_Name (Unit_Name (U));
973 Col := Column;
974 Write_Eol;
976 for J in 1 .. Col - 1 loop
977 Write_Char ('-');
978 end loop;
980 Write_Eol;
981 List_Entities (Cunit_Entity (U));
983 -- List representation information to file
985 else
986 Creat_Repinfo_File_Access.all (File_Name (Source_Index (U)));
987 Set_Special_Output (Write_Info_Line'Access);
988 List_Entities (Cunit_Entity (U));
989 Set_Special_Output (null);
990 Close_Repinfo_File_Access.all;
991 end if;
992 end if;
993 end loop;
994 end if;
995 end List_Rep_Info;
997 --------------------
998 -- List_Type_Info --
999 --------------------
1001 procedure List_Type_Info (Ent : Entity_Id) is
1002 begin
1003 Blank_Line;
1005 -- Do not list size info for unconstrained arrays, not meaningful
1007 if Is_Array_Type (Ent) and then not Is_Constrained (Ent) then
1008 null;
1010 else
1011 -- If Esize and RM_Size are the same and known, list as Size. This
1012 -- is a common case, which we may as well list in simple form.
1014 if Esize (Ent) = RM_Size (Ent) then
1015 Write_Str ("for ");
1016 List_Name (Ent);
1017 Write_Str ("'Size use ");
1018 Write_Val (Esize (Ent));
1019 Write_Line (";");
1021 -- For now, temporary case, to be removed when gigi properly back
1022 -- annotates RM_Size, if RM_Size is not set, then list Esize as
1023 -- Size. This avoids odd Object_Size output till we fix things???
1025 elsif Unknown_RM_Size (Ent) then
1026 Write_Str ("for ");
1027 List_Name (Ent);
1028 Write_Str ("'Size use ");
1029 Write_Val (Esize (Ent));
1030 Write_Line (";");
1032 -- Otherwise list size values separately if they are set
1034 else
1035 Write_Str ("for ");
1036 List_Name (Ent);
1037 Write_Str ("'Object_Size use ");
1038 Write_Val (Esize (Ent));
1039 Write_Line (";");
1041 -- Note on following check: The RM_Size of a discrete type can
1042 -- legitimately be set to zero, so a special check is needed.
1044 Write_Str ("for ");
1045 List_Name (Ent);
1046 Write_Str ("'Value_Size use ");
1047 Write_Val (RM_Size (Ent));
1048 Write_Line (";");
1049 end if;
1050 end if;
1052 Write_Str ("for ");
1053 List_Name (Ent);
1054 Write_Str ("'Alignment use ");
1055 Write_Val (Alignment (Ent));
1056 Write_Line (";");
1057 end List_Type_Info;
1059 ----------------------
1060 -- Rep_Not_Constant --
1061 ----------------------
1063 function Rep_Not_Constant (Val : Node_Ref_Or_Val) return Boolean is
1064 begin
1065 if Val = No_Uint or else Val < 0 then
1066 return True;
1067 else
1068 return False;
1069 end if;
1070 end Rep_Not_Constant;
1072 ---------------
1073 -- Rep_Value --
1074 ---------------
1076 function Rep_Value
1077 (Val : Node_Ref_Or_Val;
1078 D : Discrim_List) return Uint
1080 function B (Val : Boolean) return Uint;
1081 -- Returns Uint_0 for False, Uint_1 for True
1083 function T (Val : Node_Ref_Or_Val) return Boolean;
1084 -- Returns True for 0, False for any non-zero (i.e. True)
1086 function V (Val : Node_Ref_Or_Val) return Uint;
1087 -- Internal recursive routine to evaluate tree
1089 -------
1090 -- B --
1091 -------
1093 function B (Val : Boolean) return Uint is
1094 begin
1095 if Val then
1096 return Uint_1;
1097 else
1098 return Uint_0;
1099 end if;
1100 end B;
1102 -------
1103 -- T --
1104 -------
1106 function T (Val : Node_Ref_Or_Val) return Boolean is
1107 begin
1108 if V (Val) = 0 then
1109 return False;
1110 else
1111 return True;
1112 end if;
1113 end T;
1115 -------
1116 -- V --
1117 -------
1119 function V (Val : Node_Ref_Or_Val) return Uint is
1120 L, R, Q : Uint;
1122 begin
1123 if Val >= 0 then
1124 return Val;
1126 else
1127 declare
1128 Node : Exp_Node renames Rep_Table.Table (-UI_To_Int (Val));
1130 begin
1131 case Node.Expr is
1132 when Cond_Expr =>
1133 if T (Node.Op1) then
1134 return V (Node.Op2);
1135 else
1136 return V (Node.Op3);
1137 end if;
1139 when Plus_Expr =>
1140 return V (Node.Op1) + V (Node.Op2);
1142 when Minus_Expr =>
1143 return V (Node.Op1) - V (Node.Op2);
1145 when Mult_Expr =>
1146 return V (Node.Op1) * V (Node.Op2);
1148 when Trunc_Div_Expr =>
1149 return V (Node.Op1) / V (Node.Op2);
1151 when Ceil_Div_Expr =>
1152 return
1153 UR_Ceiling
1154 (V (Node.Op1) / UR_From_Uint (V (Node.Op2)));
1156 when Floor_Div_Expr =>
1157 return
1158 UR_Floor
1159 (V (Node.Op1) / UR_From_Uint (V (Node.Op2)));
1161 when Trunc_Mod_Expr =>
1162 return V (Node.Op1) rem V (Node.Op2);
1164 when Floor_Mod_Expr =>
1165 return V (Node.Op1) mod V (Node.Op2);
1167 when Ceil_Mod_Expr =>
1168 L := V (Node.Op1);
1169 R := V (Node.Op2);
1170 Q := UR_Ceiling (L / UR_From_Uint (R));
1171 return L - R * Q;
1173 when Exact_Div_Expr =>
1174 return V (Node.Op1) / V (Node.Op2);
1176 when Negate_Expr =>
1177 return -V (Node.Op1);
1179 when Min_Expr =>
1180 return UI_Min (V (Node.Op1), V (Node.Op2));
1182 when Max_Expr =>
1183 return UI_Max (V (Node.Op1), V (Node.Op2));
1185 when Abs_Expr =>
1186 return UI_Abs (V (Node.Op1));
1188 when Truth_Andif_Expr =>
1189 return B (T (Node.Op1) and then T (Node.Op2));
1191 when Truth_Orif_Expr =>
1192 return B (T (Node.Op1) or else T (Node.Op2));
1194 when Truth_And_Expr =>
1195 return B (T (Node.Op1) and T (Node.Op2));
1197 when Truth_Or_Expr =>
1198 return B (T (Node.Op1) or T (Node.Op2));
1200 when Truth_Xor_Expr =>
1201 return B (T (Node.Op1) xor T (Node.Op2));
1203 when Truth_Not_Expr =>
1204 return B (not T (Node.Op1));
1206 when Lt_Expr =>
1207 return B (V (Node.Op1) < V (Node.Op2));
1209 when Le_Expr =>
1210 return B (V (Node.Op1) <= V (Node.Op2));
1212 when Gt_Expr =>
1213 return B (V (Node.Op1) > V (Node.Op2));
1215 when Ge_Expr =>
1216 return B (V (Node.Op1) >= V (Node.Op2));
1218 when Eq_Expr =>
1219 return B (V (Node.Op1) = V (Node.Op2));
1221 when Ne_Expr =>
1222 return B (V (Node.Op1) /= V (Node.Op2));
1224 when Discrim_Val =>
1225 declare
1226 Sub : constant Int := UI_To_Int (Node.Op1);
1228 begin
1229 pragma Assert (Sub in D'Range);
1230 return D (Sub);
1231 end;
1233 end case;
1234 end;
1235 end if;
1236 end V;
1238 -- Start of processing for Rep_Value
1240 begin
1241 if Val = No_Uint then
1242 return No_Uint;
1244 else
1245 return V (Val);
1246 end if;
1247 end Rep_Value;
1249 ------------
1250 -- Spaces --
1251 ------------
1253 procedure Spaces (N : Natural) is
1254 begin
1255 for J in 1 .. N loop
1256 Write_Char (' ');
1257 end loop;
1258 end Spaces;
1260 ---------------
1261 -- Tree_Read --
1262 ---------------
1264 procedure Tree_Read is
1265 begin
1266 Rep_Table.Tree_Read;
1267 end Tree_Read;
1269 ----------------
1270 -- Tree_Write --
1271 ----------------
1273 procedure Tree_Write is
1274 begin
1275 Rep_Table.Tree_Write;
1276 end Tree_Write;
1278 ---------------------
1279 -- Write_Info_Line --
1280 ---------------------
1282 procedure Write_Info_Line (S : String) is
1283 begin
1284 Write_Repinfo_Line_Access.all (S (S'First .. S'Last - 1));
1285 end Write_Info_Line;
1287 ---------------------
1288 -- Write_Mechanism --
1289 ---------------------
1291 procedure Write_Mechanism (M : Mechanism_Type) is
1292 begin
1293 case M is
1294 when 0 =>
1295 Write_Str ("default");
1297 when -1 =>
1298 Write_Str ("copy");
1300 when -2 =>
1301 Write_Str ("reference");
1303 when -3 =>
1304 Write_Str ("descriptor");
1306 when -4 =>
1307 Write_Str ("descriptor (UBS)");
1309 when -5 =>
1310 Write_Str ("descriptor (UBSB)");
1312 when -6 =>
1313 Write_Str ("descriptor (UBA)");
1315 when -7 =>
1316 Write_Str ("descriptor (S)");
1318 when -8 =>
1319 Write_Str ("descriptor (SB)");
1321 when -9 =>
1322 Write_Str ("descriptor (A)");
1324 when -10 =>
1325 Write_Str ("descriptor (NCA)");
1327 when others =>
1328 raise Program_Error;
1329 end case;
1330 end Write_Mechanism;
1332 ---------------
1333 -- Write_Val --
1334 ---------------
1336 procedure Write_Val (Val : Node_Ref_Or_Val; Paren : Boolean := False) is
1337 begin
1338 if Rep_Not_Constant (Val) then
1339 if List_Representation_Info < 3 or else Val = No_Uint then
1340 Write_Str ("??");
1342 else
1343 if Back_End_Layout then
1344 Write_Char (' ');
1346 if Paren then
1347 Write_Char ('(');
1348 List_GCC_Expression (Val);
1349 Write_Char (')');
1350 else
1351 List_GCC_Expression (Val);
1352 end if;
1354 Write_Char (' ');
1356 else
1357 if Paren then
1358 Write_Char ('(');
1359 Write_Name_Decoded (Chars (Get_Dynamic_SO_Entity (Val)));
1360 Write_Char (')');
1361 else
1362 Write_Name_Decoded (Chars (Get_Dynamic_SO_Entity (Val)));
1363 end if;
1364 end if;
1365 end if;
1367 else
1368 UI_Write (Val);
1369 end if;
1370 end Write_Val;
1372 end Repinfo;