| ------------------------------------------------------------------------------ |
| -- -- |
| -- GNAAMP COMPILER COMPONENTS -- |
| -- -- |
| -- A D A B K E N D -- |
| -- -- |
| -- B o d y -- |
| -- -- |
| -- Copyright (C) 2001-2015, AdaCore -- |
| -- -- |
| -- GNAT is free software; you can redistribute it and/or modify it under -- |
| -- terms of the GNU General Public License as published by the Free Soft- -- |
| -- ware Foundation; either version 3, or (at your option) any later ver- -- |
| -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- |
| -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- |
| -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- |
| -- for more details. You should have received a copy of the GNU General -- |
| -- Public License distributed with GNAT; see file COPYING3. If not, go to -- |
| -- http://www.gnu.org/licenses for a complete copy of the license. -- |
| -- -- |
| ------------------------------------------------------------------------------ |
| |
| -- This is the version of the Back_End package for back ends written in Ada |
| |
| with Debug; |
| with Lib; |
| with Opt; use Opt; |
| with Output; use Output; |
| with Osint; use Osint; |
| with Osint.C; use Osint.C; |
| with Switch.C; use Switch.C; |
| with Types; use Types; |
| |
| with System.OS_Lib; use System.OS_Lib; |
| |
| package body Adabkend is |
| |
| use Switch; |
| |
| ------------------- |
| -- Call_Back_End -- |
| ------------------- |
| |
| procedure Call_Back_End is |
| begin |
| if (Opt.Verbose_Mode or Opt.Full_List) |
| and then not Debug.Debug_Flag_7 |
| then |
| Write_Eol; |
| Write_Str (Product_Name); |
| Write_Str (", Copyright "); |
| Write_Str (Copyright_Years); |
| Write_Str (" Ada Core Technologies, Inc."); |
| Write_Str (" (http://www.adacore.com)"); |
| Write_Eol; |
| Write_Eol; |
| end if; |
| |
| Driver (Lib.Cunit (Types.Main_Unit)); |
| end Call_Back_End; |
| |
| ------------------------ |
| -- Scan_Compiler_Args -- |
| ------------------------ |
| |
| procedure Scan_Compiler_Arguments is |
| Output_File_Name_Seen : Boolean := False; |
| -- Set to True after having scanned the file_name for switch |
| -- "-gnatO file_name" |
| |
| Argument_Count : constant Integer := Arg_Count - 1; |
| -- Number of arguments (excluding program name) |
| |
| Args : Argument_List (1 .. Argument_Count); |
| Next_Arg : Positive := 1; |
| |
| procedure Scan_Back_End_Switches (Switch_Chars : String); |
| -- Procedure to scan out switches stored in Switch_Chars. The first |
| -- character is known to be a valid switch character, and there are no |
| -- blanks or other switch terminator characters in the string, so the |
| -- entire string should consist of valid switch characters, except that |
| -- an optional terminating NUL character is allowed. |
| -- |
| -- If the switch is not valid, control will not return. The switches |
| -- must still be scanned to skip the "-o" arguments, or internal GCC |
| -- switches, which may be safely ignored by other back-ends. |
| |
| ---------------------------- |
| -- Scan_Back_End_Switches -- |
| ---------------------------- |
| |
| procedure Scan_Back_End_Switches (Switch_Chars : String) is |
| First : constant Positive := Switch_Chars'First + 1; |
| Last : constant Natural := Switch_Last (Switch_Chars); |
| |
| begin |
| -- Process any back end switches, returning if the switch does not |
| -- affect code generation or falling through if it does, so the |
| -- switch will get stored. |
| |
| if Is_Internal_GCC_Switch (Switch_Chars) then |
| Next_Arg := Next_Arg + 1; |
| return; -- ignore this switch |
| |
| -- Record that an object file name has been specified. The actual |
| -- file name argument is picked up and saved below by the main body |
| -- of Scan_Compiler_Arguments. |
| |
| elsif Switch_Chars (First .. Last) = "o" then |
| if First = Last then |
| if Opt.Output_File_Name_Present then |
| |
| -- Ignore extra -o when -gnatO has already been specified |
| |
| Next_Arg := Next_Arg + 1; |
| |
| else |
| Opt.Output_File_Name_Present := True; |
| end if; |
| |
| return; |
| else |
| Fail ("invalid switch: " & Switch_Chars); |
| end if; |
| |
| -- Set optimization indicators appropriately. In gcc-based GNAT this |
| -- is picked up from imported variables set by the gcc driver, but |
| -- for compilers with non-gcc back ends we do it here to allow use |
| -- of these switches by the front end. Allowed optimization switches |
| -- are -Os (optimize for size), -O[0123], and -O (same as -O1). |
| |
| elsif Switch_Chars (First) = 'O' then |
| if First = Last then |
| Optimization_Level := 1; |
| |
| elsif Last - First = 1 then |
| if Switch_Chars (Last) = 's' then |
| Optimize_Size := 1; |
| Optimization_Level := 2; -- Consistent with gcc setting |
| |
| elsif Switch_Chars (Last) in '0' .. '3' then |
| Optimization_Level := |
| Character'Pos (Switch_Chars (Last)) - Character'Pos ('0'); |
| |
| else |
| Fail ("invalid switch: " & Switch_Chars); |
| end if; |
| |
| else |
| Fail ("invalid switch: " & Switch_Chars); |
| end if; |
| |
| elsif Switch_Chars (First .. Last) = "quiet" then |
| return; -- ignore this switch |
| |
| elsif Switch_Chars (First .. Last) = "c" then |
| return; -- ignore this switch |
| |
| -- The -x switch and its language name argument will generally be |
| -- ignored by non-gcc back ends (e.g. the GNAAMP back end). In any |
| -- case, we save the switch and argument in the compilation switches. |
| |
| elsif Switch_Chars (First .. Last) = "x" then |
| Lib.Store_Compilation_Switch (Switch_Chars); |
| Next_Arg := Next_Arg + 1; |
| |
| declare |
| Argv : constant String := Args (Next_Arg).all; |
| |
| begin |
| if Is_Switch (Argv) then |
| Fail ("language name missing after -x"); |
| else |
| Lib.Store_Compilation_Switch (Argv); |
| end if; |
| end; |
| |
| return; |
| |
| -- Special check, the back end switch -fno-inline also sets the |
| -- front end flags to entirely inhibit all inlining. So we store it |
| -- and set the appropriate flags. |
| |
| elsif Switch_Chars (First .. Last) = "fno-inline" then |
| Lib.Store_Compilation_Switch (Switch_Chars); |
| Opt.Disable_FE_Inline := True; |
| Opt.Disable_FE_Inline_Always := True; |
| return; |
| |
| -- Similar processing for -fpreserve-control-flow |
| |
| elsif Switch_Chars (First .. Last) = "fpreserve-control-flow" then |
| Lib.Store_Compilation_Switch (Switch_Chars); |
| Opt.Suppress_Control_Flow_Optimizations := True; |
| return; |
| |
| -- Ignore all other back end switches |
| |
| elsif Is_Back_End_Switch (Switch_Chars) then |
| null; |
| |
| -- Give error for junk switch |
| |
| else |
| Fail ("invalid switch: " & Switch_Chars); |
| end if; |
| |
| -- Store any other GCC switches |
| |
| Lib.Store_Compilation_Switch (Switch_Chars); |
| end Scan_Back_End_Switches; |
| |
| -- Start of processing for Scan_Compiler_Args |
| |
| begin |
| -- Put all the arguments in argument list Args |
| |
| for Arg in 1 .. Argument_Count loop |
| declare |
| Argv : String (1 .. Len_Arg (Arg)); |
| begin |
| Fill_Arg (Argv'Address, Arg); |
| Args (Arg) := new String'(Argv); |
| end; |
| end loop; |
| |
| -- Loop through command line arguments, storing them for later access |
| |
| while Next_Arg <= Argument_Count loop |
| Look_At_Arg : declare |
| Argv : constant String := Args (Next_Arg).all; |
| |
| begin |
| if Argv'Length = 0 then |
| Fail ("Empty argument"); |
| end if; |
| |
| -- If the previous switch has set the Output_File_Name_Present |
| -- flag (that is we have seen a -gnatO), then the next argument |
| -- is the name of the output object file. |
| |
| if Opt.Output_File_Name_Present |
| and then not Output_File_Name_Seen |
| then |
| if Is_Switch (Argv) then |
| Fail ("Object file name missing after -gnatO"); |
| |
| -- In GNATprove_Mode, such an object file is never written, and |
| -- the call to Set_Output_Object_File_Name may fail (e.g. when |
| -- the object file name does not have the expected suffix). |
| -- So we skip that call when GNATprove_Mode is set. Same for |
| -- CodePeer_Mode. |
| |
| elsif GNATprove_Mode or CodePeer_Mode then |
| Output_File_Name_Seen := True; |
| |
| else |
| Set_Output_Object_File_Name (Argv); |
| Output_File_Name_Seen := True; |
| end if; |
| |
| -- If the previous switch has set the Search_Directory_Present |
| -- flag (that is if we have just seen -I), then the next |
| -- argument is a search directory path. |
| |
| elsif Search_Directory_Present then |
| if Is_Switch (Argv) then |
| Fail ("search directory missing after -I"); |
| else |
| Add_Src_Search_Dir (Argv); |
| |
| -- Add directory to lib search so that back-end can take as |
| -- input ALI files if needed. Otherwise this won't have any |
| -- impact on the compiler. |
| |
| Add_Lib_Search_Dir (Argv); |
| |
| Search_Directory_Present := False; |
| end if; |
| |
| -- If not a switch, must be a file name |
| |
| elsif not Is_Switch (Argv) then |
| Add_File (Argv); |
| |
| -- We must recognize -nostdinc to suppress visibility on the |
| -- standard GNAT RTL sources. |
| |
| elsif Argv (Argv'First + 1 .. Argv'Last) = "nostdinc" then |
| Opt.No_Stdinc := True; |
| |
| -- Front end switch |
| |
| elsif Is_Front_End_Switch (Argv) then |
| Scan_Front_End_Switches (Argv, Args, Next_Arg); |
| |
| -- All non-front-end switches are back-end switches |
| |
| else |
| Scan_Back_End_Switches (Argv); |
| end if; |
| end Look_At_Arg; |
| |
| Next_Arg := Next_Arg + 1; |
| end loop; |
| end Scan_Compiler_Arguments; |
| |
| end Adabkend; |