1 /* Subroutines for loongarch-specific option handling.
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 #include "loongarch-cpu.h"
30 #include "loongarch-opts.h"
31 #include "loongarch-str.h"
32
33 struct loongarch_target la_target;
34
35 /* ABI-related configuration. */
36 #define ABI_COUNT (sizeof(abi_priority_list)/sizeof(struct loongarch_abi))
37 static const struct loongarch_abi
38 abi_priority_list[] = {
39 {ABI_BASE_LP64D, ABI_EXT_BASE},
40 {ABI_BASE_LP64F, ABI_EXT_BASE},
41 {ABI_BASE_LP64S, ABI_EXT_BASE},
42 };
43
44 /* Initialize enabled_abi_types from TM_MULTILIB_LIST. */
45 #ifdef LA_DISABLE_MULTILIB
46 #define MULTILIB_LIST_LEN 1
47 #else
48 #define MULTILIB_LIST_LEN (sizeof (tm_multilib_list) / sizeof (int) / 2)
49 static const int tm_multilib_list[] = { TM_MULTILIB_LIST };
50 #endif
51 static int enabled_abi_types[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = { 0 };
52
53 #define isa_required(ABI) (abi_minimal_isa[(ABI).base][(ABI).ext])
54 extern "C" const struct loongarch_isa
55 abi_minimal_isa[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES];
56
57 static inline int
is_multilib_enabled(struct loongarch_abi abi)58 is_multilib_enabled (struct loongarch_abi abi)
59 {
60 return enabled_abi_types[abi.base][abi.ext];
61 }
62
63 static void
init_enabled_abi_types()64 init_enabled_abi_types ()
65 {
66 #ifdef LA_DISABLE_MULTILIB
67 enabled_abi_types[DEFAULT_ABI_BASE][DEFAULT_ABI_EXT] = 1;
68 #else
69 int abi_base, abi_ext;
70 for (unsigned int i = 0; i < MULTILIB_LIST_LEN; i++)
71 {
72 abi_base = tm_multilib_list[i << 1];
73 abi_ext = tm_multilib_list[(i << 1) + 1];
74 enabled_abi_types[abi_base][abi_ext] = 1;
75 }
76 #endif
77 }
78
79 /* Switch masks. */
80 #undef M
81 #define M(NAME) OPTION_MASK_##NAME
82 const int loongarch_switch_mask[N_SWITCH_TYPES] = {
83 /* SW_SOFT_FLOAT */ M(FORCE_SOFTF),
84 /* SW_SINGLE_FLOAT */ M(FORCE_F32),
85 /* SW_DOUBLE_FLOAT */ M(FORCE_F64),
86 };
87 #undef M
88
89 /* String processing. */
90 static struct obstack msg_obstack;
91 #define APPEND_STRING(STR) obstack_grow (&msg_obstack, STR, strlen(STR));
92 #define APPEND1(CH) obstack_1grow(&msg_obstack, CH);
93
94 static const char* abi_str (struct loongarch_abi abi);
95 static const char* isa_str (const struct loongarch_isa *isa, char separator);
96 static const char* arch_str (const struct loongarch_target *target);
97 static const char* multilib_enabled_abi_list ();
98
99 /* Misc */
100 static struct loongarch_abi isa_default_abi (const struct loongarch_isa *isa);
101 static int isa_base_compat_p (const struct loongarch_isa *set1,
102 const struct loongarch_isa *set2);
103 static int isa_fpu_compat_p (const struct loongarch_isa *set1,
104 const struct loongarch_isa *set2);
105 static int abi_compat_p (const struct loongarch_isa *isa,
106 struct loongarch_abi abi);
107 static int abi_default_cpu_arch (struct loongarch_abi abi);
108
109 /* Checking configure-time defaults. */
110 #ifndef DEFAULT_ABI_BASE
111 #error missing definition of DEFAULT_ABI_BASE in ${tm_defines}.
112 #endif
113
114 #ifndef DEFAULT_ABI_EXT
115 #error missing definition of DEFAULT_ABI_EXT in ${tm_defines}.
116 #endif
117
118 #ifndef DEFAULT_CPU_ARCH
119 #error missing definition of DEFAULT_CPU_ARCH in ${tm_defines}.
120 #endif
121
122 #ifndef DEFAULT_ISA_EXT_FPU
123 #error missing definition of DEFAULT_ISA_EXT_FPU in ${tm_defines}.
124 #endif
125
126 /* Handle combinations of -m machine option values
127 (see loongarch.opt and loongarch-opts.h). */
128 void
loongarch_config_target(struct loongarch_target * target,HOST_WIDE_INT opt_switches,int opt_arch,int opt_tune,int opt_fpu,int opt_abi_base,int opt_abi_ext,int opt_cmodel,int follow_multilib_list)129 loongarch_config_target (struct loongarch_target *target,
130 HOST_WIDE_INT opt_switches,
131 int opt_arch, int opt_tune, int opt_fpu,
132 int opt_abi_base, int opt_abi_ext,
133 int opt_cmodel, int follow_multilib_list)
134 {
135 struct loongarch_target t;
136
137 if (!target)
138 return;
139
140 /* Initialization */
141 init_enabled_abi_types ();
142 obstack_init (&msg_obstack);
143
144 struct {
145 int arch, tune, fpu, abi_base, abi_ext, cmodel;
146 } constrained = {
147 M_OPT_ABSENT(opt_arch) ? 0 : 1,
148 M_OPT_ABSENT(opt_tune) ? 0 : 1,
149 M_OPT_ABSENT(opt_fpu) ? 0 : 1,
150 M_OPT_ABSENT(opt_abi_base) ? 0 : 1,
151 M_OPT_ABSENT(opt_abi_ext) ? 0 : 1,
152 M_OPT_ABSENT(opt_cmodel) ? 0 : 1,
153 };
154
155 #define on(NAME) ((loongarch_switch_mask[(SW_##NAME)] & opt_switches) \
156 && (on_switch = (SW_##NAME), 1))
157 int on_switch;
158
159 /* 1. Target ABI */
160 t.abi.base = constrained.abi_base ? opt_abi_base : DEFAULT_ABI_BASE;
161
162 t.abi.ext = constrained.abi_ext ? opt_abi_ext : DEFAULT_ABI_EXT;
163
164 /* Extra switch handling. */
165 if (on (SOFT_FLOAT) || on (SINGLE_FLOAT) || on (DOUBLE_FLOAT))
166 {
167 switch (on_switch)
168 {
169 case SW_SOFT_FLOAT:
170 opt_fpu = ISA_EXT_NOFPU;
171 break;
172
173 case SW_SINGLE_FLOAT:
174 opt_fpu = ISA_EXT_FPU32;
175 break;
176
177 case SW_DOUBLE_FLOAT:
178 opt_fpu = ISA_EXT_FPU64;
179 break;
180
181 default:
182 gcc_unreachable();
183 }
184 constrained.fpu = 1;
185
186 /* The target ISA is not ready yet, but (isa_required (t.abi)
187 + forced fpu) is enough for computing the forced base ABI. */
188 struct loongarch_isa default_isa = isa_required (t.abi);
189 struct loongarch_isa force_isa = default_isa;
190 struct loongarch_abi force_abi = t.abi;
191 force_isa.fpu = opt_fpu;
192 force_abi.base = isa_default_abi (&force_isa).base;
193
194 if (constrained.abi_base && (t.abi.base != force_abi.base))
195 inform (UNKNOWN_LOCATION,
196 "%<-m%s%> overrides %<-m%s=%s%>, adjusting ABI to %qs",
197 loongarch_switch_strings[on_switch],
198 OPTSTR_ABI_BASE, loongarch_abi_base_strings[t.abi.base],
199 abi_str (force_abi));
200
201 t.abi.base = force_abi.base;
202 }
203
204 #ifdef LA_DISABLE_MULTILIB
205 if (follow_multilib_list)
206 if (t.abi.base != DEFAULT_ABI_BASE || t.abi.ext != DEFAULT_ABI_EXT)
207 {
208 static const struct loongarch_abi default_abi
209 = {DEFAULT_ABI_BASE, DEFAULT_ABI_EXT};
210
211 warning (0, "ABI changed (%qs to %qs) while multilib is disabled",
212 abi_str (default_abi), abi_str (t.abi));
213 }
214 #endif
215
216 /* 2. Target CPU */
217 t.cpu_arch = constrained.arch ? opt_arch : DEFAULT_CPU_ARCH;
218
219 t.cpu_tune = constrained.tune ? opt_tune
220 : (constrained.arch ? DEFAULT_CPU_ARCH : DEFAULT_CPU_TUNE);
221
222 #ifdef __loongarch__
223 /* For native compilers, gather local CPU information
224 and fill the "CPU_NATIVE" index of arrays defined in
225 loongarch-cpu.c. */
226
227 t.cpu_native = fill_native_cpu_config (t.cpu_arch == CPU_NATIVE,
228 t.cpu_tune == CPU_NATIVE);
229
230 #else
231 if (t.cpu_arch == CPU_NATIVE)
232 fatal_error (UNKNOWN_LOCATION,
233 "%qs does not work on a cross compiler",
234 "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
235
236 else if (t.cpu_tune == CPU_NATIVE)
237 fatal_error (UNKNOWN_LOCATION,
238 "%qs does not work on a cross compiler",
239 "-m" OPTSTR_TUNE "=" STR_CPU_NATIVE);
240 #endif
241
242 /* 3. Target ISA */
243 config_target_isa:
244
245 /* Get default ISA from "-march" or its default value. */
246 t.isa = loongarch_cpu_default_isa[LARCH_ACTUAL_ARCH];
247
248 /* Apply incremental changes. */
249 /* "-march=native" overrides the default FPU type. */
250 t.isa.fpu = constrained.fpu ? opt_fpu :
251 ((t.cpu_arch == CPU_NATIVE && constrained.arch) ?
252 t.isa.fpu : DEFAULT_ISA_EXT_FPU);
253
254
255 /* 4. ABI-ISA compatibility */
256 /* Note:
257 - There IS a unique default -march value for each ABI type
258 (config.gcc: triplet -> abi -> default arch).
259
260 - If the base ABI is incompatible with the default arch,
261 try using the default -march it implies (and mark it
262 as "constrained" this time), then re-apply step 3. */
263
264 struct loongarch_abi abi_tmp;
265 const struct loongarch_isa* isa_min;
266
267 abi_tmp = t.abi;
268 isa_min = &isa_required (abi_tmp);
269
270 if (isa_base_compat_p (&t.isa, isa_min)); /* OK. */
271 else if (!constrained.arch)
272 {
273 /* Base architecture can only be implied by -march,
274 so we adjust that first if it is not constrained. */
275 int fallback_arch = abi_default_cpu_arch (t.abi);
276
277 if (t.cpu_arch == CPU_NATIVE)
278 warning (0, "your native CPU architecture (%qs) "
279 "does not support %qs ABI, falling back to %<-m%s=%s%>",
280 arch_str (&t), abi_str (t.abi), OPTSTR_ARCH,
281 loongarch_cpu_strings[fallback_arch]);
282 else
283 warning (0, "default CPU architecture (%qs) "
284 "does not support %qs ABI, falling back to %<-m%s=%s%>",
285 arch_str (&t), abi_str (t.abi), OPTSTR_ARCH,
286 loongarch_cpu_strings[fallback_arch]);
287
288 t.cpu_arch = fallback_arch;
289 constrained.arch = 1;
290 goto config_target_isa;
291 }
292 else if (!constrained.abi_base)
293 {
294 /* If -march is given while -mabi is not,
295 try selecting another base ABI type. */
296 abi_tmp.base = isa_default_abi (&t.isa).base;
297 }
298 else
299 goto fatal;
300
301 if (isa_fpu_compat_p (&t.isa, isa_min)); /* OK. */
302 else if (!constrained.fpu)
303 t.isa.fpu = isa_min->fpu;
304 else if (!constrained.abi_base)
305 /* If -march is compatible with the default ABI
306 while -mfpu is not. */
307 abi_tmp.base = isa_default_abi (&t.isa).base;
308 else
309 goto fatal;
310
311 if (0)
312 fatal:
313 fatal_error (UNKNOWN_LOCATION,
314 "unable to implement ABI %qs with instruction set %qs",
315 abi_str (t.abi), isa_str (&t.isa, '/'));
316
317
318 /* Using the fallback ABI. */
319 if (abi_tmp.base != t.abi.base || abi_tmp.ext != t.abi.ext)
320 {
321 /* This flag is only set in the GCC driver. */
322 if (follow_multilib_list)
323 {
324
325 /* Continue falling back until we find a feasible ABI type
326 enabled by TM_MULTILIB_LIST. */
327 if (!is_multilib_enabled (abi_tmp))
328 {
329 for (unsigned int i = 0; i < ABI_COUNT; i++)
330 {
331 if (is_multilib_enabled (abi_priority_list[i])
332 && abi_compat_p (&t.isa, abi_priority_list[i]))
333 {
334 abi_tmp = abi_priority_list[i];
335
336 warning (0, "ABI %qs cannot be implemented due to "
337 "limited instruction set %qs, "
338 "falling back to %qs", abi_str (t.abi),
339 isa_str (&t.isa, '/'), abi_str (abi_tmp));
340
341 goto fallback;
342 }
343 }
344
345 /* Otherwise, keep using abi_tmp with a warning. */
346 #ifdef LA_DISABLE_MULTILIB
347 warning (0, "instruction set %qs cannot implement "
348 "default ABI %qs, falling back to %qs",
349 isa_str (&t.isa, '/'), abi_str (t.abi),
350 abi_str (abi_tmp));
351 #else
352 warning (0, "no multilib-enabled ABI (%qs) can be implemented "
353 "with instruction set %qs, falling back to %qs",
354 multilib_enabled_abi_list (),
355 isa_str (&t.isa, '/'), abi_str (abi_tmp));
356 #endif
357 }
358 }
359
360 fallback:
361 t.abi = abi_tmp;
362 }
363 else if (follow_multilib_list)
364 {
365 if (!is_multilib_enabled (t.abi))
366 {
367 inform (UNKNOWN_LOCATION,
368 "ABI %qs is not enabled at configure-time, "
369 "the linker might report an error", abi_str (t.abi));
370
371 inform (UNKNOWN_LOCATION, "ABI with startfiles: %s",
372 multilib_enabled_abi_list ());
373 }
374 }
375
376
377 /* 5. Target code model */
378 t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL;
379
380 /* Cleanup and return. */
381 obstack_free (&msg_obstack, NULL);
382 *target = t;
383 }
384
385 /* Returns the default ABI for the given instruction set. */
386 static inline struct loongarch_abi
isa_default_abi(const struct loongarch_isa * isa)387 isa_default_abi (const struct loongarch_isa *isa)
388 {
389 struct loongarch_abi abi;
390
391 switch (isa->fpu)
392 {
393 case ISA_EXT_FPU64:
394 if (isa->base == ISA_BASE_LA64V100)
395 abi.base = ABI_BASE_LP64D;
396 break;
397
398 case ISA_EXT_FPU32:
399 if (isa->base == ISA_BASE_LA64V100)
400 abi.base = ABI_BASE_LP64F;
401 break;
402
403 case ISA_EXT_NOFPU:
404 if (isa->base == ISA_BASE_LA64V100)
405 abi.base = ABI_BASE_LP64S;
406 break;
407
408 default:
409 gcc_unreachable ();
410 }
411
412 abi.ext = ABI_EXT_BASE;
413 return abi;
414 }
415
416 /* Check if set2 is a subset of set1. */
417 static inline int
isa_base_compat_p(const struct loongarch_isa * set1,const struct loongarch_isa * set2)418 isa_base_compat_p (const struct loongarch_isa *set1,
419 const struct loongarch_isa *set2)
420 {
421 switch (set2->base)
422 {
423 case ISA_BASE_LA64V100:
424 return (set1->base == ISA_BASE_LA64V100);
425
426 default:
427 gcc_unreachable ();
428 }
429 }
430
431 static inline int
isa_fpu_compat_p(const struct loongarch_isa * set1,const struct loongarch_isa * set2)432 isa_fpu_compat_p (const struct loongarch_isa *set1,
433 const struct loongarch_isa *set2)
434 {
435 switch (set2->fpu)
436 {
437 case ISA_EXT_FPU64:
438 return set1->fpu == ISA_EXT_FPU64;
439
440 case ISA_EXT_FPU32:
441 return set1->fpu == ISA_EXT_FPU32 || set1->fpu == ISA_EXT_FPU64;
442
443 case ISA_EXT_NOFPU:
444 return 1;
445
446 default:
447 gcc_unreachable ();
448 }
449
450 }
451
452 static inline int
abi_compat_p(const struct loongarch_isa * isa,struct loongarch_abi abi)453 abi_compat_p (const struct loongarch_isa *isa, struct loongarch_abi abi)
454 {
455 int compatible = 1;
456 const struct loongarch_isa *isa2 = &isa_required (abi);
457
458 /* Append conditionals for new ISA components below. */
459 compatible = compatible && isa_base_compat_p (isa, isa2);
460 compatible = compatible && isa_fpu_compat_p (isa, isa2);
461 return compatible;
462 }
463
464 /* The behavior of this function should be consistent
465 with config.gcc. */
466 static inline int
abi_default_cpu_arch(struct loongarch_abi abi)467 abi_default_cpu_arch (struct loongarch_abi abi)
468 {
469 switch (abi.base)
470 {
471 case ABI_BASE_LP64D:
472 case ABI_BASE_LP64F:
473 case ABI_BASE_LP64S:
474 if (abi.ext == ABI_EXT_BASE)
475 return CPU_LOONGARCH64;
476 }
477 gcc_unreachable ();
478 }
479
480 static const char*
abi_str(struct loongarch_abi abi)481 abi_str (struct loongarch_abi abi)
482 {
483 /* "/base" can be omitted. */
484 if (abi.ext == ABI_EXT_BASE)
485 return (const char*)
486 obstack_copy0 (&msg_obstack, loongarch_abi_base_strings[abi.base],
487 strlen (loongarch_abi_base_strings[abi.base]));
488 else
489 {
490 APPEND_STRING (loongarch_abi_base_strings[abi.base])
491 APPEND1 ('/')
492 APPEND_STRING (loongarch_abi_ext_strings[abi.ext])
493 APPEND1 ('\0')
494
495 return XOBFINISH (&msg_obstack, const char *);
496 }
497 }
498
499 static const char*
isa_str(const struct loongarch_isa * isa,char separator)500 isa_str (const struct loongarch_isa *isa, char separator)
501 {
502 APPEND_STRING (loongarch_isa_base_strings[isa->base])
503 APPEND1 (separator)
504
505 if (isa->fpu == ISA_EXT_NOFPU)
506 {
507 APPEND_STRING ("no" OPTSTR_ISA_EXT_FPU)
508 }
509 else
510 {
511 APPEND_STRING (OPTSTR_ISA_EXT_FPU)
512 APPEND_STRING (loongarch_isa_ext_strings[isa->fpu])
513 }
514 APPEND1 ('\0')
515
516 /* Add more here. */
517
518 return XOBFINISH (&msg_obstack, const char *);
519 }
520
521 static const char*
arch_str(const struct loongarch_target * target)522 arch_str (const struct loongarch_target *target)
523 {
524 if (target->cpu_arch == CPU_NATIVE)
525 {
526 if (target->cpu_native == CPU_NATIVE)
527 {
528 /* Describe a native CPU with unknown PRID. */
529 const char* isa_string = isa_str (&target->isa, ',');
530 APPEND_STRING ("PRID: 0x")
531 APPEND_STRING (get_native_prid_str ())
532 APPEND_STRING (", ISA features: ")
533 APPEND_STRING (isa_string)
534 APPEND1 ('\0')
535 }
536 else
537 APPEND_STRING (loongarch_cpu_strings[target->cpu_native]);
538 }
539 else
540 APPEND_STRING (loongarch_cpu_strings[target->cpu_arch]);
541
542 APPEND1 ('\0')
543 return XOBFINISH (&msg_obstack, const char *);
544 }
545
546 static const char*
multilib_enabled_abi_list()547 multilib_enabled_abi_list ()
548 {
549 int enabled_abi_idx[MULTILIB_LIST_LEN] = { 0 };
550 const char* enabled_abi_str[MULTILIB_LIST_LEN] = { NULL };
551 unsigned int j = 0;
552
553 for (unsigned int i = 0; i < ABI_COUNT && j < MULTILIB_LIST_LEN; i++)
554 {
555 if (enabled_abi_types[abi_priority_list[i].base]
556 [abi_priority_list[i].ext])
557 {
558 enabled_abi_idx[j++] = i;
559 }
560 }
561
562 for (unsigned int k = 0; k < j; k++)
563 {
564 enabled_abi_str[k] = abi_str (abi_priority_list[enabled_abi_idx[k]]);
565 }
566
567 for (unsigned int k = 0; k < j - 1; k++)
568 {
569 APPEND_STRING (enabled_abi_str[k])
570 APPEND1 (',')
571 APPEND1 (' ')
572 }
573 APPEND_STRING (enabled_abi_str[j - 1])
574 APPEND1 ('\0')
575
576 return XOBFINISH (&msg_obstack, const char *);
577 }
578
579 /* option status feedback for "gcc --help=target -Q" */
580 void
loongarch_update_gcc_opt_status(struct loongarch_target * target,struct gcc_options * opts,struct gcc_options * opts_set)581 loongarch_update_gcc_opt_status (struct loongarch_target *target,
582 struct gcc_options *opts,
583 struct gcc_options *opts_set)
584 {
585 (void) opts_set;
586
587 /* status of -mabi */
588 opts->x_la_opt_abi_base = target->abi.base;
589
590 /* status of -march and -mtune */
591 opts->x_la_opt_cpu_arch = target->cpu_arch;
592 opts->x_la_opt_cpu_tune = target->cpu_tune;
593
594 /* status of -mcmodel */
595 opts->x_la_opt_cmodel = target->cmodel;
596
597 /* status of -mfpu */
598 opts->x_la_opt_fpu = target->isa.fpu;
599 }
600