1------------------------------------------------------------------------------
2--                                                                          --
3--                        GNAAMP COMPILER COMPONENTS                        --
4--                                                                          --
5--                             A D A B K E N D                              --
6--                                                                          --
7--                                 B o d y                                  --
8--                                                                          --
9--                     Copyright (C) 2001-2013, AdaCore                     --
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------------------------------------------------------------------------------
22
23--  This is the version of the Back_End package for back ends written in Ada
24
25with Debug;
26with Lib;
27with Opt;      use Opt;
28with Output;   use Output;
29with Osint;    use Osint;
30with Osint.C;  use Osint.C;
31with Switch.C; use Switch.C;
32with Types;    use Types;
33
34with System.OS_Lib; use System.OS_Lib;
35
36package body Adabkend is
37
38   use Switch;
39
40   -------------------
41   -- Call_Back_End --
42   -------------------
43
44   procedure Call_Back_End is
45   begin
46      if (Opt.Verbose_Mode or Opt.Full_List)
47        and then not Debug.Debug_Flag_7
48      then
49         Write_Eol;
50         Write_Str (Product_Name);
51         Write_Str (", Copyright ");
52         Write_Str (Copyright_Years);
53         Write_Str (" Ada Core Technologies, Inc.");
54         Write_Str (" (http://www.adacore.com)");
55         Write_Eol;
56         Write_Eol;
57      end if;
58
59      Driver (Lib.Cunit (Types.Main_Unit));
60   end Call_Back_End;
61
62   ------------------------
63   -- Scan_Compiler_Args --
64   ------------------------
65
66   procedure Scan_Compiler_Arguments is
67      Output_File_Name_Seen : Boolean := False;
68      --  Set to True after having scanned the file_name for switch
69      --  "-gnatO file_name"
70
71      Argument_Count : constant Integer := Arg_Count - 1;
72      --  Number of arguments (excluding program name)
73
74      Args     : Argument_List (1 .. Argument_Count);
75      Next_Arg : Positive := 1;
76
77      procedure Scan_Back_End_Switches (Switch_Chars : String);
78      --  Procedure to scan out switches stored in Switch_Chars. The first
79      --  character is known to be a valid switch character, and there are no
80      --  blanks or other switch terminator characters in the string, so the
81      --  entire string should consist of valid switch characters, except that
82      --  an optional terminating NUL character is allowed.
83      --
84      --  If the switch is not valid, control will not return. The switches
85      --  must still be scanned to skip the "-o" arguments, or internal GCC
86      --  switches, which may be safely ignored by other back-ends.
87
88      ----------------------------
89      -- Scan_Back_End_Switches --
90      ----------------------------
91
92      procedure Scan_Back_End_Switches (Switch_Chars : String) is
93         First : constant Positive := Switch_Chars'First + 1;
94         Last  : constant Natural  := Switch_Last (Switch_Chars);
95
96      begin
97         --  Process any back end switches, returning if the switch does not
98         --  affect code generation or falling through if it does, so the
99         --  switch will get stored.
100
101         if Is_Internal_GCC_Switch (Switch_Chars) then
102            Next_Arg := Next_Arg + 1;
103            return; -- ignore this switch
104
105         --  Record that an object file name has been specified. The actual
106         --  file name argument is picked up and saved below by the main body
107         --  of Scan_Compiler_Arguments.
108
109         elsif Switch_Chars (First .. Last) = "o" then
110            if First = Last then
111               Opt.Output_File_Name_Present := True;
112               return;
113            else
114               Fail ("invalid switch: " & Switch_Chars);
115            end if;
116
117         --  Set optimization indicators appropriately. In gcc-based GNAT this
118         --  is picked up from imported variables set by the gcc driver, but
119         --  for compilers with non-gcc back ends we do it here to allow use
120         --  of these switches by the front end. Allowed optimization switches
121         --  are -Os (optimize for size), -O[0123], and -O (same as -O1).
122
123         elsif Switch_Chars (First) = 'O' then
124            if First = Last then
125               Optimization_Level := 1;
126
127            elsif Last - First = 1 then
128               if Switch_Chars (Last) = 's' then
129                  Optimize_Size := 1;
130                  Optimization_Level := 2;  -- Consistent with gcc setting
131
132               elsif Switch_Chars (Last) in '0' .. '3' then
133                  Optimization_Level :=
134                    Character'Pos (Switch_Chars (Last)) - Character'Pos ('0');
135
136               else
137                  Fail ("invalid switch: " & Switch_Chars);
138               end if;
139
140            else
141               Fail ("invalid switch: " & Switch_Chars);
142            end if;
143
144         elsif Switch_Chars (First .. Last) = "quiet" then
145            return; -- ignore this switch
146
147         elsif Switch_Chars (First .. Last) = "c" then
148            return; -- ignore this switch
149
150         --  The -x switch and its language name argument will generally be
151         --  ignored by non-gcc back ends (e.g. the GNAAMP back end). In any
152         --  case, we save the switch and argument in the compilation switches.
153
154         elsif Switch_Chars (First .. Last) = "x" then
155            Lib.Store_Compilation_Switch (Switch_Chars);
156            Next_Arg := Next_Arg + 1;
157
158            declare
159               Argv : constant String := Args (Next_Arg).all;
160
161            begin
162               if Is_Switch (Argv) then
163                  Fail ("language name missing after -x");
164               else
165                  Lib.Store_Compilation_Switch (Argv);
166               end if;
167            end;
168
169            return;
170
171         --  Special check, the back end switch -fno-inline also sets the
172         --  front end flag to entirely inhibit all inlining. So we store it
173         --  and set the appropriate flag.
174
175         elsif Switch_Chars (First .. Last) = "fno-inline" then
176            Lib.Store_Compilation_Switch (Switch_Chars);
177            Opt.Suppress_All_Inlining := True;
178            return;
179
180         --  Similar processing for -fpreserve-control-flow
181
182         elsif Switch_Chars (First .. Last) = "fpreserve-control-flow" then
183            Lib.Store_Compilation_Switch (Switch_Chars);
184            Opt.Suppress_Control_Flow_Optimizations := True;
185            return;
186
187         --  Ignore all other back end switches
188
189         elsif Is_Back_End_Switch (Switch_Chars) then
190            null;
191
192         --  Give error for junk switch
193
194         else
195            Fail ("invalid switch: " & Switch_Chars);
196         end if;
197
198         --  Store any other GCC switches
199
200         Lib.Store_Compilation_Switch (Switch_Chars);
201      end Scan_Back_End_Switches;
202
203   --  Start of processing for Scan_Compiler_Args
204
205   begin
206      --  Put all the arguments in argument list Args
207
208      for Arg in 1 .. Argument_Count loop
209         declare
210            Argv : String (1 .. Len_Arg (Arg));
211         begin
212            Fill_Arg (Argv'Address, Arg);
213            Args (Arg) := new String'(Argv);
214         end;
215      end loop;
216
217      --  Loop through command line arguments, storing them for later access
218
219      while Next_Arg <= Argument_Count loop
220         Look_At_Arg : declare
221            Argv : constant String := Args (Next_Arg).all;
222
223         begin
224            if Argv'Length = 0 then
225               Fail ("Empty argument");
226            end if;
227
228            --  If the previous switch has set the Output_File_Name_Present
229            --  flag (that is we have seen a -gnatO), then the next argument
230            --  is the name of the output object file.
231
232            if Opt.Output_File_Name_Present
233              and then not Output_File_Name_Seen
234            then
235               if Is_Switch (Argv) then
236                  Fail ("Object file name missing after -gnatO");
237
238               --  In GNATprove_Mode, such an object file is never written, and
239               --  the call to Set_Output_Object_File_Name may fail (e.g. when
240               --  the object file name does not have the expected suffix). So
241               --  we skip that call when GNATprove_Mode is set.
242
243               elsif GNATprove_Mode then
244                  Output_File_Name_Seen := True;
245
246               else
247                  Set_Output_Object_File_Name (Argv);
248                  Output_File_Name_Seen := True;
249               end if;
250
251               --  If the previous switch has set the Search_Directory_Present
252               --  flag (that is if we have just seen -I), then the next
253               --  argument is a search directory path.
254
255            elsif Search_Directory_Present then
256               if Is_Switch (Argv) then
257                  Fail ("search directory missing after -I");
258               else
259                  Add_Src_Search_Dir (Argv);
260
261                  --  Add directory to lib search so that back-end can take as
262                  --  input ALI files if needed. Otherwise this won't have any
263                  --  impact on the compiler.
264
265                  Add_Lib_Search_Dir (Argv);
266
267                  Search_Directory_Present := False;
268               end if;
269
270            --  If not a switch, must be a file name
271
272            elsif not Is_Switch (Argv) then
273               Add_File (Argv);
274
275            --  We must recognize -nostdinc to suppress visibility on the
276            --  standard GNAT RTL sources.
277
278            elsif Argv (Argv'First + 1 .. Argv'Last) = "nostdinc" then
279               Opt.No_Stdinc := True;
280
281            --  Front end switch
282
283            elsif Is_Front_End_Switch (Argv) then
284               Scan_Front_End_Switches (Argv, Args, Next_Arg);
285
286            --  All non-front-end switches are back-end switches
287
288            else
289               Scan_Back_End_Switches (Argv);
290            end if;
291         end Look_At_Arg;
292
293         Next_Arg := Next_Arg + 1;
294      end loop;
295   end Scan_Compiler_Arguments;
296
297end Adabkend;
298