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