1 /* Subroutines for the gcc driver. 2 Copyright (C) 2009-2022 Free Software Foundation, Inc. 3 Contributed by Georg-Johann Lay <avr (at) 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* 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 // Return X_NODEVLIB when we are compiling for a core. As 109 // there are devices like AVR128DA32, a simple mmcu=avr* to 110 // discriminate between cores and devices ceased to work, 111 // hence use spec function no-devlib=avr_no_devlib from below. 112 // See also PR107201. 113 " %{mmcu=avr*:%:no-devlib(avr%*)} %{!mmcu=*:" X_NODEVLIB "}", 114 #else 115 " " X_NODEVLIB, 116 #endif 117 NULL); 118 } 119 120 121 /* Return X_NODEVLIB when ARGV[] contains a core like "avr5", 122 otherwise return "". */ 123 124 const char * 125 avr_no_devlib (int argc, const char **argv) 126 { 127 for (int i = 0; i < argc; ++i) 128 { 129 if (avr_get_parch (argv[i])) 130 return X_NODEVLIB; 131 } 132 133 return ""; 134 } 135 136 137 /* Re-build the -mdouble= and -mlong-double= options. This is needed 138 because these options are not independent of each other. */ 139 140 const char * 141 avr_double_lib (int argc, const char **argv) 142 { 143 #if defined (WITH_DOUBLE64) 144 int dbl = 64; 145 #elif defined (WITH_DOUBLE32) 146 int dbl = 32; 147 #else 148 #error "align this with config.gcc" 149 #endif 150 151 #if defined (WITH_LONG_DOUBLE64) 152 int ldb = 64; 153 #elif defined (WITH_LONG_DOUBLE32) 154 int ldb = 32; 155 #else 156 #error "align this with config.gcc" 157 #endif 158 159 for (int i = 0; i < argc; i++) 160 { 161 if (strcmp (argv[i], "mdouble=32") == 0) 162 { 163 dbl = 32; 164 #ifdef HAVE_LONG_DOUBLE_IS_DOUBLE 165 ldb = dbl; 166 #endif 167 } 168 else if (strcmp (argv[i], "mdouble=64") == 0) 169 { 170 ldb = dbl = 64; 171 } 172 else if (strcmp (argv[i], "mlong-double=32") == 0) 173 { 174 ldb = dbl = 32; 175 } 176 else if (strcmp (argv[i], "mlong-double=64") == 0) 177 { 178 ldb = 64; 179 #ifdef HAVE_LONG_DOUBLE_IS_DOUBLE 180 dbl = ldb; 181 #endif 182 } 183 } 184 185 return concat (" %<mdouble=* -mdouble=", dbl == 32 ? "32" : "64", 186 " %<mlong-double=* -mlong-double=", ldb == 32 ? "32" : "64", 187 NULL); 188 } 189