1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2013, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Debug
; use Debug
;
27 with Get_Targ
; use Get_Targ
;
29 with Output
; use Output
;
31 with System
; use System
;
32 with System
.OS_Lib
; use System
.OS_Lib
;
34 with Unchecked_Conversion
;
36 package body Set_Targ
is
38 --------------------------------------------------------
39 -- Data Used to Read/Write Target Dependent Info File --
40 --------------------------------------------------------
42 -- Table of string names written to file
44 subtype Str
is String;
46 S_Bits_BE
: constant Str
:= "Bits_BE";
47 S_Bits_Per_Unit
: constant Str
:= "Bits_Per_Unit";
48 S_Bits_Per_Word
: constant Str
:= "Bits_Per_Word";
49 S_Bytes_BE
: constant Str
:= "Bytes_BE";
50 S_Char_Size
: constant Str
:= "Char_Size";
51 S_Double_Float_Alignment
: constant Str
:= "Double_Float_Alignment";
52 S_Double_Scalar_Alignment
: constant Str
:= "Double_Scalar_Alignment";
53 S_Double_Size
: constant Str
:= "Double_Size";
54 S_Float_Size
: constant Str
:= "Float_Size";
55 S_Float_Words_BE
: constant Str
:= "Float_Words_BE";
56 S_Int_Size
: constant Str
:= "Int_Size";
57 S_Long_Double_Size
: constant Str
:= "Long_Double_Size";
58 S_Long_Long_Size
: constant Str
:= "Long_Long_Size";
59 S_Long_Size
: constant Str
:= "Long_Size";
60 S_Maximum_Alignment
: constant Str
:= "Maximum_Alignment";
61 S_Max_Unaligned_Field
: constant Str
:= "Max_Unaligned_Field";
62 S_Pointer_Size
: constant Str
:= "Pointer_Size";
63 S_Short_Size
: constant Str
:= "Short_Size";
64 S_Strict_Alignment
: constant Str
:= "Strict_Alignment";
65 S_System_Allocator_Alignment
: constant Str
:= "System_Allocator_Alignment";
66 S_Wchar_T_Size
: constant Str
:= "Wchar_T_Size";
67 S_Words_BE
: constant Str
:= "Words_BE";
71 type AStr
is access all String;
73 DTN
: constant array (Nat
range <>) of AStr
:= (
74 S_Bits_BE
'Unrestricted_Access,
75 S_Bits_Per_Unit 'Unrestricted_Access
,
76 S_Bits_Per_Word
'Unrestricted_Access,
77 S_Bytes_BE 'Unrestricted_Access
,
78 S_Char_Size
'Unrestricted_Access,
79 S_Double_Float_Alignment 'Unrestricted_Access
,
80 S_Double_Scalar_Alignment
'Unrestricted_Access,
81 S_Double_Size 'Unrestricted_Access
,
82 S_Float_Size
'Unrestricted_Access,
83 S_Float_Words_BE 'Unrestricted_Access
,
84 S_Int_Size
'Unrestricted_Access,
85 S_Long_Double_Size 'Unrestricted_Access
,
86 S_Long_Long_Size
'Unrestricted_Access,
87 S_Long_Size 'Unrestricted_Access
,
88 S_Maximum_Alignment
'Unrestricted_Access,
89 S_Max_Unaligned_Field 'Unrestricted_Access
,
90 S_Pointer_Size
'Unrestricted_Access,
91 S_Short_Size 'Unrestricted_Access
,
92 S_Strict_Alignment
'Unrestricted_Access,
93 S_System_Allocator_Alignment 'Unrestricted_Access
,
94 S_Wchar_T_Size
'Unrestricted_Access,
95 S_Words_BE 'Unrestricted_Access
);
97 -- Table of corresponding value pointers
99 DTV
: constant array (Nat
range <>) of System
.Address
:= (
101 Bits_Per_Unit 'Address
,
102 Bits_Per_Word
'Address,
105 Double_Float_Alignment 'Address
,
106 Double_Scalar_Alignment
'Address,
107 Double_Size 'Address
,
109 Float_Words_BE 'Address
,
111 Long_Double_Size 'Address
,
112 Long_Long_Size
'Address,
114 Maximum_Alignment
'Address,
115 Max_Unaligned_Field 'Address
,
116 Pointer_Size
'Address,
118 Strict_Alignment
'Address,
119 System_Allocator_Alignment 'Address
,
120 Wchar_T_Size
'Address,
123 DTR
: array (Nat
range DTV
'Range) of Boolean := (others => False);
124 -- Table of flags used to validate that all values are present in file
126 -----------------------
127 -- Local Subprograms --
128 -----------------------
130 procedure Fail
(E
: String);
131 pragma No_Return
(Fail
);
132 -- Terminate program with fatal error message passed as parameter
134 procedure Register_Float_Type
139 Float_Rep
: Float_Rep_Kind
;
141 Alignment
: Natural);
142 pragma Convention
(C
, Register_Float_Type
);
143 -- Call back to allow the back end to register available types. This call
144 -- back makes entries in the FPT_Mode_Table for any floating point types
145 -- reported by the back end. Name is the name of the type as a normal
146 -- format Null-terminated string. Digs is the number of digits, where 0
147 -- means it is not a fpt type (ignored during registration). Complex is
148 -- non-zero if the type has real and imaginary parts (also ignored during
149 -- registration). Count is the number of elements in a vector type (zero =
150 -- not a vector, registration ignores vectors). Float_Rep shows the kind of
151 -- floating-point type, and Size/Alignment are the size/alignment in bits.
153 -- So to summarize, the only types that are actually registered have Digs
154 -- non-zero, Complex zero (false), and Count zero (not a vector).
160 procedure Fail
(E
: String) is
161 E_Fatal
: constant := 4;
162 -- Code for fatal error
169 -------------------------
170 -- Register_Float_Type --
171 -------------------------
173 procedure Register_Float_Type
178 Float_Rep
: Float_Rep_Kind
;
182 T
: String (1 .. Name
'Length);
186 -- Dump information given by the back end for the type to register
194 Write_Str
("type " & T
(1 .. Last
) & " is ");
197 Write_Str
("array (1 .. ");
198 Write_Int
(Int
(Count
));
201 Write_Str
(", 1 .. 2");
207 Write_Str
("array (1 .. 2) of ");
211 Write_Str
("digits ");
212 Write_Int
(Int
(Digs
));
215 Write_Str
("pragma Float_Representation (");
234 Write_Int
(Int
(Digs
));
237 when AAMP
=> Write_Str
("AAMP");
240 Write_Line
(", " & T
(1 .. Last
) & ");");
243 Write_Str
("mod 2**");
244 Write_Int
(Int
(Size
/ Positive'Max (1, Count
)));
248 Write_Str
("for " & T
(1 .. Last
) & "'Size use ");
249 Write_Int
(Int
(Size
));
252 Write_Str
("for " & T
(1 .. Last
) & "'Alignment use ");
253 Write_Int
(Int
(Alignment
/ 8));
258 -- Start of processing for Register_Float_Type
263 for J
in T
'Range loop
264 T
(J
) := Name
(Name
'First + J
- 1);
266 if T
(J
) = ASCII
.NUL
then
272 -- Dump info if debug flag set
274 if Debug_Flag_Dot_B
then
278 -- Acquire entry if non-vector non-complex fpt type (digits non-zero)
280 if Digs
> 0 and then not Complex
and then Count
= 0 then
281 Num_FPT_Modes
:= Num_FPT_Modes
+ 1;
282 FPT_Mode_Table
(Num_FPT_Modes
) :=
283 (NAME
=> new String'(T (1 .. Last)),
285 FLOAT_REP => Float_Rep,
287 ALIGNMENT => Alignment);
289 end Register_Float_Type;
291 -----------------------------------
292 -- Write_Target_Dependent_Values --
293 -----------------------------------
295 -- We do this at the System.Os_Lib level, since we have to do the read at
296 -- that level anyway, so it is easier and more consistent to follow the
297 -- same path for the write.
299 procedure Write_Target_Dependent_Values is
300 Fdesc : File_Descriptor;
303 Buffer : String (1 .. 80);
305 -- Buffer used to build line one of file
307 type ANat is access all Natural;
308 -- Pointer to Nat or Pos value (it is harmless to treat Pos values and
309 -- Nat values as Natural via Unchecked_Conversion).
311 function To_ANat is new Unchecked_Conversion (Address, ANat);
313 procedure AddC (C : Character);
314 -- Add one character to buffer
316 procedure AddN (N : Natural);
317 -- Add representation of integer N to Buffer, updating Buflen. N
318 -- must be less than 1000, and output is 3 characters with leading
321 procedure Write_Line;
322 -- Output contents of Buffer (1 .. Buflen) followed by a New_Line,
323 -- and set Buflen back to zero, ready to write next line.
329 procedure AddC (C : Character) is
331 Buflen := Buflen + 1;
332 Buffer (Buflen) := C;
339 procedure AddN (N : Natural) is
346 AddC (Character'Val (48 + N / 100));
352 AddC (Character'Val (48 + N / 10 mod 10));
357 AddC (Character'Val (48 + N mod 10));
364 procedure Write_Line is
368 if Buflen /= Write (Fdesc, Buffer'Address, Buflen) then
369 Delete_File (Target_Dependent_Info_Write_Name'Address, OK);
370 Fail ("disk full writing file "
371 & Target_Dependent_Info_Write_Name.all);
377 -- Start of processing for Write_Target_Dependent_Values
381 Create_File (Target_Dependent_Info_Write_Name.all'Address, Text);
383 if Fdesc = Invalid_FD then
384 Fail ("cannot create file " & Target_Dependent_Info_Write_Name.all);
387 -- Loop through values
389 for J in DTN'Range loop
393 Buflen := DTN (J)'Length;
394 Buffer (1 .. Buflen) := DTN (J).all;
398 while Buflen < 26 loop
405 -- Output value and write line
407 AddN (To_ANat (DTV (J)).all);
411 -- Blank line to separate sections
415 -- Write lines for registered FPT types
417 for J in 1 .. Num_FPT_Modes loop
419 E : FPT_Mode_Entry renames FPT_Mode_Table (J);
421 Buflen := E.NAME'Last;
422 Buffer (1 .. Buflen) := E.NAME.all;
424 -- Pad out to line up values
426 while Buflen < 11 loop
461 Fail ("disk full writing file "
462 & Target_Dependent_Info_Write_Name.all);
464 end Write_Target_Dependent_Values;
466 -- Package Initialization, set target dependent values. This must be done
467 -- early on, before we start accessing various compiler packages, since
468 -- these values are used all over the place.
471 -- First step: see if the -gnateT switch is present. As we have noted,
472 -- this has to be done very early, so can not depend on the normal circuit
473 -- for reading switches and setting switches in Opt. The following code
474 -- will set Opt.Target_Dependent_Info_Read_Name if the switch -gnateT=name
475 -- is present in the options string.
478 type Arg_Array is array (Nat) of Big_String_Ptr;
479 type Arg_Array_Ptr is access Arg_Array;
480 -- Types to access compiler arguments
483 pragma Import (C, save_argc);
484 -- Saved value of argc (number of arguments), imported from misc.c
486 save_argv : Arg_Array_Ptr;
487 pragma Import (C, save_argv);
488 -- Saved value of argv (argument pointers), imported from misc.c
491 gnat_argv : Arg_Array_Ptr;
492 pragma Import (C, gnat_argc);
493 pragma Import (C, gnat_argv);
494 -- If save_argv is not set, default to gnat_argc/argv
497 argv : Arg_Array_Ptr;
499 function Len_Arg (Arg : Big_String_Ptr) return Nat;
500 -- Determine length of argument Arg (a nul terminated C string).
506 function Len_Arg (Arg : Big_String_Ptr) return Nat is
508 for J in 1 .. Nat'Last loop
509 if Arg (Natural (J)) = ASCII.NUL then
518 if save_argv /= null then
522 -- Case of a non gcc compiler, e.g. gnat2why or gnat2scil
527 -- Loop through arguments looking for -gnateT, also look for -gnatd.b
529 for Arg in 1 .. argc - 1 loop
531 Argv_Ptr : constant Big_String_Ptr := argv (Arg);
532 Argv_Len : constant Nat := Len_Arg (Argv_Ptr);
536 and then Argv_Ptr (1 .. 8) = "-gnateT="
538 Opt.Target_Dependent_Info_Read_Name :=
539 new String'(Argv_Ptr
(9 .. Natural (Argv_Len
)));
542 and then Argv_Ptr
(1 .. 8) = "-gnatd.b"
544 Debug_Flag_Dot_B
:= True;
550 -- If the switch is not set, we get all values from the back end
552 if Opt
.Target_Dependent_Info_Read_Name
= null then
554 -- Set values by direct calls to the back end
556 Bits_BE
:= Get_Bits_BE
;
557 Bits_Per_Unit
:= Get_Bits_Per_Unit
;
558 Bits_Per_Word
:= Get_Bits_Per_Word
;
559 Bytes_BE
:= Get_Bytes_BE
;
560 Char_Size
:= Get_Char_Size
;
561 Double_Float_Alignment
:= Get_Double_Float_Alignment
;
562 Double_Scalar_Alignment
:= Get_Double_Scalar_Alignment
;
563 Double_Size
:= Get_Double_Size
;
564 Float_Size
:= Get_Float_Size
;
565 Float_Words_BE
:= Get_Float_Words_BE
;
566 Int_Size
:= Get_Int_Size
;
567 Long_Double_Size
:= Get_Long_Double_Size
;
568 Long_Long_Size
:= Get_Long_Long_Size
;
569 Long_Size
:= Get_Long_Size
;
570 Maximum_Alignment
:= Get_Maximum_Alignment
;
571 Max_Unaligned_Field
:= Get_Max_Unaligned_Field
;
572 Pointer_Size
:= Get_Pointer_Size
;
573 Short_Size
:= Get_Short_Size
;
574 Strict_Alignment
:= Get_Strict_Alignment
;
575 System_Allocator_Alignment
:= Get_System_Allocator_Alignment
;
576 Wchar_T_Size
:= Get_Wchar_T_Size
;
577 Words_BE
:= Get_Words_BE
;
579 -- Register floating-point types from the back end
581 Register_Back_End_Types
(Register_Float_Type
'Access);
583 -- Case of reading the target dependent values from file
585 -- This is bit more complex than might be expected, because it has to be
586 -- done very early. All kinds of packages depend on these values, and we
587 -- can't wait till the normal processing of reading command line switches
588 -- etc to read the file. We do this at the System.OS_Lib level since it is
589 -- too early to be using Osint directly.
592 Read_Target_Dependent_Values
: declare
593 File_Desc
: File_Descriptor
;
596 type ANat
is access all Natural;
597 -- Pointer to Nat or Pos value (it is harmless to treat Pos values
598 -- as Nat via Unchecked_Conversion).
600 function To_ANat
is new Unchecked_Conversion
(Address
, ANat
);
604 Buffer
: String (1 .. 2000);
606 -- File information and length (2000 easily enough!)
608 Nam_Buf
: String (1 .. 40);
611 procedure Check_Spaces
;
612 -- Checks that we have one or more spaces and skips them
614 procedure FailN
(S
: String);
615 -- Calls Fail adding " name in file xxx", where name is the currently
616 -- gathered name in Nam_Buf, surrounded by quotes, and xxx is the
620 -- Scan out name, leaving it in Nam_Buf with Nam_Len set. Calls
621 -- Skip_Spaces to skip any following spaces. Note that the name is
622 -- terminated by a sequence of at least two spaces.
624 function Get_Nat
return Natural;
625 -- N on entry points to decimal integer, scan out decimal integer
626 -- and return it, leaving N pointing to following space or LF.
628 procedure Skip_Spaces
;
635 procedure Check_Spaces
is
637 if N
> Buflen
or else Buffer
(N
) /= ' ' then
638 FailN
("missing space for");
649 procedure FailN
(S
: String) is
651 Fail
(S
& " """ & Nam_Buf
(1 .. Nam_Len
) & """ in file "
652 & Target_Dependent_Info_Read_Name
.all);
659 procedure Get_Name
is
663 -- Scan out name and put it in Nam_Buf
666 if N
> Buflen
or else Buffer
(N
) = ASCII
.LF
then
667 FailN
("incorrectly formatted line for");
670 -- Name is terminated by two blanks
672 exit when N
< Buflen
and then Buffer
(N
.. N
+ 1) = " ";
674 Nam_Len
:= Nam_Len
+ 1;
676 if Nam_Len
> Nam_Buf
'Last then
677 Fail
("name too long");
680 Nam_Buf
(Nam_Len
) := Buffer
(N
);
691 function Get_Nat
return Natural is
692 Result
: Natural := 0;
697 or else Buffer
(N
) not in '0' .. '9'
700 FailN
("bad value for");
703 Result
:= Result
* 10 + (Character'Pos (Buffer
(N
)) - 48);
706 exit when N
<= Buflen
707 and then (Buffer
(N
) = ASCII
.LF
or else Buffer
(N
) = ' ');
717 procedure Skip_Spaces
is
719 while N
<= Buflen
and Buffer
(N
) = ' ' loop
724 -- Start of processing for Read_Target_Dependent_Values
727 File_Desc
:= Open_Read
(Target_Dependent_Info_Read_Name
.all, Text
);
729 if File_Desc
= Invalid_FD
then
730 Fail
("cannot read file " & Target_Dependent_Info_Read_Name
.all);
733 Buflen
:= Read
(File_Desc
, Buffer
'Address, Buffer
'Length);
735 if Buflen
= Buffer
'Length then
736 Fail
("file is too long: " & Target_Dependent_Info_Read_Name
.all);
739 -- Scan through file for properly formatted entries in first section
742 while N
<= Buflen
and then Buffer
(N
) /= ASCII
.LF
loop
745 -- Validate name and get corresponding value pointer
749 for J
in DTN
'Range loop
750 if DTN
(J
).all = Nam_Buf
(1 .. Nam_Len
) then
751 VP
:= To_ANat
(DTV
(J
));
758 FailN
("unrecognized name");
765 if N
> Buflen
or else Buffer
(N
) /= ASCII
.LF
then
766 FailN
("misformatted line for");
769 N
:= N
+ 1; -- skip LF
772 -- Fall through this loop when all lines in first section read.
773 -- Check that values have been supplied for all entries.
775 for J
in DTR
'Range loop
777 Fail
("missing entry for " & DTN
(J
).all & " in file "
778 & Target_Dependent_Info_Read_Name
.all);
782 -- Now acquire FPT entries
785 Fail
("missing entries for FPT modes in file "
786 & Target_Dependent_Info_Read_Name
.all);
789 if Buffer
(N
) = ASCII
.LF
then
792 Fail
("missing blank line in file "
793 & Target_Dependent_Info_Read_Name
.all);
797 while N
<= Buflen
loop
800 Num_FPT_Modes
:= Num_FPT_Modes
+ 1;
803 E
: FPT_Mode_Entry
renames FPT_Mode_Table
(Num_FPT_Modes
);
806 E
.NAME
:= new String'(Nam_Buf (1 .. Nam_Len));
813 E.FLOAT_REP := IEEE_Binary;
815 E.FLOAT_REP := VAX_Native;
819 FailN ("bad float rep field for");
828 E.ALIGNMENT := Get_Nat;
830 if Buffer (N) /= ASCII.LF then
831 FailN ("junk at end of line for");
837 end Read_Target_Dependent_Values;