xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/loongarch/loongarch-driver.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Subroutines for the gcc driver.
2    Copyright (C) 2021-2022 Free Software Foundation, Inc.
3    Contributed by Loongson Ltd.
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 "tm.h"
27 #include "obstack.h"
28 #include "diagnostic-core.h"
29 
30 #include "loongarch-opts.h"
31 #include "loongarch-driver.h"
32 
33 static int
34   opt_arch_driver = M_OPTION_NOT_SEEN,
35   opt_tune_driver = M_OPTION_NOT_SEEN,
36   opt_fpu_driver = M_OPTION_NOT_SEEN,
37   opt_abi_base_driver = M_OPTION_NOT_SEEN,
38   opt_abi_ext_driver = M_OPTION_NOT_SEEN,
39   opt_cmodel_driver = M_OPTION_NOT_SEEN;
40 
41 int opt_switches = 0;
42 
43 /* This flag is set to 1 if we believe that the user might be avoiding
44    linking (implicitly) against something from the startfile search paths.  */
45 static int no_link = 0;
46 
47 #define LARCH_DRIVER_SET_M_FLAG(OPTS_ARRAY, N_OPTS, FLAG, STR)	\
48   for (int i = 0; i < (N_OPTS); i++)				\
49   {								\
50     if ((OPTS_ARRAY)[i] != 0)					\
51       if (strcmp ((STR), (OPTS_ARRAY)[i]) == 0)			\
52 	(FLAG) = i;						\
53   }
54 
55 /* Use the public obstack from the gcc driver (defined in gcc.c).
56    This is for allocating space for the returned string.  */
57 extern struct obstack opts_obstack;
58 
59 #define APPEND_LTR(S)				      \
60   obstack_grow (&opts_obstack, (const void*) (S),     \
61 		sizeof ((S)) / sizeof (char) -1)
62 
63 #define APPEND_VAL(S) \
64   obstack_grow (&opts_obstack, (const void*) (S), strlen ((S)))
65 
66 
67 const char*
driver_set_m_flag(int argc,const char ** argv)68 driver_set_m_flag (int argc, const char **argv)
69 {
70   int parm_off = 0;
71 
72   if (argc != 1)
73     return "%eset_m_flag requires exactly 1 argument.";
74 
75 #undef PARM
76 #define PARM (argv[0] + parm_off)
77 
78 /* Note: sizeof (OPTSTR_##NAME) equals the length of "<option>=".  */
79 #undef MATCH_OPT
80 #define MATCH_OPT(NAME) \
81   (strncmp (argv[0], OPTSTR_##NAME "=", \
82 	    (parm_off = sizeof (OPTSTR_##NAME))) == 0)
83 
84   if (strcmp (argv[0], "no_link") == 0)
85     {
86       no_link = 1;
87     }
88   else if (MATCH_OPT (ABI_BASE))
89     {
90       LARCH_DRIVER_SET_M_FLAG (
91 	loongarch_abi_base_strings, N_ABI_BASE_TYPES,
92 	opt_abi_base_driver, PARM)
93     }
94   else if (MATCH_OPT (ISA_EXT_FPU))
95     {
96       LARCH_DRIVER_SET_M_FLAG (loongarch_isa_ext_strings, N_ISA_EXT_FPU_TYPES,
97 			       opt_fpu_driver, PARM)
98     }
99   else if (MATCH_OPT (ARCH))
100     {
101       LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_ARCH_TYPES,
102 			       opt_arch_driver, PARM)
103     }
104   else if (MATCH_OPT (TUNE))
105     {
106       LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_TUNE_TYPES,
107 			       opt_tune_driver, PARM)
108     }
109   else if (MATCH_OPT (CMODEL))
110     {
111       LARCH_DRIVER_SET_M_FLAG (loongarch_cmodel_strings, N_CMODEL_TYPES,
112 			       opt_cmodel_driver, PARM)
113     }
114   else /* switches */
115     {
116       int switch_idx = M_OPTION_NOT_SEEN;
117 
118       LARCH_DRIVER_SET_M_FLAG (loongarch_switch_strings, N_SWITCH_TYPES,
119 			       switch_idx, argv[0])
120 
121       if (switch_idx != M_OPTION_NOT_SEEN)
122 	opt_switches |= loongarch_switch_mask[switch_idx];
123     }
124   return "";
125 }
126 
127 const char*
driver_get_normalized_m_opts(int argc,const char ** argv)128 driver_get_normalized_m_opts (int argc, const char **argv)
129 {
130   if (argc != 0)
131     {
132       (void) argv;  /* To make compiler shut up about unused argument.  */
133       return " %eget_normalized_m_opts requires no argument.\n";
134     }
135 
136   loongarch_config_target (& la_target,
137 			   opt_switches,
138 			   opt_arch_driver,
139 			   opt_tune_driver,
140 			   opt_fpu_driver,
141 			   opt_abi_base_driver,
142 			   opt_abi_ext_driver,
143 			   opt_cmodel_driver,
144 			   !no_link /* follow_multilib_list */);
145 
146   /* Output normalized option strings.  */
147   obstack_blank (&opts_obstack, 0);
148 
149 #undef APPEND_LTR
150 #define APPEND_LTR(S) \
151   obstack_grow (&opts_obstack, (const void*) (S), \
152 		sizeof ((S)) / sizeof (char) -1)
153 
154 #undef APPEND_VAL
155 #define APPEND_VAL(S) \
156   obstack_grow (&opts_obstack, (const void*) (S), strlen ((S)))
157 
158 #undef APPEND_OPT
159 #define APPEND_OPT(NAME) \
160    APPEND_LTR (" %<m" OPTSTR_##NAME "=* " \
161 	       " -m" OPTSTR_##NAME "=")
162 
163   for (int i = 0; i < N_SWITCH_TYPES; i++)
164     {
165       APPEND_LTR (" %<m");
166       APPEND_VAL (loongarch_switch_strings[i]);
167     }
168 
169   APPEND_OPT (ABI_BASE);
170   APPEND_VAL (loongarch_abi_base_strings[la_target.abi.base]);
171 
172   APPEND_OPT (ARCH);
173   APPEND_VAL (loongarch_cpu_strings[la_target.cpu_arch]);
174 
175   APPEND_OPT (ISA_EXT_FPU);
176   APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.fpu]);
177 
178   APPEND_OPT (CMODEL);
179   APPEND_VAL (loongarch_cmodel_strings[la_target.cmodel]);
180 
181   APPEND_OPT (TUNE);
182   APPEND_VAL (loongarch_cpu_strings[la_target.cpu_tune]);
183 
184   obstack_1grow (&opts_obstack, '\0');
185 
186   return XOBFINISH (&opts_obstack, const char *);
187 }
188