1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2013-2020, 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_Long_Size
: constant Str
:= "Long_Long_Long_Size";
59 S_Long_Long_Size
: constant Str
:= "Long_Long_Size";
60 S_Long_Size
: constant Str
:= "Long_Size";
61 S_Maximum_Alignment
: constant Str
:= "Maximum_Alignment";
62 S_Max_Unaligned_Field
: constant Str
:= "Max_Unaligned_Field";
63 S_Pointer_Size
: constant Str
:= "Pointer_Size";
64 S_Short_Enums
: constant Str
:= "Short_Enums";
65 S_Short_Size
: constant Str
:= "Short_Size";
66 S_Strict_Alignment
: constant Str
:= "Strict_Alignment";
67 S_System_Allocator_Alignment
: constant Str
:= "System_Allocator_Alignment";
68 S_Wchar_T_Size
: constant Str
:= "Wchar_T_Size";
69 S_Words_BE
: constant Str
:= "Words_BE";
73 type AStr
is access all String;
75 DTN
: constant array (Nat
range <>) of AStr
:= (
76 S_Bits_BE
'Unrestricted_Access,
77 S_Bits_Per_Unit 'Unrestricted_Access
,
78 S_Bits_Per_Word
'Unrestricted_Access,
79 S_Bytes_BE 'Unrestricted_Access
,
80 S_Char_Size
'Unrestricted_Access,
81 S_Double_Float_Alignment 'Unrestricted_Access
,
82 S_Double_Scalar_Alignment
'Unrestricted_Access,
83 S_Double_Size 'Unrestricted_Access
,
84 S_Float_Size
'Unrestricted_Access,
85 S_Float_Words_BE 'Unrestricted_Access
,
86 S_Int_Size
'Unrestricted_Access,
87 S_Long_Double_Size 'Unrestricted_Access
,
88 S_Long_Long_Long_Size
'Unrestricted_Access,
89 S_Long_Long_Size 'Unrestricted_Access
,
90 S_Long_Size
'Unrestricted_Access,
91 S_Maximum_Alignment 'Unrestricted_Access
,
92 S_Max_Unaligned_Field
'Unrestricted_Access,
93 S_Pointer_Size 'Unrestricted_Access
,
94 S_Short_Enums
'Unrestricted_Access,
95 S_Short_Size 'Unrestricted_Access
,
96 S_Strict_Alignment
'Unrestricted_Access,
97 S_System_Allocator_Alignment 'Unrestricted_Access
,
98 S_Wchar_T_Size
'Unrestricted_Access,
99 S_Words_BE 'Unrestricted_Access
);
101 -- Table of corresponding value pointers
103 DTV
: constant array (Nat
range <>) of System
.Address
:= (
105 Bits_Per_Unit 'Address
,
106 Bits_Per_Word
'Address,
109 Double_Float_Alignment 'Address
,
110 Double_Scalar_Alignment
'Address,
111 Double_Size 'Address
,
113 Float_Words_BE 'Address
,
115 Long_Double_Size 'Address
,
116 Long_Long_Long_Size
'Address,
117 Long_Long_Size 'Address
,
119 Maximum_Alignment 'Address
,
120 Max_Unaligned_Field
'Address,
121 Pointer_Size 'Address
,
122 Short_Enums
'Address,
124 Strict_Alignment
'Address,
125 System_Allocator_Alignment 'Address
,
126 Wchar_T_Size
'Address,
129 DTR
: array (Nat
range DTV
'Range) of Boolean := (others => False);
130 -- Table of flags used to validate that all values are present in file
132 -----------------------
133 -- Local Subprograms --
134 -----------------------
136 procedure Read_Target_Dependent_Values
(File_Name
: String);
137 -- Read target dependent values from File_Name, and set the target
138 -- dependent values (global variables) declared in this package.
140 procedure Fail
(E
: String);
141 pragma No_Return
(Fail
);
142 -- Terminate program with fatal error message passed as parameter
144 procedure Register_Float_Type
149 Float_Rep
: Float_Rep_Kind
;
150 Precision
: Positive;
152 Alignment
: Natural);
153 pragma Convention
(C
, Register_Float_Type
);
154 -- Call back to allow the back end to register available types. This call
155 -- back makes entries in the FPT_Mode_Table for any floating point types
156 -- reported by the back end. Name is the name of the type as a normal
157 -- format Null-terminated string. Digs is the number of digits, where 0
158 -- means it is not a fpt type (ignored during registration). Complex is
159 -- non-zero if the type has real and imaginary parts (also ignored during
160 -- registration). Count is the number of elements in a vector type (zero =
161 -- not a vector, registration ignores vectors). Float_Rep shows the kind of
162 -- floating-point type, and Precision, Size and Alignment are the precision
163 -- size and alignment in bits.
165 -- The only types that are actually registered have Digs non-zero, Complex
166 -- zero (false), and Count zero (not a vector). The Long_Double_Index
167 -- variable below is updated to indicate the index at which a "long double"
168 -- type can be found if it gets registered at all.
170 Long_Double_Index
: Integer := -1;
171 -- Once all the floating point types have been registered, the index in
172 -- FPT_Mode_Table at which "long double" can be found, if anywhere. A
173 -- negative value means that no "long double" has been registered. This
174 -- is useful to know whether we have a "long double" available at all and
175 -- get at it's characteristics without having to search the FPT_Mode_Table
176 -- when we need to decide which C type should be used as the basis for
177 -- Long_Long_Float in Ada.
179 function FPT_Mode_Index_For
(Name
: String) return Natural;
180 -- Return the index in FPT_Mode_Table that designates the entry
181 -- corresponding to the C type named Name. Raise Program_Error if
182 -- there is no such entry.
184 function FPT_Mode_Index_For
(T
: S_Float_Types
) return Natural;
185 -- Return the index in FPT_Mode_Table that designates the entry for
186 -- a back-end type suitable as a basis to construct the standard Ada
187 -- floating point type identified by T.
193 function C_Type_For
(T
: S_Float_Types
) return String is
195 -- ??? For now, we don't have a good way to tell the widest float
196 -- type with hardware support. Basically, GCC knows the size of that
197 -- type, but on x86-64 there often are two or three 128-bit types,
198 -- one double extended that has 18 decimal digits, a 128-bit quad
199 -- precision type with 33 digits and possibly a 128-bit decimal float
200 -- type with 34 digits. As a workaround, we define Long_Long_Float as
201 -- C's "long double" if that type exists and has at most 18 digits,
202 -- or otherwise the same as Long_Float.
204 Max_HW_Digs
: constant := 18;
205 -- Maximum hardware digits supported
217 when S_Long_Long_Float
=>
218 if Long_Double_Index
>= 0
219 and then FPT_Mode_Table
(Long_Double_Index
).DIGS
<= Max_HW_Digs
221 return "long double";
232 procedure Fail
(E
: String) is
233 E_Fatal
: constant := 4;
234 -- Code for fatal error
242 ------------------------
243 -- FPT_Mode_Index_For --
244 ------------------------
246 function FPT_Mode_Index_For
(Name
: String) return Natural is
248 for J
in FPT_Mode_Table
'First .. Num_FPT_Modes
loop
249 if FPT_Mode_Table
(J
).NAME
.all = Name
then
255 end FPT_Mode_Index_For
;
257 function FPT_Mode_Index_For
(T
: S_Float_Types
) return Natural is
259 return FPT_Mode_Index_For
(C_Type_For
(T
));
260 end FPT_Mode_Index_For
;
262 -------------------------
263 -- Register_Float_Type --
264 -------------------------
266 procedure Register_Float_Type
271 Float_Rep
: Float_Rep_Kind
;
272 Precision
: Positive;
276 T
: String (1 .. Name
'Length);
280 -- Dump information given by the back end for the type to register
288 Write_Str
("type " & T
(1 .. Last
) & " is ");
291 Write_Str
("array (1 .. ");
292 Write_Int
(Int
(Count
));
295 Write_Str
(", 1 .. 2");
301 Write_Str
("array (1 .. 2) of ");
305 Write_Str
("digits ");
306 Write_Int
(Int
(Digs
));
309 Write_Str
("pragma Float_Representation (");
312 when AAMP
=> Write_Str
("AAMP");
313 when IEEE_Binary
=> Write_Str
("IEEE");
316 Write_Line
(", " & T
(1 .. Last
) & ");");
319 Write_Str
("mod 2**");
320 Write_Int
(Int
(Precision
/ Positive'Max (1, Count
)));
324 if Precision
= Size
then
325 Write_Str
("for " & T
(1 .. Last
) & "'Size use ");
326 Write_Int
(Int
(Size
));
330 Write_Str
("for " & T
(1 .. Last
) & "'Value_Size use ");
331 Write_Int
(Int
(Precision
));
334 Write_Str
("for " & T
(1 .. Last
) & "'Object_Size use ");
335 Write_Int
(Int
(Size
));
339 Write_Str
("for " & T
(1 .. Last
) & "'Alignment use ");
340 Write_Int
(Int
(Alignment
/ 8));
345 -- Start of processing for Register_Float_Type
350 for J
in T
'Range loop
351 T
(J
) := Name
(Name
'First + J
- 1);
353 if T
(J
) = ASCII
.NUL
then
359 -- Dump info if debug flag set
361 if Debug_Flag_Dot_B
then
365 -- Acquire entry if non-vector non-complex fpt type (digits non-zero)
367 if Digs
> 0 and then not Complex
and then Count
= 0 then
370 This_Name
: constant String := T
(1 .. Last
);
372 Num_FPT_Modes
:= Num_FPT_Modes
+ 1;
373 FPT_Mode_Table
(Num_FPT_Modes
) :=
374 (NAME
=> new String'(This_Name),
376 FLOAT_REP => Float_Rep,
377 PRECISION => Precision,
379 ALIGNMENT => Alignment);
381 if Long_Double_Index < 0 and then This_Name = "long double" then
382 Long_Double_Index := Num_FPT_Modes;
386 end Register_Float_Type;
388 -----------------------------------
389 -- Write_Target_Dependent_Values --
390 -----------------------------------
392 -- We do this at the System.Os_Lib level, since we have to do the read at
393 -- that level anyway, so it is easier and more consistent to follow the
394 -- same path for the write.
396 procedure Write_Target_Dependent_Values is
397 Fdesc : File_Descriptor;
400 Buffer : String (1 .. 80);
402 -- Buffer used to build line one of file
404 type ANat is access all Natural;
405 -- Pointer to Nat or Pos value (it is harmless to treat Pos values and
406 -- Nat values as Natural via Unchecked_Conversion).
408 function To_ANat is new Unchecked_Conversion (Address, ANat);
410 procedure AddC (C : Character);
411 -- Add one character to buffer
413 procedure AddN (N : Natural);
414 -- Add representation of integer N to Buffer, updating Buflen. N
415 -- must be less than 1000, and output is 3 characters with leading
418 procedure Write_Line;
419 -- Output contents of Buffer (1 .. Buflen) followed by a New_Line,
420 -- and set Buflen back to zero, ready to write next line.
426 procedure AddC (C : Character) is
428 Buflen := Buflen + 1;
429 Buffer (Buflen) := C;
436 procedure AddN (N : Natural) is
443 AddC (Character'Val (48 + N / 100));
449 AddC (Character'Val (48 + N / 10 mod 10));
454 AddC (Character'Val (48 + N mod 10));
461 procedure Write_Line is
465 if Buflen /= Write (Fdesc, Buffer'Address, Buflen) then
466 Delete_File (Target_Dependent_Info_Write_Name.all, OK);
467 Fail ("disk full writing file "
468 & Target_Dependent_Info_Write_Name.all);
474 -- Start of processing for Write_Target_Dependent_Values
478 Create_File (Target_Dependent_Info_Write_Name.all, Text);
480 if Fdesc = Invalid_FD then
481 Fail ("cannot create file " & Target_Dependent_Info_Write_Name.all);
484 -- Loop through values
486 for J in DTN'Range loop
490 Buflen := DTN (J)'Length;
491 Buffer (1 .. Buflen) := DTN (J).all;
495 while Buflen < 26 loop
502 -- Output value and write line
504 AddN (To_ANat (DTV (J)).all);
508 -- Blank line to separate sections
512 -- Write lines for registered FPT types
514 for J in 1 .. Num_FPT_Modes loop
516 E : FPT_Mode_Entry renames FPT_Mode_Table (J);
518 Buflen := E.NAME'Last;
519 Buffer (1 .. Buflen) := E.NAME.all;
521 -- Pad out to line up values
523 while Buflen < 11 loop
535 when AAMP => AddC ('A
');
536 when IEEE_Binary => AddC ('I
');
554 Fail ("disk full writing file "
555 & Target_Dependent_Info_Write_Name.all);
557 end Write_Target_Dependent_Values;
559 ----------------------------------
560 -- Read_Target_Dependent_Values --
561 ----------------------------------
563 procedure Read_Target_Dependent_Values (File_Name : String) is
564 File_Desc : File_Descriptor;
567 type ANat is access all Natural;
568 -- Pointer to Nat or Pos value (it is harmless to treat Pos values
569 -- as Nat via Unchecked_Conversion).
571 function To_ANat is new Unchecked_Conversion (Address, ANat);
575 Buffer : String (1 .. 2000);
577 -- File information and length (2000 easily enough)
579 Nam_Buf : String (1 .. 40);
582 procedure Check_Spaces;
583 -- Checks that we have one or more spaces and skips them
585 procedure FailN (S : String);
586 pragma No_Return (FailN);
587 -- Calls Fail adding " name in file xxx", where name is the currently
588 -- gathered name in Nam_Buf, surrounded by quotes, and xxx is the
592 -- Scan out name, leaving it in Nam_Buf with Nam_Len set. Calls
593 -- Skip_Spaces to skip any following spaces. Note that the name is
594 -- terminated by a sequence of at least two spaces.
596 function Get_Nat return Natural;
597 -- N on entry points to decimal integer, scan out decimal integer
598 -- and return it, leaving N pointing to following space or LF.
600 procedure Skip_Spaces;
607 procedure Check_Spaces is
609 if N > Buflen or else Buffer (N) /= ' ' then
610 FailN ("missing space for");
621 procedure FailN (S : String) is
623 Fail (S & " """ & Nam_Buf (1 .. Nam_Len) & """ in file "
631 procedure Get_Name is
635 -- Scan out name and put it in Nam_Buf
638 if N > Buflen or else Buffer (N) = ASCII.LF then
639 FailN ("incorrectly formatted line for");
642 -- Name is terminated by two blanks
644 exit when N < Buflen and then Buffer (N .. N + 1) = " ";
646 Nam_Len := Nam_Len + 1;
648 if Nam_Len > Nam_Buf'Last then
649 Fail ("name too long");
652 Nam_Buf (Nam_Len) := Buffer (N);
663 function Get_Nat return Natural is
664 Result : Natural := 0;
669 or else Buffer (N) not in '0' .. '9'
672 FailN ("bad value for");
675 Result := Result * 10 + (Character'Pos (Buffer (N)) - 48);
678 exit when N <= Buflen
679 and then (Buffer (N) = ASCII.LF or else Buffer (N) = ' ');
689 procedure Skip_Spaces is
691 while N <= Buflen and Buffer (N) = ' ' loop
696 -- Start of processing for Read_Target_Dependent_Values
699 File_Desc := Open_Read (File_Name, Text);
701 if File_Desc = Invalid_FD then
702 Fail ("cannot read file " & File_Name);
705 Buflen := Read (File_Desc, Buffer'Address, Buffer'Length);
709 if Buflen = Buffer'Length then
710 Fail ("file is too long: " & File_Name);
713 -- Scan through file for properly formatted entries in first section
716 while N <= Buflen and then Buffer (N) /= ASCII.LF loop
719 -- Validate name and get corresponding value pointer
723 for J in DTN'Range loop
724 if DTN (J).all = Nam_Buf (1 .. Nam_Len) then
725 VP := To_ANat (DTV (J));
732 FailN ("unrecognized name");
739 if N > Buflen or else Buffer (N) /= ASCII.LF then
740 FailN ("misformatted line for");
743 N := N + 1; -- skip LF
746 -- Fall through this loop when all lines in first section read.
747 -- Check that values have been supplied for all entries.
749 for J in DTR'Range loop
751 -- Make an exception for Long_Long_Long_Size???
753 if DTN (J) = S_Long_Long_Long_Size'Unrestricted_Access then
754 Long_Long_Long_Size := Long_Long_Size;
757 Fail ("missing entry for " & DTN (J).all & " in file "
763 -- Now acquire FPT entries
766 Fail ("missing entries for FPT modes in file " & File_Name);
769 if Buffer (N) = ASCII.LF then
772 Fail ("missing blank line in file " & File_Name);
776 while N <= Buflen loop
779 Num_FPT_Modes := Num_FPT_Modes + 1;
782 E : FPT_Mode_Entry renames FPT_Mode_Table (Num_FPT_Modes);
785 E.NAME := new String'(Nam_Buf
(1 .. Nam_Len
));
787 if Long_Double_Index
< 0 and then E
.NAME
.all = "long double" then
788 Long_Double_Index
:= Num_FPT_Modes
;
796 E
.FLOAT_REP
:= IEEE_Binary
;
802 FailN
("bad float rep field for");
808 E
.PRECISION
:= Get_Nat
;
811 E
.ALIGNMENT
:= Get_Nat
;
813 if Buffer
(N
) /= ASCII
.LF
then
814 FailN
("junk at end of line for");
817 -- ??? We do not read E.SIZE, see Write_Target_Dependent_Values
820 (E
.PRECISION
+ E
.ALIGNMENT
- 1) / E
.ALIGNMENT
* E
.ALIGNMENT
;
825 end Read_Target_Dependent_Values
;
827 -- Package Initialization, set target dependent values. This must be done
828 -- early on, before we start accessing various compiler packages, since
829 -- these values are used all over the place.
832 -- First step: see if the -gnateT switch is present. As we have noted,
833 -- this has to be done very early, so cannot depend on the normal circuit
834 -- for reading switches and setting switches in Opt. The following code
835 -- will set Opt.Target_Dependent_Info_Read_Name if the switch -gnateT=name
836 -- is present in the options string.
839 type Arg_Array
is array (Nat
) of Big_String_Ptr
;
840 type Arg_Array_Ptr
is access Arg_Array
;
841 -- Types to access compiler arguments
844 pragma Import
(C
, save_argc
);
845 -- Saved value of argc (number of arguments), imported from misc.c
847 save_argv
: Arg_Array_Ptr
;
848 pragma Import
(C
, save_argv
);
849 -- Saved value of argv (argument pointers), imported from misc.c
852 gnat_argv
: Arg_Array_Ptr
;
853 pragma Import
(C
, gnat_argc
);
854 pragma Import
(C
, gnat_argv
);
855 -- If save_argv is not set, default to gnat_argc/argv
858 argv
: Arg_Array_Ptr
;
860 function Len_Arg
(Arg
: Big_String_Ptr
) return Nat
;
861 -- Determine length of argument Arg (a nul terminated C string).
867 function Len_Arg
(Arg
: Big_String_Ptr
) return Nat
is
869 for J
in 1 .. Nat
'Last loop
870 if Arg
(Natural (J
)) = ASCII
.NUL
then
879 if save_argv
/= null then
883 -- Case of a non gcc compiler, e.g. gnat2why or gnat2scil
888 -- Loop through arguments looking for -gnateT, also look for -gnatd.b
890 for Arg
in 1 .. argc
- 1 loop
892 Argv_Ptr
: constant Big_String_Ptr
:= argv
(Arg
);
893 Argv_Len
: constant Nat
:= Len_Arg
(Argv_Ptr
);
897 and then Argv_Ptr
(1 .. 8) = "-gnateT="
899 Opt
.Target_Dependent_Info_Read_Name
:=
900 new String'(Argv_Ptr (9 .. Natural (Argv_Len)));
903 and then Argv_Ptr (1 .. 8) = "-gnatd.b"
905 Debug_Flag_Dot_B := True;
911 -- Case of reading the target dependent values from file
913 -- This is bit more complex than might be expected, because it has to be
914 -- done very early. All kinds of packages depend on these values, and we
915 -- can't wait till the normal processing of reading command line switches
916 -- etc to read the file. We do this at the System.OS_Lib level since it is
917 -- too early to be using Osint directly.
919 if Opt.Target_Dependent_Info_Read_Name /= null then
920 Read_Target_Dependent_Values (Target_Dependent_Info_Read_Name.all);
922 -- If the back-end comes with a target config file, then use it
926 Back_End_Config_File : constant String_Ptr :=
927 Get_Back_End_Config_File;
929 if Back_End_Config_File /= null then
931 (CodePeer, Intentional, "test always false",
932 "some variant body will return non null");
933 Read_Target_Dependent_Values (Back_End_Config_File.all);
935 -- Otherwise we get all values from the back end directly
938 Bits_BE := Get_Bits_BE;
939 Bits_Per_Unit := Get_Bits_Per_Unit;
940 Bits_Per_Word := Get_Bits_Per_Word;
941 Bytes_BE := Get_Bytes_BE;
942 Char_Size := Get_Char_Size;
943 Double_Float_Alignment := Get_Double_Float_Alignment;
944 Double_Scalar_Alignment := Get_Double_Scalar_Alignment;
945 Float_Words_BE := Get_Float_Words_BE;
946 Int_Size := Get_Int_Size;
947 Long_Long_Long_Size := Get_Long_Long_Long_Size;
948 Long_Long_Size := Get_Long_Long_Size;
949 Long_Size := Get_Long_Size;
950 Maximum_Alignment := Get_Maximum_Alignment;
951 Max_Unaligned_Field := Get_Max_Unaligned_Field;
952 Pointer_Size := Get_Pointer_Size;
953 Short_Enums := Get_Short_Enums;
954 Short_Size := Get_Short_Size;
955 Strict_Alignment := Get_Strict_Alignment;
956 System_Allocator_Alignment := Get_System_Allocator_Alignment;
957 Wchar_T_Size := Get_Wchar_T_Size;
958 Words_BE := Get_Words_BE;
960 -- Let the back-end register its floating point types and compute
961 -- the sizes of our standard types from there:
964 Register_Back_End_Types (Register_Float_Type'Access);
967 T : FPT_Mode_Entry renames
968 FPT_Mode_Table (FPT_Mode_Index_For (S_Float));
970 Float_Size := Pos (T.SIZE);
974 T : FPT_Mode_Entry renames
975 FPT_Mode_Table (FPT_Mode_Index_For (S_Long_Float));
977 Double_Size := Pos (T.SIZE);
981 T : FPT_Mode_Entry renames
982 FPT_Mode_Table (FPT_Mode_Index_For (S_Long_Long_Float));
984 Long_Double_Size := Pos (T.SIZE);