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_Enums
: constant Str
:= "Short_Enums";
64 S_Short_Size
: constant Str
:= "Short_Size";
65 S_Strict_Alignment
: constant Str
:= "Strict_Alignment";
66 S_System_Allocator_Alignment
: constant Str
:= "System_Allocator_Alignment";
67 S_Wchar_T_Size
: constant Str
:= "Wchar_T_Size";
68 S_Words_BE
: constant Str
:= "Words_BE";
72 type AStr
is access all String;
74 DTN
: constant array (Nat
range <>) of AStr
:= (
75 S_Bits_BE
'Unrestricted_Access,
76 S_Bits_Per_Unit 'Unrestricted_Access
,
77 S_Bits_Per_Word
'Unrestricted_Access,
78 S_Bytes_BE 'Unrestricted_Access
,
79 S_Char_Size
'Unrestricted_Access,
80 S_Double_Float_Alignment 'Unrestricted_Access
,
81 S_Double_Scalar_Alignment
'Unrestricted_Access,
82 S_Double_Size 'Unrestricted_Access
,
83 S_Float_Size
'Unrestricted_Access,
84 S_Float_Words_BE 'Unrestricted_Access
,
85 S_Int_Size
'Unrestricted_Access,
86 S_Long_Double_Size 'Unrestricted_Access
,
87 S_Long_Long_Size
'Unrestricted_Access,
88 S_Long_Size 'Unrestricted_Access
,
89 S_Maximum_Alignment
'Unrestricted_Access,
90 S_Max_Unaligned_Field 'Unrestricted_Access
,
91 S_Pointer_Size
'Unrestricted_Access,
92 S_Short_Enums 'Unrestricted_Access
,
93 S_Short_Size
'Unrestricted_Access,
94 S_Strict_Alignment 'Unrestricted_Access
,
95 S_System_Allocator_Alignment
'Unrestricted_Access,
96 S_Wchar_T_Size 'Unrestricted_Access
,
97 S_Words_BE
'Unrestricted_Access);
99 -- Table of corresponding value pointers
101 DTV : constant array (Nat range <>) of System.Address := (
103 Bits_Per_Unit
'Address,
104 Bits_Per_Word 'Address
,
107 Double_Float_Alignment
'Address,
108 Double_Scalar_Alignment 'Address
,
109 Double_Size
'Address,
111 Float_Words_BE
'Address,
113 Long_Double_Size
'Address,
114 Long_Long_Size 'Address
,
116 Maximum_Alignment 'Address
,
117 Max_Unaligned_Field
'Address,
118 Pointer_Size 'Address
,
119 Short_Enums
'Address,
121 Strict_Alignment
'Address,
122 System_Allocator_Alignment 'Address
,
123 Wchar_T_Size
'Address,
126 DTR
: array (Nat
range DTV
'Range) of Boolean := (others => False);
127 -- Table of flags used to validate that all values are present in file
129 -----------------------
130 -- Local Subprograms --
131 -----------------------
133 procedure Fail
(E
: String);
134 pragma No_Return
(Fail
);
135 -- Terminate program with fatal error message passed as parameter
137 procedure Register_Float_Type
142 Float_Rep
: Float_Rep_Kind
;
144 Alignment
: Natural);
145 pragma Convention
(C
, Register_Float_Type
);
146 -- Call back to allow the back end to register available types. This call
147 -- back makes entries in the FPT_Mode_Table for any floating point types
148 -- reported by the back end. Name is the name of the type as a normal
149 -- format Null-terminated string. Digs is the number of digits, where 0
150 -- means it is not a fpt type (ignored during registration). Complex is
151 -- non-zero if the type has real and imaginary parts (also ignored during
152 -- registration). Count is the number of elements in a vector type (zero =
153 -- not a vector, registration ignores vectors). Float_Rep shows the kind of
154 -- floating-point type, and Size/Alignment are the size/alignment in bits.
156 -- So to summarize, the only types that are actually registered have Digs
157 -- non-zero, Complex zero (false), and Count zero (not a vector).
163 procedure Fail
(E
: String) is
164 E_Fatal
: constant := 4;
165 -- Code for fatal error
172 -------------------------
173 -- Register_Float_Type --
174 -------------------------
176 procedure Register_Float_Type
181 Float_Rep
: Float_Rep_Kind
;
185 T
: String (1 .. Name
'Length);
189 -- Dump information given by the back end for the type to register
197 Write_Str
("type " & T
(1 .. Last
) & " is ");
200 Write_Str
("array (1 .. ");
201 Write_Int
(Int
(Count
));
204 Write_Str
(", 1 .. 2");
210 Write_Str
("array (1 .. 2) of ");
214 Write_Str
("digits ");
215 Write_Int
(Int
(Digs
));
218 Write_Str
("pragma Float_Representation (");
237 Write_Int
(Int
(Digs
));
240 when AAMP
=> Write_Str
("AAMP");
243 Write_Line
(", " & T
(1 .. Last
) & ");");
246 Write_Str
("mod 2**");
247 Write_Int
(Int
(Size
/ Positive'Max (1, Count
)));
251 Write_Str
("for " & T
(1 .. Last
) & "'Size use ");
252 Write_Int
(Int
(Size
));
255 Write_Str
("for " & T
(1 .. Last
) & "'Alignment use ");
256 Write_Int
(Int
(Alignment
/ 8));
261 -- Start of processing for Register_Float_Type
266 for J
in T
'Range loop
267 T
(J
) := Name
(Name
'First + J
- 1);
269 if T
(J
) = ASCII
.NUL
then
275 -- Dump info if debug flag set
277 if Debug_Flag_Dot_B
then
281 -- Acquire entry if non-vector non-complex fpt type (digits non-zero)
283 if Digs
> 0 and then not Complex
and then Count
= 0 then
284 Num_FPT_Modes
:= Num_FPT_Modes
+ 1;
285 FPT_Mode_Table
(Num_FPT_Modes
) :=
286 (NAME
=> new String'(T (1 .. Last)),
288 FLOAT_REP => Float_Rep,
290 ALIGNMENT => Alignment);
292 end Register_Float_Type;
294 -----------------------------------
295 -- Write_Target_Dependent_Values --
296 -----------------------------------
298 -- We do this at the System.Os_Lib level, since we have to do the read at
299 -- that level anyway, so it is easier and more consistent to follow the
300 -- same path for the write.
302 procedure Write_Target_Dependent_Values is
303 Fdesc : File_Descriptor;
306 Buffer : String (1 .. 80);
308 -- Buffer used to build line one of file
310 type ANat is access all Natural;
311 -- Pointer to Nat or Pos value (it is harmless to treat Pos values and
312 -- Nat values as Natural via Unchecked_Conversion).
314 function To_ANat is new Unchecked_Conversion (Address, ANat);
316 procedure AddC (C : Character);
317 -- Add one character to buffer
319 procedure AddN (N : Natural);
320 -- Add representation of integer N to Buffer, updating Buflen. N
321 -- must be less than 1000, and output is 3 characters with leading
324 procedure Write_Line;
325 -- Output contents of Buffer (1 .. Buflen) followed by a New_Line,
326 -- and set Buflen back to zero, ready to write next line.
332 procedure AddC (C : Character) is
334 Buflen := Buflen + 1;
335 Buffer (Buflen) := C;
342 procedure AddN (N : Natural) is
349 AddC (Character'Val (48 + N / 100));
355 AddC (Character'Val (48 + N / 10 mod 10));
360 AddC (Character'Val (48 + N mod 10));
367 procedure Write_Line is
371 if Buflen /= Write (Fdesc, Buffer'Address, Buflen) then
372 Delete_File (Target_Dependent_Info_Write_Name'Address, OK);
373 Fail ("disk full writing file "
374 & Target_Dependent_Info_Write_Name.all);
380 -- Start of processing for Write_Target_Dependent_Values
384 Create_File (Target_Dependent_Info_Write_Name.all'Address, Text);
386 if Fdesc = Invalid_FD then
387 Fail ("cannot create file " & Target_Dependent_Info_Write_Name.all);
390 -- Loop through values
392 for J in DTN'Range loop
396 Buflen := DTN (J)'Length;
397 Buffer (1 .. Buflen) := DTN (J).all;
401 while Buflen < 26 loop
408 -- Output value and write line
410 AddN (To_ANat (DTV (J)).all);
414 -- Blank line to separate sections
418 -- Write lines for registered FPT types
420 for J in 1 .. Num_FPT_Modes loop
422 E : FPT_Mode_Entry renames FPT_Mode_Table (J);
424 Buflen := E.NAME'Last;
425 Buffer (1 .. Buflen) := E.NAME.all;
427 -- Pad out to line up values
429 while Buflen < 11 loop
464 Fail ("disk full writing file "
465 & Target_Dependent_Info_Write_Name.all);
467 end Write_Target_Dependent_Values;
469 -- Package Initialization, set target dependent values. This must be done
470 -- early on, before we start accessing various compiler packages, since
471 -- these values are used all over the place.
474 -- First step: see if the -gnateT switch is present. As we have noted,
475 -- this has to be done very early, so can not depend on the normal circuit
476 -- for reading switches and setting switches in Opt. The following code
477 -- will set Opt.Target_Dependent_Info_Read_Name if the switch -gnateT=name
478 -- is present in the options string.
481 type Arg_Array is array (Nat) of Big_String_Ptr;
482 type Arg_Array_Ptr is access Arg_Array;
483 -- Types to access compiler arguments
486 pragma Import (C, save_argc);
487 -- Saved value of argc (number of arguments), imported from misc.c
489 save_argv : Arg_Array_Ptr;
490 pragma Import (C, save_argv);
491 -- Saved value of argv (argument pointers), imported from misc.c
494 gnat_argv : Arg_Array_Ptr;
495 pragma Import (C, gnat_argc);
496 pragma Import (C, gnat_argv);
497 -- If save_argv is not set, default to gnat_argc/argv
500 argv : Arg_Array_Ptr;
502 function Len_Arg (Arg : Big_String_Ptr) return Nat;
503 -- Determine length of argument Arg (a nul terminated C string).
509 function Len_Arg (Arg : Big_String_Ptr) return Nat is
511 for J in 1 .. Nat'Last loop
512 if Arg (Natural (J)) = ASCII.NUL then
521 if save_argv /= null then
525 -- Case of a non gcc compiler, e.g. gnat2why or gnat2scil
530 -- Loop through arguments looking for -gnateT, also look for -gnatd.b
532 for Arg in 1 .. argc - 1 loop
534 Argv_Ptr : constant Big_String_Ptr := argv (Arg);
535 Argv_Len : constant Nat := Len_Arg (Argv_Ptr);
539 and then Argv_Ptr (1 .. 8) = "-gnateT="
541 Opt.Target_Dependent_Info_Read_Name :=
542 new String'(Argv_Ptr
(9 .. Natural (Argv_Len
)));
545 and then Argv_Ptr
(1 .. 8) = "-gnatd.b"
547 Debug_Flag_Dot_B
:= True;
553 -- If the switch is not set, we get all values from the back end
555 if Opt
.Target_Dependent_Info_Read_Name
= null then
557 -- Set values by direct calls to the back end
559 Bits_BE
:= Get_Bits_BE
;
560 Bits_Per_Unit
:= Get_Bits_Per_Unit
;
561 Bits_Per_Word
:= Get_Bits_Per_Word
;
562 Bytes_BE
:= Get_Bytes_BE
;
563 Char_Size
:= Get_Char_Size
;
564 Double_Float_Alignment
:= Get_Double_Float_Alignment
;
565 Double_Scalar_Alignment
:= Get_Double_Scalar_Alignment
;
566 Double_Size
:= Get_Double_Size
;
567 Float_Size
:= Get_Float_Size
;
568 Float_Words_BE
:= Get_Float_Words_BE
;
569 Int_Size
:= Get_Int_Size
;
570 Long_Double_Size
:= Get_Long_Double_Size
;
571 Long_Long_Size
:= Get_Long_Long_Size
;
572 Long_Size
:= Get_Long_Size
;
573 Maximum_Alignment
:= Get_Maximum_Alignment
;
574 Max_Unaligned_Field
:= Get_Max_Unaligned_Field
;
575 Pointer_Size
:= Get_Pointer_Size
;
576 Short_Enums
:= Get_Short_Enums
;
577 Short_Size
:= Get_Short_Size
;
578 Strict_Alignment
:= Get_Strict_Alignment
;
579 System_Allocator_Alignment
:= Get_System_Allocator_Alignment
;
580 Wchar_T_Size
:= Get_Wchar_T_Size
;
581 Words_BE
:= Get_Words_BE
;
583 -- Register floating-point types from the back end
585 Register_Back_End_Types
(Register_Float_Type
'Access);
587 -- Case of reading the target dependent values from file
589 -- This is bit more complex than might be expected, because it has to be
590 -- done very early. All kinds of packages depend on these values, and we
591 -- can't wait till the normal processing of reading command line switches
592 -- etc to read the file. We do this at the System.OS_Lib level since it is
593 -- too early to be using Osint directly.
596 Read_Target_Dependent_Values
: declare
597 File_Desc
: File_Descriptor
;
600 type ANat
is access all Natural;
601 -- Pointer to Nat or Pos value (it is harmless to treat Pos values
602 -- as Nat via Unchecked_Conversion).
604 function To_ANat
is new Unchecked_Conversion
(Address
, ANat
);
608 Buffer
: String (1 .. 2000);
610 -- File information and length (2000 easily enough)
612 Nam_Buf
: String (1 .. 40);
615 procedure Check_Spaces
;
616 -- Checks that we have one or more spaces and skips them
618 procedure FailN
(S
: String);
619 -- Calls Fail adding " name in file xxx", where name is the currently
620 -- gathered name in Nam_Buf, surrounded by quotes, and xxx is the
624 -- Scan out name, leaving it in Nam_Buf with Nam_Len set. Calls
625 -- Skip_Spaces to skip any following spaces. Note that the name is
626 -- terminated by a sequence of at least two spaces.
628 function Get_Nat
return Natural;
629 -- N on entry points to decimal integer, scan out decimal integer
630 -- and return it, leaving N pointing to following space or LF.
632 procedure Skip_Spaces
;
639 procedure Check_Spaces
is
641 if N
> Buflen
or else Buffer
(N
) /= ' ' then
642 FailN
("missing space for");
653 procedure FailN
(S
: String) is
655 Fail
(S
& " """ & Nam_Buf
(1 .. Nam_Len
) & """ in file "
656 & Target_Dependent_Info_Read_Name
.all);
663 procedure Get_Name
is
667 -- Scan out name and put it in Nam_Buf
670 if N
> Buflen
or else Buffer
(N
) = ASCII
.LF
then
671 FailN
("incorrectly formatted line for");
674 -- Name is terminated by two blanks
676 exit when N
< Buflen
and then Buffer
(N
.. N
+ 1) = " ";
678 Nam_Len
:= Nam_Len
+ 1;
680 if Nam_Len
> Nam_Buf
'Last then
681 Fail
("name too long");
684 Nam_Buf
(Nam_Len
) := Buffer
(N
);
695 function Get_Nat
return Natural is
696 Result
: Natural := 0;
701 or else Buffer
(N
) not in '0' .. '9'
704 FailN
("bad value for");
707 Result
:= Result
* 10 + (Character'Pos (Buffer
(N
)) - 48);
710 exit when N
<= Buflen
711 and then (Buffer
(N
) = ASCII
.LF
or else Buffer
(N
) = ' ');
721 procedure Skip_Spaces
is
723 while N
<= Buflen
and Buffer
(N
) = ' ' loop
728 -- Start of processing for Read_Target_Dependent_Values
731 File_Desc
:= Open_Read
(Target_Dependent_Info_Read_Name
.all, Text
);
733 if File_Desc
= Invalid_FD
then
734 Fail
("cannot read file " & Target_Dependent_Info_Read_Name
.all);
737 Buflen
:= Read
(File_Desc
, Buffer
'Address, Buffer
'Length);
739 if Buflen
= Buffer
'Length then
740 Fail
("file is too long: " & Target_Dependent_Info_Read_Name
.all);
743 -- Scan through file for properly formatted entries in first section
746 while N
<= Buflen
and then Buffer
(N
) /= ASCII
.LF
loop
749 -- Validate name and get corresponding value pointer
753 for J
in DTN
'Range loop
754 if DTN
(J
).all = Nam_Buf
(1 .. Nam_Len
) then
755 VP
:= To_ANat
(DTV
(J
));
762 FailN
("unrecognized name");
769 if N
> Buflen
or else Buffer
(N
) /= ASCII
.LF
then
770 FailN
("misformatted line for");
773 N
:= N
+ 1; -- skip LF
776 -- Fall through this loop when all lines in first section read.
777 -- Check that values have been supplied for all entries.
779 for J
in DTR
'Range loop
781 Fail
("missing entry for " & DTN
(J
).all & " in file "
782 & Target_Dependent_Info_Read_Name
.all);
786 -- Now acquire FPT entries
789 Fail
("missing entries for FPT modes in file "
790 & Target_Dependent_Info_Read_Name
.all);
793 if Buffer
(N
) = ASCII
.LF
then
796 Fail
("missing blank line in file "
797 & Target_Dependent_Info_Read_Name
.all);
801 while N
<= Buflen
loop
804 Num_FPT_Modes
:= Num_FPT_Modes
+ 1;
807 E
: FPT_Mode_Entry
renames FPT_Mode_Table
(Num_FPT_Modes
);
810 E
.NAME
:= new String'(Nam_Buf (1 .. Nam_Len));
817 E.FLOAT_REP := IEEE_Binary;
819 E.FLOAT_REP := VAX_Native;
823 FailN ("bad float rep field for");
832 E.ALIGNMENT := Get_Nat;
834 if Buffer (N) /= ASCII.LF then
835 FailN ("junk at end of line for");
841 end Read_Target_Dependent_Values;