comparison gcc/ada/exp_imgv.adb @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
comparison
equal deleted inserted replaced
68:561a7518be6b 111:04ced10e8804
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ I M G V --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2017, 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 3, 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 COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
25
26 with Atree; use Atree;
27 with Casing; use Casing;
28 with Checks; use Checks;
29 with Einfo; use Einfo;
30 with Exp_Util; use Exp_Util;
31 with Lib; use Lib;
32 with Namet; use Namet;
33 with Nmake; use Nmake;
34 with Nlists; use Nlists;
35 with Opt; use Opt;
36 with Rtsfind; use Rtsfind;
37 with Sem_Aux; use Sem_Aux;
38 with Sem_Res; use Sem_Res;
39 with Sem_Util; use Sem_Util;
40 with Sinfo; use Sinfo;
41 with Snames; use Snames;
42 with Stand; use Stand;
43 with Stringt; use Stringt;
44 with Tbuild; use Tbuild;
45 with Ttypes; use Ttypes;
46 with Uintp; use Uintp;
47 with Urealp; use Urealp;
48
49 package body Exp_Imgv is
50
51 function Has_Decimal_Small (E : Entity_Id) return Boolean;
52 -- Applies to all entities. True for a Decimal_Fixed_Point_Type, or an
53 -- Ordinary_Fixed_Point_Type with a small that is a negative power of ten.
54 -- Shouldn't this be in einfo.adb or sem_aux.adb???
55
56 procedure Rewrite_Object_Image
57 (N : Node_Id;
58 Pref : Entity_Id;
59 Attr_Name : Name_Id;
60 Str_Typ : Entity_Id);
61 -- AI12-00124: Rewrite attribute 'Image when it is applied to an object
62 -- reference as an attribute applied to a type. N denotes the node to be
63 -- rewritten, Pref denotes the prefix of the 'Image attribute, and Name
64 -- and Str_Typ specify which specific string type and 'Image attribute to
65 -- apply (e.g. Name_Wide_Image and Standard_Wide_String).
66
67 ------------------------------------
68 -- Build_Enumeration_Image_Tables --
69 ------------------------------------
70
71 procedure Build_Enumeration_Image_Tables (E : Entity_Id; N : Node_Id) is
72 Loc : constant Source_Ptr := Sloc (E);
73 Str : String_Id;
74 Ind : List_Id;
75 Lit : Entity_Id;
76 Nlit : Nat;
77 Len : Nat;
78 Estr : Entity_Id;
79 Eind : Entity_Id;
80 Ityp : Node_Id;
81
82 begin
83 -- Nothing to do for other than a root enumeration type
84
85 if E /= Root_Type (E) then
86 return;
87
88 -- Nothing to do if pragma Discard_Names applies
89
90 elsif Discard_Names (E) then
91 return;
92 end if;
93
94 -- Otherwise tables need constructing
95
96 Start_String;
97 Ind := New_List;
98 Lit := First_Literal (E);
99 Len := 1;
100 Nlit := 0;
101
102 loop
103 Append_To (Ind,
104 Make_Integer_Literal (Loc, UI_From_Int (Len)));
105
106 exit when No (Lit);
107 Nlit := Nlit + 1;
108
109 Get_Unqualified_Decoded_Name_String (Chars (Lit));
110
111 if Name_Buffer (1) /= ''' then
112 Set_Casing (All_Upper_Case);
113 end if;
114
115 Store_String_Chars (Name_Buffer (1 .. Name_Len));
116 Len := Len + Int (Name_Len);
117 Next_Literal (Lit);
118 end loop;
119
120 if Len < Int (2 ** (8 - 1)) then
121 Ityp := Standard_Integer_8;
122 elsif Len < Int (2 ** (16 - 1)) then
123 Ityp := Standard_Integer_16;
124 else
125 Ityp := Standard_Integer_32;
126 end if;
127
128 Str := End_String;
129
130 Estr :=
131 Make_Defining_Identifier (Loc,
132 Chars => New_External_Name (Chars (E), 'S'));
133
134 Eind :=
135 Make_Defining_Identifier (Loc,
136 Chars => New_External_Name (Chars (E), 'N'));
137
138 Set_Lit_Strings (E, Estr);
139 Set_Lit_Indexes (E, Eind);
140
141 Insert_Actions (N,
142 New_List (
143 Make_Object_Declaration (Loc,
144 Defining_Identifier => Estr,
145 Constant_Present => True,
146 Object_Definition =>
147 New_Occurrence_Of (Standard_String, Loc),
148 Expression =>
149 Make_String_Literal (Loc,
150 Strval => Str)),
151
152 Make_Object_Declaration (Loc,
153 Defining_Identifier => Eind,
154 Constant_Present => True,
155
156 Object_Definition =>
157 Make_Constrained_Array_Definition (Loc,
158 Discrete_Subtype_Definitions => New_List (
159 Make_Range (Loc,
160 Low_Bound => Make_Integer_Literal (Loc, 0),
161 High_Bound => Make_Integer_Literal (Loc, Nlit))),
162 Component_Definition =>
163 Make_Component_Definition (Loc,
164 Aliased_Present => False,
165 Subtype_Indication => New_Occurrence_Of (Ityp, Loc))),
166
167 Expression =>
168 Make_Aggregate (Loc,
169 Expressions => Ind))),
170 Suppress => All_Checks);
171 end Build_Enumeration_Image_Tables;
172
173 ----------------------------
174 -- Expand_Image_Attribute --
175 ----------------------------
176
177 -- For all cases other than user-defined enumeration types, the scheme
178 -- is as follows. First we insert the following code:
179
180 -- Snn : String (1 .. rt'Width);
181 -- Pnn : Natural;
182 -- Image_xx (tv, Snn, Pnn [,pm]);
183 --
184 -- and then Expr is replaced by Snn (1 .. Pnn)
185
186 -- In the above expansion:
187
188 -- rt is the root type of the expression
189 -- tv is the expression with the value, usually a type conversion
190 -- pm is an extra parameter present in some cases
191
192 -- The following table shows tv, xx, and (if used) pm for the various
193 -- possible types of the argument:
194
195 -- For types whose root type is Character
196 -- xx = Character
197 -- tv = Character (Expr)
198
199 -- For types whose root type is Boolean
200 -- xx = Boolean
201 -- tv = Boolean (Expr)
202
203 -- For signed integer types with size <= Integer'Size
204 -- xx = Integer
205 -- tv = Integer (Expr)
206
207 -- For other signed integer types
208 -- xx = Long_Long_Integer
209 -- tv = Long_Long_Integer (Expr)
210
211 -- For modular types with modulus <= System.Unsigned_Types.Unsigned
212 -- xx = Unsigned
213 -- tv = System.Unsigned_Types.Unsigned (Expr)
214
215 -- For other modular integer types
216 -- xx = Long_Long_Unsigned
217 -- tv = System.Unsigned_Types.Long_Long_Unsigned (Expr)
218
219 -- For types whose root type is Wide_Character
220 -- xx = Wide_Character
221 -- tv = Wide_Character (Expr)
222 -- pm = Boolean, true if Ada 2005 mode, False otherwise
223
224 -- For types whose root type is Wide_Wide_Character
225 -- xx = Wide_Wide_Character
226 -- tv = Wide_Wide_Character (Expr)
227
228 -- For floating-point types
229 -- xx = Floating_Point
230 -- tv = Long_Long_Float (Expr)
231 -- pm = typ'Digits (typ = subtype of expression)
232
233 -- For ordinary fixed-point types
234 -- xx = Ordinary_Fixed_Point
235 -- tv = Long_Long_Float (Expr)
236 -- pm = typ'Aft (typ = subtype of expression)
237
238 -- For decimal fixed-point types with size = Integer'Size
239 -- xx = Decimal
240 -- tv = Integer (Expr)
241 -- pm = typ'Scale (typ = subtype of expression)
242
243 -- For decimal fixed-point types with size > Integer'Size
244 -- xx = Long_Long_Decimal
245 -- tv = Long_Long_Integer?(Expr) [convert with no scaling]
246 -- pm = typ'Scale (typ = subtype of expression)
247
248 -- For enumeration types other than those declared packages Standard
249 -- or System, Snn, Pnn, are expanded as above, but the call looks like:
250
251 -- Image_Enumeration_NN (rt'Pos (X), Snn, Pnn, typS, typI'Address)
252
253 -- where rt is the root type of the expression, and typS and typI are
254 -- the entities constructed as described in the spec for the procedure
255 -- Build_Enumeration_Image_Tables and NN is 32/16/8 depending on the
256 -- element type of Lit_Indexes. The rewriting of the expression to
257 -- Snn (1 .. Pnn) then occurs as in the other cases. A special case is
258 -- when pragma Discard_Names applies, in which case we replace expr by:
259
260 -- (rt'Pos (expr))'Img
261
262 -- So that the result is a space followed by the decimal value for the
263 -- position of the enumeration value in the enumeration type.
264
265 procedure Expand_Image_Attribute (N : Node_Id) is
266 Loc : constant Source_Ptr := Sloc (N);
267 Exprs : constant List_Id := Expressions (N);
268 Expr : constant Node_Id := Relocate_Node (First (Exprs));
269 Pref : constant Node_Id := Prefix (N);
270
271 procedure Expand_User_Defined_Enumeration_Image;
272 -- Expand attribute 'Image in user-defined enumeration types, avoiding
273 -- string copy.
274
275 function Is_User_Defined_Enumeration_Type
276 (Typ : Entity_Id) return Boolean;
277 -- Return True if Typ is a user-defined enumeration type
278
279 -------------------------------------------
280 -- Expand_User_Defined_Enumeration_Image --
281 -------------------------------------------
282
283 procedure Expand_User_Defined_Enumeration_Image is
284 Ins_List : constant List_Id := New_List;
285 P1_Id : constant Entity_Id := Make_Temporary (Loc, 'P');
286 P2_Id : constant Entity_Id := Make_Temporary (Loc, 'P');
287 P3_Id : constant Entity_Id := Make_Temporary (Loc, 'P');
288 P4_Id : constant Entity_Id := Make_Temporary (Loc, 'P');
289 Ptyp : constant Entity_Id := Entity (Pref);
290 Rtyp : constant Entity_Id := Root_Type (Ptyp);
291 S1_Id : constant Entity_Id := Make_Temporary (Loc, 'S');
292
293 begin
294 -- Apply a validity check, since it is a bit drastic to get a
295 -- completely junk image value for an invalid value.
296
297 if not Expr_Known_Valid (Expr) then
298 Insert_Valid_Check (Expr);
299 end if;
300
301 -- Generate:
302 -- P1 : constant Natural := Pos;
303
304 Append_To (Ins_List,
305 Make_Object_Declaration (Loc,
306 Defining_Identifier => P1_Id,
307 Object_Definition =>
308 New_Occurrence_Of (Standard_Natural, Loc),
309 Constant_Present => True,
310 Expression =>
311 Convert_To (Standard_Natural,
312 Make_Attribute_Reference (Loc,
313 Attribute_Name => Name_Pos,
314 Prefix => New_Occurrence_Of (Ptyp, Loc),
315 Expressions => New_List (Expr)))));
316
317 -- Compute the index of the string start, generating:
318 -- P2 : constant Natural := call_put_enumN (P1);
319
320 Append_To (Ins_List,
321 Make_Object_Declaration (Loc,
322 Defining_Identifier => P2_Id,
323 Object_Definition =>
324 New_Occurrence_Of (Standard_Natural, Loc),
325 Constant_Present => True,
326 Expression =>
327 Convert_To (Standard_Natural,
328 Make_Indexed_Component (Loc,
329 Prefix =>
330 New_Occurrence_Of (Lit_Indexes (Rtyp), Loc),
331 Expressions =>
332 New_List (New_Occurrence_Of (P1_Id, Loc))))));
333
334 -- Compute the index of the next value, generating:
335 -- P3 : constant Natural := call_put_enumN (P1 + 1);
336
337 declare
338 Add_Node : constant Node_Id := New_Op_Node (N_Op_Add, Loc);
339
340 begin
341 Set_Left_Opnd (Add_Node, New_Occurrence_Of (P1_Id, Loc));
342 Set_Right_Opnd (Add_Node, Make_Integer_Literal (Loc, 1));
343
344 Append_To (Ins_List,
345 Make_Object_Declaration (Loc,
346 Defining_Identifier => P3_Id,
347 Object_Definition =>
348 New_Occurrence_Of (Standard_Natural, Loc),
349 Constant_Present => True,
350 Expression =>
351 Convert_To (Standard_Natural,
352 Make_Indexed_Component (Loc,
353 Prefix =>
354 New_Occurrence_Of (Lit_Indexes (Rtyp), Loc),
355 Expressions =>
356 New_List (Add_Node)))));
357 end;
358
359 -- Generate:
360 -- S4 : String renames call_put_enumS (S2 .. S3 - 1);
361
362 declare
363 Sub_Node : constant Node_Id := New_Op_Node (N_Op_Subtract, Loc);
364
365 begin
366 Set_Left_Opnd (Sub_Node, New_Occurrence_Of (P3_Id, Loc));
367 Set_Right_Opnd (Sub_Node, Make_Integer_Literal (Loc, 1));
368
369 Append_To (Ins_List,
370 Make_Object_Renaming_Declaration (Loc,
371 Defining_Identifier => P4_Id,
372 Subtype_Mark =>
373 New_Occurrence_Of (Standard_String, Loc),
374 Name =>
375 Make_Slice (Loc,
376 Prefix =>
377 New_Occurrence_Of (Lit_Strings (Rtyp), Loc),
378 Discrete_Range =>
379 Make_Range (Loc,
380 Low_Bound => New_Occurrence_Of (P2_Id, Loc),
381 High_Bound => Sub_Node))));
382 end;
383
384 -- Generate:
385 -- subtype S1 is string (1 .. P3 - P2);
386
387 declare
388 HB : constant Node_Id := New_Op_Node (N_Op_Subtract, Loc);
389
390 begin
391 Set_Left_Opnd (HB, New_Occurrence_Of (P3_Id, Loc));
392 Set_Right_Opnd (HB, New_Occurrence_Of (P2_Id, Loc));
393
394 Append_To (Ins_List,
395 Make_Subtype_Declaration (Loc,
396 Defining_Identifier => S1_Id,
397 Subtype_Indication =>
398 Make_Subtype_Indication (Loc,
399 Subtype_Mark =>
400 New_Occurrence_Of (Standard_String, Loc),
401 Constraint =>
402 Make_Index_Or_Discriminant_Constraint (Loc,
403 Constraints => New_List (
404 Make_Range (Loc,
405 Low_Bound => Make_Integer_Literal (Loc, 1),
406 High_Bound => HB))))));
407 end;
408
409 -- Insert all the above declarations before N. We suppress checks
410 -- because everything is in range at this stage.
411
412 Insert_Actions (N, Ins_List, Suppress => All_Checks);
413
414 Rewrite (N,
415 Unchecked_Convert_To (S1_Id, New_Occurrence_Of (P4_Id, Loc)));
416
417 Analyze_And_Resolve (N, Standard_String);
418 end Expand_User_Defined_Enumeration_Image;
419
420 --------------------------------------
421 -- Is_User_Defined_Enumeration_Type --
422 --------------------------------------
423
424 function Is_User_Defined_Enumeration_Type
425 (Typ : Entity_Id) return Boolean is
426 begin
427 return Ekind (Typ) = E_Enumeration_Type
428 and then Typ /= Standard_Boolean
429 and then Typ /= Standard_Character
430 and then Typ /= Standard_Wide_Character
431 and then Typ /= Standard_Wide_Wide_Character;
432 end Is_User_Defined_Enumeration_Type;
433
434 -- Local variables
435
436 Imid : RE_Id;
437 Ptyp : Entity_Id;
438 Rtyp : Entity_Id;
439 Tent : Entity_Id;
440 Ttyp : Entity_Id;
441 Proc_Ent : Entity_Id;
442 Enum_Case : Boolean;
443
444 Arg_List : List_Id;
445 -- List of arguments for run-time procedure call
446
447 Ins_List : List_Id;
448 -- List of actions to be inserted
449
450 Snn : constant Entity_Id := Make_Temporary (Loc, 'S');
451 Pnn : constant Entity_Id := Make_Temporary (Loc, 'P');
452
453 begin
454 if Is_Object_Image (Pref) then
455 Rewrite_Object_Image (N, Pref, Name_Image, Standard_String);
456 return;
457
458 -- Enable speed-optimized expansion of user-defined enumeration types
459 -- if we are compiling with optimizations enabled and enumeration type
460 -- literals are generated. Otherwise the call will be expanded into a
461 -- call to the runtime library.
462
463 elsif Optimization_Level > 0
464 and then not Global_Discard_Names
465 and then Is_User_Defined_Enumeration_Type (Root_Type (Entity (Pref)))
466 then
467 Expand_User_Defined_Enumeration_Image;
468 return;
469 end if;
470
471 Ptyp := Entity (Pref);
472 Rtyp := Root_Type (Ptyp);
473
474 -- Build declarations of Snn and Pnn to be inserted
475
476 Ins_List := New_List (
477
478 -- Snn : String (1 .. typ'Width);
479
480 Make_Object_Declaration (Loc,
481 Defining_Identifier => Snn,
482 Object_Definition =>
483 Make_Subtype_Indication (Loc,
484 Subtype_Mark => New_Occurrence_Of (Standard_String, Loc),
485 Constraint =>
486 Make_Index_Or_Discriminant_Constraint (Loc,
487 Constraints => New_List (
488 Make_Range (Loc,
489 Low_Bound => Make_Integer_Literal (Loc, 1),
490 High_Bound =>
491 Make_Attribute_Reference (Loc,
492 Prefix => New_Occurrence_Of (Rtyp, Loc),
493 Attribute_Name => Name_Width)))))),
494
495 -- Pnn : Natural;
496
497 Make_Object_Declaration (Loc,
498 Defining_Identifier => Pnn,
499 Object_Definition => New_Occurrence_Of (Standard_Natural, Loc)));
500
501 -- Set Imid (RE_Id of procedure to call), and Tent, target for the
502 -- type conversion of the first argument for all possibilities.
503
504 Enum_Case := False;
505
506 if Rtyp = Standard_Boolean then
507 Imid := RE_Image_Boolean;
508 Tent := Rtyp;
509
510 -- For standard character, we have to select the version which handles
511 -- soft hyphen correctly, based on the version of Ada in use (this is
512 -- ugly, but we have no choice).
513
514 elsif Rtyp = Standard_Character then
515 if Ada_Version < Ada_2005 then
516 Imid := RE_Image_Character;
517 else
518 Imid := RE_Image_Character_05;
519 end if;
520
521 Tent := Rtyp;
522
523 elsif Rtyp = Standard_Wide_Character then
524 Imid := RE_Image_Wide_Character;
525 Tent := Rtyp;
526
527 elsif Rtyp = Standard_Wide_Wide_Character then
528 Imid := RE_Image_Wide_Wide_Character;
529 Tent := Rtyp;
530
531 elsif Is_Signed_Integer_Type (Rtyp) then
532 if Esize (Rtyp) <= Esize (Standard_Integer) then
533 Imid := RE_Image_Integer;
534 Tent := Standard_Integer;
535 else
536 Imid := RE_Image_Long_Long_Integer;
537 Tent := Standard_Long_Long_Integer;
538 end if;
539
540 elsif Is_Modular_Integer_Type (Rtyp) then
541 if Modulus (Rtyp) <= Modulus (RTE (RE_Unsigned)) then
542 Imid := RE_Image_Unsigned;
543 Tent := RTE (RE_Unsigned);
544 else
545 Imid := RE_Image_Long_Long_Unsigned;
546 Tent := RTE (RE_Long_Long_Unsigned);
547 end if;
548
549 elsif Is_Fixed_Point_Type (Rtyp) and then Has_Decimal_Small (Rtyp) then
550 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
551 Imid := RE_Image_Decimal;
552 Tent := Standard_Integer;
553 else
554 Imid := RE_Image_Long_Long_Decimal;
555 Tent := Standard_Long_Long_Integer;
556 end if;
557
558 elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
559 Imid := RE_Image_Ordinary_Fixed_Point;
560 Tent := Standard_Long_Long_Float;
561
562 elsif Is_Floating_Point_Type (Rtyp) then
563 Imid := RE_Image_Floating_Point;
564 Tent := Standard_Long_Long_Float;
565
566 -- Only other possibility is user-defined enumeration type
567
568 else
569 if Discard_Names (First_Subtype (Ptyp))
570 or else No (Lit_Strings (Root_Type (Ptyp)))
571 then
572 -- When pragma Discard_Names applies to the first subtype, build
573 -- (Pref'Pos (Expr))'Img.
574
575 Rewrite (N,
576 Make_Attribute_Reference (Loc,
577 Prefix =>
578 Make_Attribute_Reference (Loc,
579 Prefix => Pref,
580 Attribute_Name => Name_Pos,
581 Expressions => New_List (Expr)),
582 Attribute_Name =>
583 Name_Img));
584 Analyze_And_Resolve (N, Standard_String);
585 return;
586
587 else
588 -- Here for enumeration type case
589
590 Ttyp := Component_Type (Etype (Lit_Indexes (Rtyp)));
591
592 if Ttyp = Standard_Integer_8 then
593 Imid := RE_Image_Enumeration_8;
594
595 elsif Ttyp = Standard_Integer_16 then
596 Imid := RE_Image_Enumeration_16;
597
598 else
599 Imid := RE_Image_Enumeration_32;
600 end if;
601
602 -- Apply a validity check, since it is a bit drastic to get a
603 -- completely junk image value for an invalid value.
604
605 if not Expr_Known_Valid (Expr) then
606 Insert_Valid_Check (Expr);
607 end if;
608
609 Enum_Case := True;
610 end if;
611 end if;
612
613 -- Build first argument for call
614
615 if Enum_Case then
616 Arg_List := New_List (
617 Make_Attribute_Reference (Loc,
618 Attribute_Name => Name_Pos,
619 Prefix => New_Occurrence_Of (Ptyp, Loc),
620 Expressions => New_List (Expr)));
621
622 else
623 Arg_List := New_List (Convert_To (Tent, Expr));
624 end if;
625
626 -- Append Snn, Pnn arguments
627
628 Append_To (Arg_List, New_Occurrence_Of (Snn, Loc));
629 Append_To (Arg_List, New_Occurrence_Of (Pnn, Loc));
630
631 -- Get entity of procedure to call
632
633 Proc_Ent := RTE (Imid);
634
635 -- If the procedure entity is empty, that means we have a case in
636 -- no run time mode where the operation is not allowed, and an
637 -- appropriate diagnostic has already been issued.
638
639 if No (Proc_Ent) then
640 return;
641 end if;
642
643 -- Otherwise complete preparation of arguments for run-time call
644
645 -- Add extra arguments for Enumeration case
646
647 if Enum_Case then
648 Append_To (Arg_List, New_Occurrence_Of (Lit_Strings (Rtyp), Loc));
649 Append_To (Arg_List,
650 Make_Attribute_Reference (Loc,
651 Prefix => New_Occurrence_Of (Lit_Indexes (Rtyp), Loc),
652 Attribute_Name => Name_Address));
653
654 -- For floating-point types, append Digits argument
655
656 elsif Is_Floating_Point_Type (Rtyp) then
657 Append_To (Arg_List,
658 Make_Attribute_Reference (Loc,
659 Prefix => New_Occurrence_Of (Ptyp, Loc),
660 Attribute_Name => Name_Digits));
661
662 -- For ordinary fixed-point types, append Aft parameter
663
664 elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
665 Append_To (Arg_List,
666 Make_Attribute_Reference (Loc,
667 Prefix => New_Occurrence_Of (Ptyp, Loc),
668 Attribute_Name => Name_Aft));
669
670 if Has_Decimal_Small (Rtyp) then
671 Set_Conversion_OK (First (Arg_List));
672 Set_Etype (First (Arg_List), Tent);
673 end if;
674
675 -- For decimal, append Scale and also set to do literal conversion
676
677 elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
678 Append_To (Arg_List,
679 Make_Attribute_Reference (Loc,
680 Prefix => New_Occurrence_Of (Ptyp, Loc),
681 Attribute_Name => Name_Scale));
682
683 Set_Conversion_OK (First (Arg_List));
684 Set_Etype (First (Arg_List), Tent);
685
686 -- For Wide_Character, append Ada 2005 indication
687
688 elsif Rtyp = Standard_Wide_Character then
689 Append_To (Arg_List,
690 New_Occurrence_Of
691 (Boolean_Literals (Ada_Version >= Ada_2005), Loc));
692 end if;
693
694 -- Now append the procedure call to the insert list
695
696 Append_To (Ins_List,
697 Make_Procedure_Call_Statement (Loc,
698 Name => New_Occurrence_Of (Proc_Ent, Loc),
699 Parameter_Associations => Arg_List));
700
701 -- Insert declarations of Snn, Pnn, and the procedure call. We suppress
702 -- checks because we are sure that everything is in range at this stage.
703
704 Insert_Actions (N, Ins_List, Suppress => All_Checks);
705
706 -- Final step is to rewrite the expression as a slice and analyze,
707 -- again with no checks, since we are sure that everything is OK.
708
709 Rewrite (N,
710 Make_Slice (Loc,
711 Prefix => New_Occurrence_Of (Snn, Loc),
712 Discrete_Range =>
713 Make_Range (Loc,
714 Low_Bound => Make_Integer_Literal (Loc, 1),
715 High_Bound => New_Occurrence_Of (Pnn, Loc))));
716
717 Analyze_And_Resolve (N, Standard_String, Suppress => All_Checks);
718 end Expand_Image_Attribute;
719
720 ----------------------------
721 -- Expand_Value_Attribute --
722 ----------------------------
723
724 -- For scalar types derived from Boolean, Character and integer types
725 -- in package Standard, typ'Value (X) expands into:
726
727 -- btyp (Value_xx (X))
728
729 -- where btyp is he base type of the prefix
730
731 -- For types whose root type is Character
732 -- xx = Character
733
734 -- For types whose root type is Wide_Character
735 -- xx = Wide_Character
736
737 -- For types whose root type is Wide_Wide_Character
738 -- xx = Wide_Wide_Character
739
740 -- For types whose root type is Boolean
741 -- xx = Boolean
742
743 -- For signed integer types with size <= Integer'Size
744 -- xx = Integer
745
746 -- For other signed integer types
747 -- xx = Long_Long_Integer
748
749 -- For modular types with modulus <= System.Unsigned_Types.Unsigned
750 -- xx = Unsigned
751
752 -- For other modular integer types
753 -- xx = Long_Long_Unsigned
754
755 -- For floating-point types and ordinary fixed-point types
756 -- xx = Real
757
758 -- For Wide_[Wide_]Character types, typ'Value (X) expands into:
759
760 -- btyp (Value_xx (X, EM))
761
762 -- where btyp is the base type of the prefix, and EM is the encoding method
763
764 -- For decimal types with size <= Integer'Size, typ'Value (X)
765 -- expands into
766
767 -- btyp?(Value_Decimal (X, typ'Scale));
768
769 -- For all other decimal types, typ'Value (X) expands into
770
771 -- btyp?(Value_Long_Long_Decimal (X, typ'Scale))
772
773 -- For enumeration types other than those derived from types Boolean,
774 -- Character, Wide_[Wide_]Character in Standard, typ'Value (X) expands to:
775
776 -- Enum'Val (Value_Enumeration_NN (typS, typI'Address, Num, X))
777
778 -- where typS and typI and the Lit_Strings and Lit_Indexes entities
779 -- from T's root type entity, and Num is Enum'Pos (Enum'Last). The
780 -- Value_Enumeration_NN function will search the tables looking for
781 -- X and return the position number in the table if found which is
782 -- used to provide the result of 'Value (using Enum'Val). If the
783 -- value is not found Constraint_Error is raised. The suffix _NN
784 -- depends on the element type of typI.
785
786 procedure Expand_Value_Attribute (N : Node_Id) is
787 Loc : constant Source_Ptr := Sloc (N);
788 Typ : constant Entity_Id := Etype (N);
789 Btyp : constant Entity_Id := Base_Type (Typ);
790 Rtyp : constant Entity_Id := Root_Type (Typ);
791 Exprs : constant List_Id := Expressions (N);
792 Vid : RE_Id;
793 Args : List_Id;
794 Func : RE_Id;
795 Ttyp : Entity_Id;
796
797 begin
798 Args := Exprs;
799
800 if Rtyp = Standard_Character then
801 Vid := RE_Value_Character;
802
803 elsif Rtyp = Standard_Boolean then
804 Vid := RE_Value_Boolean;
805
806 elsif Rtyp = Standard_Wide_Character then
807 Vid := RE_Value_Wide_Character;
808
809 Append_To (Args,
810 Make_Integer_Literal (Loc,
811 Intval => Int (Wide_Character_Encoding_Method)));
812
813 elsif Rtyp = Standard_Wide_Wide_Character then
814 Vid := RE_Value_Wide_Wide_Character;
815
816 Append_To (Args,
817 Make_Integer_Literal (Loc,
818 Intval => Int (Wide_Character_Encoding_Method)));
819
820 elsif Rtyp = Base_Type (Standard_Short_Short_Integer)
821 or else Rtyp = Base_Type (Standard_Short_Integer)
822 or else Rtyp = Base_Type (Standard_Integer)
823 then
824 Vid := RE_Value_Integer;
825
826 elsif Is_Signed_Integer_Type (Rtyp) then
827 Vid := RE_Value_Long_Long_Integer;
828
829 elsif Is_Modular_Integer_Type (Rtyp) then
830 if Modulus (Rtyp) <= Modulus (RTE (RE_Unsigned)) then
831 Vid := RE_Value_Unsigned;
832 else
833 Vid := RE_Value_Long_Long_Unsigned;
834 end if;
835
836 elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
837 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
838 Vid := RE_Value_Decimal;
839 else
840 Vid := RE_Value_Long_Long_Decimal;
841 end if;
842
843 Append_To (Args,
844 Make_Attribute_Reference (Loc,
845 Prefix => New_Occurrence_Of (Typ, Loc),
846 Attribute_Name => Name_Scale));
847
848 Rewrite (N,
849 OK_Convert_To (Btyp,
850 Make_Function_Call (Loc,
851 Name => New_Occurrence_Of (RTE (Vid), Loc),
852 Parameter_Associations => Args)));
853
854 Set_Etype (N, Btyp);
855 Analyze_And_Resolve (N, Btyp);
856 return;
857
858 elsif Is_Real_Type (Rtyp) then
859 Vid := RE_Value_Real;
860
861 -- Only other possibility is user-defined enumeration type
862
863 else
864 pragma Assert (Is_Enumeration_Type (Rtyp));
865
866 -- Case of pragma Discard_Names, transform the Value
867 -- attribute to Btyp'Val (Long_Long_Integer'Value (Args))
868
869 if Discard_Names (First_Subtype (Typ))
870 or else No (Lit_Strings (Rtyp))
871 then
872 Rewrite (N,
873 Make_Attribute_Reference (Loc,
874 Prefix => New_Occurrence_Of (Btyp, Loc),
875 Attribute_Name => Name_Val,
876 Expressions => New_List (
877 Make_Attribute_Reference (Loc,
878 Prefix =>
879 New_Occurrence_Of (Standard_Long_Long_Integer, Loc),
880 Attribute_Name => Name_Value,
881 Expressions => Args))));
882
883 Analyze_And_Resolve (N, Btyp);
884
885 -- Here for normal case where we have enumeration tables, this
886 -- is where we build
887
888 -- T'Val (Value_Enumeration_NN (typS, typI'Address, Num, X))
889
890 else
891 Ttyp := Component_Type (Etype (Lit_Indexes (Rtyp)));
892
893 if Ttyp = Standard_Integer_8 then
894 Func := RE_Value_Enumeration_8;
895 elsif Ttyp = Standard_Integer_16 then
896 Func := RE_Value_Enumeration_16;
897 else
898 Func := RE_Value_Enumeration_32;
899 end if;
900
901 Prepend_To (Args,
902 Make_Attribute_Reference (Loc,
903 Prefix => New_Occurrence_Of (Rtyp, Loc),
904 Attribute_Name => Name_Pos,
905 Expressions => New_List (
906 Make_Attribute_Reference (Loc,
907 Prefix => New_Occurrence_Of (Rtyp, Loc),
908 Attribute_Name => Name_Last))));
909
910 Prepend_To (Args,
911 Make_Attribute_Reference (Loc,
912 Prefix => New_Occurrence_Of (Lit_Indexes (Rtyp), Loc),
913 Attribute_Name => Name_Address));
914
915 Prepend_To (Args,
916 New_Occurrence_Of (Lit_Strings (Rtyp), Loc));
917
918 Rewrite (N,
919 Make_Attribute_Reference (Loc,
920 Prefix => New_Occurrence_Of (Typ, Loc),
921 Attribute_Name => Name_Val,
922 Expressions => New_List (
923 Make_Function_Call (Loc,
924 Name =>
925 New_Occurrence_Of (RTE (Func), Loc),
926 Parameter_Associations => Args))));
927
928 Analyze_And_Resolve (N, Btyp);
929 end if;
930
931 return;
932 end if;
933
934 -- Fall through for all cases except user-defined enumeration type
935 -- and decimal types, with Vid set to the Id of the entity for the
936 -- Value routine and Args set to the list of parameters for the call.
937
938 -- Compiling package Ada.Tags under No_Run_Time_Mode we disable the
939 -- expansion of the attribute into the function call statement to avoid
940 -- generating spurious errors caused by the use of Integer_Address'Value
941 -- in our implementation of Ada.Tags.Internal_Tag
942
943 -- Seems like a bit of a odd approach, there should be a better way ???
944
945 -- There is a better way, test RTE_Available ???
946
947 if No_Run_Time_Mode
948 and then Rtyp = RTE (RE_Integer_Address)
949 and then RTU_Loaded (Ada_Tags)
950 and then Cunit_Entity (Current_Sem_Unit)
951 = Body_Entity (RTU_Entity (Ada_Tags))
952 then
953 Rewrite (N,
954 Unchecked_Convert_To (Rtyp,
955 Make_Integer_Literal (Loc, Uint_0)));
956 else
957 Rewrite (N,
958 Convert_To (Btyp,
959 Make_Function_Call (Loc,
960 Name => New_Occurrence_Of (RTE (Vid), Loc),
961 Parameter_Associations => Args)));
962 end if;
963
964 Analyze_And_Resolve (N, Btyp);
965 end Expand_Value_Attribute;
966
967 ---------------------------------
968 -- Expand_Wide_Image_Attribute --
969 ---------------------------------
970
971 -- We expand typ'Wide_Image (X) as follows. First we insert this code:
972
973 -- Rnn : Wide_String (1 .. rt'Wide_Width);
974 -- Lnn : Natural;
975 -- String_To_Wide_String
976 -- (typ'Image (Expr), Rnn, Lnn, Wide_Character_Encoding_Method);
977
978 -- where rt is the root type of the prefix type
979
980 -- Now we replace the Wide_Image reference by
981
982 -- Rnn (1 .. Lnn)
983
984 -- This works in all cases because String_To_Wide_String converts any
985 -- wide character escape sequences resulting from the Image call to the
986 -- proper Wide_Character equivalent
987
988 -- not quite right for typ = Wide_Character ???
989
990 procedure Expand_Wide_Image_Attribute (N : Node_Id) is
991 Loc : constant Source_Ptr := Sloc (N);
992 Pref : constant Entity_Id := Prefix (N);
993 Rnn : constant Entity_Id := Make_Temporary (Loc, 'S');
994 Lnn : constant Entity_Id := Make_Temporary (Loc, 'P');
995 Rtyp : Entity_Id;
996
997 begin
998 if Is_Object_Image (Pref) then
999 Rewrite_Object_Image (N, Pref, Name_Wide_Image, Standard_Wide_String);
1000 return;
1001 end if;
1002
1003 Rtyp := Root_Type (Entity (Pref));
1004
1005 Insert_Actions (N, New_List (
1006
1007 -- Rnn : Wide_String (1 .. base_typ'Width);
1008
1009 Make_Object_Declaration (Loc,
1010 Defining_Identifier => Rnn,
1011 Object_Definition =>
1012 Make_Subtype_Indication (Loc,
1013 Subtype_Mark =>
1014 New_Occurrence_Of (Standard_Wide_String, Loc),
1015 Constraint =>
1016 Make_Index_Or_Discriminant_Constraint (Loc,
1017 Constraints => New_List (
1018 Make_Range (Loc,
1019 Low_Bound => Make_Integer_Literal (Loc, 1),
1020 High_Bound =>
1021 Make_Attribute_Reference (Loc,
1022 Prefix => New_Occurrence_Of (Rtyp, Loc),
1023 Attribute_Name => Name_Wide_Width)))))),
1024
1025 -- Lnn : Natural;
1026
1027 Make_Object_Declaration (Loc,
1028 Defining_Identifier => Lnn,
1029 Object_Definition => New_Occurrence_Of (Standard_Natural, Loc)),
1030
1031 -- String_To_Wide_String
1032 -- (typ'Image (X), Rnn, Lnn, Wide_Character_Encoding_Method);
1033
1034 Make_Procedure_Call_Statement (Loc,
1035 Name =>
1036 New_Occurrence_Of (RTE (RE_String_To_Wide_String), Loc),
1037
1038 Parameter_Associations => New_List (
1039 Make_Attribute_Reference (Loc,
1040 Prefix => Prefix (N),
1041 Attribute_Name => Name_Image,
1042 Expressions => Expressions (N)),
1043 New_Occurrence_Of (Rnn, Loc),
1044 New_Occurrence_Of (Lnn, Loc),
1045 Make_Integer_Literal (Loc,
1046 Intval => Int (Wide_Character_Encoding_Method))))),
1047
1048 -- Suppress checks because we know everything is properly in range
1049
1050 Suppress => All_Checks);
1051
1052 -- Final step is to rewrite the expression as a slice and analyze,
1053 -- again with no checks, since we are sure that everything is OK.
1054
1055 Rewrite (N,
1056 Make_Slice (Loc,
1057 Prefix => New_Occurrence_Of (Rnn, Loc),
1058 Discrete_Range =>
1059 Make_Range (Loc,
1060 Low_Bound => Make_Integer_Literal (Loc, 1),
1061 High_Bound => New_Occurrence_Of (Lnn, Loc))));
1062
1063 Analyze_And_Resolve (N, Standard_Wide_String, Suppress => All_Checks);
1064 end Expand_Wide_Image_Attribute;
1065
1066 --------------------------------------
1067 -- Expand_Wide_Wide_Image_Attribute --
1068 --------------------------------------
1069
1070 -- We expand typ'Wide_Wide_Image (X) as follows. First we insert this code:
1071
1072 -- Rnn : Wide_Wide_String (1 .. rt'Wide_Wide_Width);
1073 -- Lnn : Natural;
1074 -- String_To_Wide_Wide_String
1075 -- (typ'Image (Expr), Rnn, Lnn, Wide_Character_Encoding_Method);
1076
1077 -- where rt is the root type of the prefix type
1078
1079 -- Now we replace the Wide_Wide_Image reference by
1080
1081 -- Rnn (1 .. Lnn)
1082
1083 -- This works in all cases because String_To_Wide_Wide_String converts any
1084 -- wide character escape sequences resulting from the Image call to the
1085 -- proper Wide_Wide_Character equivalent
1086
1087 -- not quite right for typ = Wide_Wide_Character ???
1088
1089 procedure Expand_Wide_Wide_Image_Attribute (N : Node_Id) is
1090 Loc : constant Source_Ptr := Sloc (N);
1091 Pref : constant Entity_Id := Prefix (N);
1092 Rnn : constant Entity_Id := Make_Temporary (Loc, 'S');
1093 Lnn : constant Entity_Id := Make_Temporary (Loc, 'P');
1094 Rtyp : Entity_Id;
1095
1096 begin
1097 if Is_Object_Image (Pref) then
1098 Rewrite_Object_Image
1099 (N, Pref, Name_Wide_Wide_Image, Standard_Wide_Wide_String);
1100 return;
1101 end if;
1102
1103 Rtyp := Root_Type (Entity (Pref));
1104
1105 Insert_Actions (N, New_List (
1106
1107 -- Rnn : Wide_Wide_String (1 .. rt'Wide_Wide_Width);
1108
1109 Make_Object_Declaration (Loc,
1110 Defining_Identifier => Rnn,
1111 Object_Definition =>
1112 Make_Subtype_Indication (Loc,
1113 Subtype_Mark =>
1114 New_Occurrence_Of (Standard_Wide_Wide_String, Loc),
1115 Constraint =>
1116 Make_Index_Or_Discriminant_Constraint (Loc,
1117 Constraints => New_List (
1118 Make_Range (Loc,
1119 Low_Bound => Make_Integer_Literal (Loc, 1),
1120 High_Bound =>
1121 Make_Attribute_Reference (Loc,
1122 Prefix => New_Occurrence_Of (Rtyp, Loc),
1123 Attribute_Name => Name_Wide_Wide_Width)))))),
1124
1125 -- Lnn : Natural;
1126
1127 Make_Object_Declaration (Loc,
1128 Defining_Identifier => Lnn,
1129 Object_Definition => New_Occurrence_Of (Standard_Natural, Loc)),
1130
1131 -- String_To_Wide_Wide_String
1132 -- (typ'Image (X), Rnn, Lnn, Wide_Character_Encoding_Method);
1133
1134 Make_Procedure_Call_Statement (Loc,
1135 Name =>
1136 New_Occurrence_Of (RTE (RE_String_To_Wide_Wide_String), Loc),
1137
1138 Parameter_Associations => New_List (
1139 Make_Attribute_Reference (Loc,
1140 Prefix => Prefix (N),
1141 Attribute_Name => Name_Image,
1142 Expressions => Expressions (N)),
1143 New_Occurrence_Of (Rnn, Loc),
1144 New_Occurrence_Of (Lnn, Loc),
1145 Make_Integer_Literal (Loc,
1146 Intval => Int (Wide_Character_Encoding_Method))))),
1147
1148 -- Suppress checks because we know everything is properly in range
1149
1150 Suppress => All_Checks);
1151
1152 -- Final step is to rewrite the expression as a slice and analyze,
1153 -- again with no checks, since we are sure that everything is OK.
1154
1155 Rewrite (N,
1156 Make_Slice (Loc,
1157 Prefix => New_Occurrence_Of (Rnn, Loc),
1158 Discrete_Range =>
1159 Make_Range (Loc,
1160 Low_Bound => Make_Integer_Literal (Loc, 1),
1161 High_Bound => New_Occurrence_Of (Lnn, Loc))));
1162
1163 Analyze_And_Resolve
1164 (N, Standard_Wide_Wide_String, Suppress => All_Checks);
1165 end Expand_Wide_Wide_Image_Attribute;
1166
1167 ----------------------------
1168 -- Expand_Width_Attribute --
1169 ----------------------------
1170
1171 -- The processing here also handles the case of Wide_[Wide_]Width. With the
1172 -- exceptions noted, the processing is identical
1173
1174 -- For scalar types derived from Boolean, character and integer types
1175 -- in package Standard. Note that the Width attribute is computed at
1176 -- compile time for all cases except those involving non-static sub-
1177 -- types. For such subtypes, typ'[Wide_[Wide_]]Width expands into:
1178
1179 -- Result_Type (xx (yy (Ptyp'First), yy (Ptyp'Last)))
1180
1181 -- where
1182
1183 -- For types whose root type is Character
1184 -- xx = Width_Character
1185 -- yy = Character
1186
1187 -- For types whose root type is Wide_Character
1188 -- xx = Wide_Width_Character
1189 -- yy = Character
1190
1191 -- For types whose root type is Wide_Wide_Character
1192 -- xx = Wide_Wide_Width_Character
1193 -- yy = Character
1194
1195 -- For types whose root type is Boolean
1196 -- xx = Width_Boolean
1197 -- yy = Boolean
1198
1199 -- For signed integer types
1200 -- xx = Width_Long_Long_Integer
1201 -- yy = Long_Long_Integer
1202
1203 -- For modular integer types
1204 -- xx = Width_Long_Long_Unsigned
1205 -- yy = Long_Long_Unsigned
1206
1207 -- For types derived from Wide_Character, typ'Width expands into
1208
1209 -- Result_Type (Width_Wide_Character (
1210 -- Wide_Character (typ'First),
1211 -- Wide_Character (typ'Last),
1212
1213 -- and typ'Wide_Width expands into:
1214
1215 -- Result_Type (Wide_Width_Wide_Character (
1216 -- Wide_Character (typ'First),
1217 -- Wide_Character (typ'Last));
1218
1219 -- and typ'Wide_Wide_Width expands into
1220
1221 -- Result_Type (Wide_Wide_Width_Wide_Character (
1222 -- Wide_Character (typ'First),
1223 -- Wide_Character (typ'Last));
1224
1225 -- For types derived from Wide_Wide_Character, typ'Width expands into
1226
1227 -- Result_Type (Width_Wide_Wide_Character (
1228 -- Wide_Wide_Character (typ'First),
1229 -- Wide_Wide_Character (typ'Last),
1230
1231 -- and typ'Wide_Width expands into:
1232
1233 -- Result_Type (Wide_Width_Wide_Wide_Character (
1234 -- Wide_Wide_Character (typ'First),
1235 -- Wide_Wide_Character (typ'Last));
1236
1237 -- and typ'Wide_Wide_Width expands into
1238
1239 -- Result_Type (Wide_Wide_Width_Wide_Wide_Char (
1240 -- Wide_Wide_Character (typ'First),
1241 -- Wide_Wide_Character (typ'Last));
1242
1243 -- For real types, typ'Width and typ'Wide_[Wide_]Width expand into
1244
1245 -- if Ptyp'First > Ptyp'Last then 0 else btyp'Width end if
1246
1247 -- where btyp is the base type. This looks recursive but it isn't
1248 -- because the base type is always static, and hence the expression
1249 -- in the else is reduced to an integer literal.
1250
1251 -- For user-defined enumeration types, typ'Width expands into
1252
1253 -- Result_Type (Width_Enumeration_NN
1254 -- (typS,
1255 -- typI'Address,
1256 -- typ'Pos (typ'First),
1257 -- typ'Pos (Typ'Last)));
1258
1259 -- and typ'Wide_Width expands into:
1260
1261 -- Result_Type (Wide_Width_Enumeration_NN
1262 -- (typS,
1263 -- typI,
1264 -- typ'Pos (typ'First),
1265 -- typ'Pos (Typ'Last))
1266 -- Wide_Character_Encoding_Method);
1267
1268 -- and typ'Wide_Wide_Width expands into:
1269
1270 -- Result_Type (Wide_Wide_Width_Enumeration_NN
1271 -- (typS,
1272 -- typI,
1273 -- typ'Pos (typ'First),
1274 -- typ'Pos (Typ'Last))
1275 -- Wide_Character_Encoding_Method);
1276
1277 -- where typS and typI are the enumeration image strings and indexes
1278 -- table, as described in Build_Enumeration_Image_Tables. NN is 8/16/32
1279 -- for depending on the element type for typI.
1280
1281 -- Finally if Discard_Names is in effect for an enumeration type, then
1282 -- a special if expression is built that yields the space needed for the
1283 -- decimal representation of the largest pos value in the subtype. See
1284 -- code below for details.
1285
1286 procedure Expand_Width_Attribute (N : Node_Id; Attr : Atype := Normal) is
1287 Loc : constant Source_Ptr := Sloc (N);
1288 Typ : constant Entity_Id := Etype (N);
1289 Pref : constant Node_Id := Prefix (N);
1290 Ptyp : constant Entity_Id := Etype (Pref);
1291 Rtyp : constant Entity_Id := Root_Type (Ptyp);
1292 Arglist : List_Id;
1293 Ttyp : Entity_Id;
1294 XX : RE_Id;
1295 YY : Entity_Id;
1296
1297 begin
1298 -- Types derived from Standard.Boolean
1299
1300 if Rtyp = Standard_Boolean then
1301 XX := RE_Width_Boolean;
1302 YY := Rtyp;
1303
1304 -- Types derived from Standard.Character
1305
1306 elsif Rtyp = Standard_Character then
1307 case Attr is
1308 when Normal => XX := RE_Width_Character;
1309 when Wide => XX := RE_Wide_Width_Character;
1310 when Wide_Wide => XX := RE_Wide_Wide_Width_Character;
1311 end case;
1312
1313 YY := Rtyp;
1314
1315 -- Types derived from Standard.Wide_Character
1316
1317 elsif Rtyp = Standard_Wide_Character then
1318 case Attr is
1319 when Normal => XX := RE_Width_Wide_Character;
1320 when Wide => XX := RE_Wide_Width_Wide_Character;
1321 when Wide_Wide => XX := RE_Wide_Wide_Width_Wide_Character;
1322 end case;
1323
1324 YY := Rtyp;
1325
1326 -- Types derived from Standard.Wide_Wide_Character
1327
1328 elsif Rtyp = Standard_Wide_Wide_Character then
1329 case Attr is
1330 when Normal => XX := RE_Width_Wide_Wide_Character;
1331 when Wide => XX := RE_Wide_Width_Wide_Wide_Character;
1332 when Wide_Wide => XX := RE_Wide_Wide_Width_Wide_Wide_Char;
1333 end case;
1334
1335 YY := Rtyp;
1336
1337 -- Signed integer types
1338
1339 elsif Is_Signed_Integer_Type (Rtyp) then
1340 XX := RE_Width_Long_Long_Integer;
1341 YY := Standard_Long_Long_Integer;
1342
1343 -- Modular integer types
1344
1345 elsif Is_Modular_Integer_Type (Rtyp) then
1346 XX := RE_Width_Long_Long_Unsigned;
1347 YY := RTE (RE_Long_Long_Unsigned);
1348
1349 -- Real types
1350
1351 elsif Is_Real_Type (Rtyp) then
1352 Rewrite (N,
1353 Make_If_Expression (Loc,
1354 Expressions => New_List (
1355
1356 Make_Op_Gt (Loc,
1357 Left_Opnd =>
1358 Make_Attribute_Reference (Loc,
1359 Prefix => New_Occurrence_Of (Ptyp, Loc),
1360 Attribute_Name => Name_First),
1361
1362 Right_Opnd =>
1363 Make_Attribute_Reference (Loc,
1364 Prefix => New_Occurrence_Of (Ptyp, Loc),
1365 Attribute_Name => Name_Last)),
1366
1367 Make_Integer_Literal (Loc, 0),
1368
1369 Make_Attribute_Reference (Loc,
1370 Prefix => New_Occurrence_Of (Base_Type (Ptyp), Loc),
1371 Attribute_Name => Name_Width))));
1372
1373 Analyze_And_Resolve (N, Typ);
1374 return;
1375
1376 -- User-defined enumeration types
1377
1378 else
1379 pragma Assert (Is_Enumeration_Type (Rtyp));
1380
1381 -- Whenever pragma Discard_Names is in effect, the value we need
1382 -- is the value needed to accommodate the largest integer pos value
1383 -- in the range of the subtype + 1 for the space at the start. We
1384 -- build:
1385
1386 -- Tnn : constant Integer := Rtyp'Pos (Ptyp'Last)
1387
1388 -- and replace the expression by
1389
1390 -- (if Ptyp'Range_Length = 0 then 0
1391 -- else (if Tnn < 10 then 2
1392 -- else (if Tnn < 100 then 3
1393 -- ...
1394 -- else n)))...
1395
1396 -- where n is equal to Rtyp'Pos (Ptyp'Last) + 1
1397
1398 -- Note: The above processing is in accordance with the intent of
1399 -- the RM, which is that Width should be related to the impl-defined
1400 -- behavior of Image. It is not clear what this means if Image is
1401 -- not defined (as in the configurable run-time case for GNAT) and
1402 -- gives an error at compile time.
1403
1404 -- We choose in this case to just go ahead and implement Width the
1405 -- same way, returning what Image would have returned if it has been
1406 -- available in the configurable run-time library.
1407
1408 if Discard_Names (Rtyp) then
1409 declare
1410 Tnn : constant Entity_Id := Make_Temporary (Loc, 'T');
1411 Cexpr : Node_Id;
1412 P : Int;
1413 M : Int;
1414 K : Int;
1415
1416 begin
1417 Insert_Action (N,
1418 Make_Object_Declaration (Loc,
1419 Defining_Identifier => Tnn,
1420 Constant_Present => True,
1421 Object_Definition =>
1422 New_Occurrence_Of (Standard_Integer, Loc),
1423 Expression =>
1424 Make_Attribute_Reference (Loc,
1425 Prefix => New_Occurrence_Of (Rtyp, Loc),
1426 Attribute_Name => Name_Pos,
1427 Expressions => New_List (
1428 Convert_To (Rtyp,
1429 Make_Attribute_Reference (Loc,
1430 Prefix => New_Occurrence_Of (Ptyp, Loc),
1431 Attribute_Name => Name_Last))))));
1432
1433 -- OK, now we need to build the if expression. First get the
1434 -- value of M, the largest possible value needed.
1435
1436 P := UI_To_Int
1437 (Enumeration_Pos (Entity (Type_High_Bound (Rtyp))));
1438
1439 K := 1;
1440 M := 1;
1441 while M < P loop
1442 M := M * 10;
1443 K := K + 1;
1444 end loop;
1445
1446 -- Build inner else
1447
1448 Cexpr := Make_Integer_Literal (Loc, K);
1449
1450 -- Wrap in inner if's until counted down to 2
1451
1452 while K > 2 loop
1453 M := M / 10;
1454 K := K - 1;
1455
1456 Cexpr :=
1457 Make_If_Expression (Loc,
1458 Expressions => New_List (
1459 Make_Op_Lt (Loc,
1460 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
1461 Right_Opnd => Make_Integer_Literal (Loc, M)),
1462 Make_Integer_Literal (Loc, K),
1463 Cexpr));
1464 end loop;
1465
1466 -- Add initial comparison for null range and we are done, so
1467 -- rewrite the attribute occurrence with this expression.
1468
1469 Rewrite (N,
1470 Convert_To (Typ,
1471 Make_If_Expression (Loc,
1472 Expressions => New_List (
1473 Make_Op_Eq (Loc,
1474 Left_Opnd =>
1475 Make_Attribute_Reference (Loc,
1476 Prefix => New_Occurrence_Of (Ptyp, Loc),
1477 Attribute_Name => Name_Range_Length),
1478 Right_Opnd => Make_Integer_Literal (Loc, 0)),
1479 Make_Integer_Literal (Loc, 0),
1480 Cexpr))));
1481
1482 Analyze_And_Resolve (N, Typ);
1483 return;
1484 end;
1485 end if;
1486
1487 -- Normal case, not Discard_Names
1488
1489 Ttyp := Component_Type (Etype (Lit_Indexes (Rtyp)));
1490
1491 case Attr is
1492 when Normal =>
1493 if Ttyp = Standard_Integer_8 then
1494 XX := RE_Width_Enumeration_8;
1495 elsif Ttyp = Standard_Integer_16 then
1496 XX := RE_Width_Enumeration_16;
1497 else
1498 XX := RE_Width_Enumeration_32;
1499 end if;
1500
1501 when Wide =>
1502 if Ttyp = Standard_Integer_8 then
1503 XX := RE_Wide_Width_Enumeration_8;
1504 elsif Ttyp = Standard_Integer_16 then
1505 XX := RE_Wide_Width_Enumeration_16;
1506 else
1507 XX := RE_Wide_Width_Enumeration_32;
1508 end if;
1509
1510 when Wide_Wide =>
1511 if Ttyp = Standard_Integer_8 then
1512 XX := RE_Wide_Wide_Width_Enumeration_8;
1513 elsif Ttyp = Standard_Integer_16 then
1514 XX := RE_Wide_Wide_Width_Enumeration_16;
1515 else
1516 XX := RE_Wide_Wide_Width_Enumeration_32;
1517 end if;
1518 end case;
1519
1520 Arglist :=
1521 New_List (
1522 New_Occurrence_Of (Lit_Strings (Rtyp), Loc),
1523
1524 Make_Attribute_Reference (Loc,
1525 Prefix => New_Occurrence_Of (Lit_Indexes (Rtyp), Loc),
1526 Attribute_Name => Name_Address),
1527
1528 Make_Attribute_Reference (Loc,
1529 Prefix => New_Occurrence_Of (Ptyp, Loc),
1530 Attribute_Name => Name_Pos,
1531
1532 Expressions => New_List (
1533 Make_Attribute_Reference (Loc,
1534 Prefix => New_Occurrence_Of (Ptyp, Loc),
1535 Attribute_Name => Name_First))),
1536
1537 Make_Attribute_Reference (Loc,
1538 Prefix => New_Occurrence_Of (Ptyp, Loc),
1539 Attribute_Name => Name_Pos,
1540
1541 Expressions => New_List (
1542 Make_Attribute_Reference (Loc,
1543 Prefix => New_Occurrence_Of (Ptyp, Loc),
1544 Attribute_Name => Name_Last))));
1545
1546 Rewrite (N,
1547 Convert_To (Typ,
1548 Make_Function_Call (Loc,
1549 Name => New_Occurrence_Of (RTE (XX), Loc),
1550 Parameter_Associations => Arglist)));
1551
1552 Analyze_And_Resolve (N, Typ);
1553 return;
1554 end if;
1555
1556 -- If we fall through XX and YY are set
1557
1558 Arglist := New_List (
1559 Convert_To (YY,
1560 Make_Attribute_Reference (Loc,
1561 Prefix => New_Occurrence_Of (Ptyp, Loc),
1562 Attribute_Name => Name_First)),
1563
1564 Convert_To (YY,
1565 Make_Attribute_Reference (Loc,
1566 Prefix => New_Occurrence_Of (Ptyp, Loc),
1567 Attribute_Name => Name_Last)));
1568
1569 Rewrite (N,
1570 Convert_To (Typ,
1571 Make_Function_Call (Loc,
1572 Name => New_Occurrence_Of (RTE (XX), Loc),
1573 Parameter_Associations => Arglist)));
1574
1575 Analyze_And_Resolve (N, Typ);
1576 end Expand_Width_Attribute;
1577
1578 -----------------------
1579 -- Has_Decimal_Small --
1580 -----------------------
1581
1582 function Has_Decimal_Small (E : Entity_Id) return Boolean is
1583 begin
1584 return Is_Decimal_Fixed_Point_Type (E)
1585 or else
1586 (Is_Ordinary_Fixed_Point_Type (E)
1587 and then Ureal_10**Aft_Value (E) * Small_Value (E) = Ureal_1);
1588 end Has_Decimal_Small;
1589
1590 --------------------------
1591 -- Rewrite_Object_Image --
1592 --------------------------
1593
1594 procedure Rewrite_Object_Image
1595 (N : Node_Id;
1596 Pref : Entity_Id;
1597 Attr_Name : Name_Id;
1598 Str_Typ : Entity_Id)
1599 is
1600 begin
1601 Rewrite (N,
1602 Make_Attribute_Reference (Sloc (N),
1603 Prefix => New_Occurrence_Of (Etype (Pref), Sloc (N)),
1604 Attribute_Name => Attr_Name,
1605 Expressions => New_List (Relocate_Node (Pref))));
1606
1607 Analyze_And_Resolve (N, Str_Typ);
1608 end Rewrite_Object_Image;
1609 end Exp_Imgv;