xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/avr/driver-avr.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* Subroutines for the gcc driver.
2    Copyright (C) 2009-2020 Free Software Foundation, Inc.
3    Contributed by Georg-Johann Lay <avr@gjlay.de>
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #define IN_TARGET_CODE 1
22 
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "diagnostic.h"
27 #include "tm.h"
28 
29 // Remove -nodevicelib and -nodevicespecs from the command line if not needed.
30 #define X_NODEVLIB "%<nodevicelib %<nodevicespecs"
31 
32 static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
33 
34 
35 /* Implement spec function `device-specs-file´.
36 
37    Validate mcu name given with -mmcu option. Compose
38    -specs=<specs-file-name>%s. If everything went well then argv[0] is the
39    inflated (absolute) first device-specs directory and argv[1] is a device
40    or core name as supplied by -mmcu=*. When building GCC the path might be
41    relative.  */
42 
43 const char*
avr_devicespecs_file(int argc,const char ** argv)44 avr_devicespecs_file (int argc, const char **argv)
45 {
46   const char *mmcu = NULL;
47 
48 #ifdef DEBUG_SPECS
49   if (verbose_flag)
50     fnotice (stderr, "Running spec function '%s' with %d args\n\n",
51              __FUNCTION__, argc);
52 #endif
53 
54   switch (argc)
55     {
56     case 0:
57       fatal_error (input_location,
58                    "bad usage of spec function %qs", "device-specs-file");
59       return X_NODEVLIB;
60 
61     case 1:
62       if (strcmp ("device-specs", argv[0]) == 0)
63         {
64           /* FIXME:  This means "device-specs%s" from avr.h:DRIVER_SELF_SPECS
65              has not been resolved to a path.  That case can occur when the
66              c++ testsuite is run from the build directory.  DejaGNU's
67              libgloss.exp:get_multilibs runs $compiler without -B, i.e.runs
68              xgcc without specifying a prefix.  Without any prefix, there is
69              no means to find out where the specs files might be located.
70              get_multilibs runs xgcc --print-multi-lib, hence we don't actually
71              need information form a specs file and may skip it here.  */
72           return X_NODEVLIB;
73         }
74 
75       mmcu = AVR_MMCU_DEFAULT;
76       break;
77 
78     default:
79       mmcu = argv[1];
80 
81       // Allow specifying the same MCU more than once.
82 
83       for (int i = 2; i < argc; i++)
84 	if (strcmp (mmcu, argv[i]) != 0)
85           {
86             error ("specified option %qs more than once", "-mmcu");
87             return X_NODEVLIB;
88           }
89 
90       break;
91     }
92 
93   // Filter out silly -mmcu= arguments like "foo bar".
94 
95   for (const char *s = mmcu; *s; s++)
96     if (!ISALNUM (*s)
97         && '-' != *s
98         && '_' != *s)
99       {
100         error ("strange device name %qs after %qs: bad character %qc",
101                mmcu, "-mmcu=", *s);
102         return X_NODEVLIB;
103       }
104 
105   return concat ("%{!nodevicespecs:-specs=device-specs", dir_separator_str,
106 				 "specs-", mmcu, "%s} %<nodevicespecs"
107 #if defined (WITH_AVRLIBC)
108                  " %{mmcu=avr*:" X_NODEVLIB "} %{!mmcu=*:" X_NODEVLIB "}",
109 #else
110                  " " X_NODEVLIB,
111 #endif
112                  NULL);
113 }
114 
115 
116 /* Re-build the -mdouble= and -mlong-double= options.  This is needed
117    because these options are not independent of each other.  */
118 
119 const char*
avr_double_lib(int argc,const char ** argv)120 avr_double_lib (int argc, const char **argv)
121 {
122 #if defined (WITH_DOUBLE64)
123   int dbl = 64;
124 #elif defined (WITH_DOUBLE32)
125   int dbl = 32;
126 #else
127 #error "align this with config.gcc"
128 #endif
129 
130 #if defined (WITH_LONG_DOUBLE64)
131   int ldb = 64;
132 #elif defined (WITH_LONG_DOUBLE32)
133   int ldb = 32;
134 #else
135 #error "align this with config.gcc"
136 #endif
137 
138   for (int i = 0; i < argc; i++)
139     {
140       if (strcmp (argv[i], "mdouble=32") == 0)
141         {
142           dbl = 32;
143 #ifdef HAVE_LONG_DOUBLE_IS_DOUBLE
144           ldb = dbl;
145 #endif
146         }
147       else if (strcmp (argv[i], "mdouble=64") == 0)
148         {
149           ldb = dbl = 64;
150         }
151       else if (strcmp (argv[i], "mlong-double=32") == 0)
152         {
153           ldb = dbl = 32;
154         }
155       else if (strcmp (argv[i], "mlong-double=64") == 0)
156         {
157           ldb = 64;
158 #ifdef HAVE_LONG_DOUBLE_IS_DOUBLE
159           dbl = ldb;
160 #endif
161         }
162     }
163 
164   return concat (" %<mdouble=* -mdouble=", dbl == 32 ? "32" : "64",
165                  " %<mlong-double=* -mlong-double=", ldb == 32 ? "32" : "64",
166                  NULL);
167 }
168