xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/loongarch/loongarch-opts.cc (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
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