Home | History | Annotate | Line # | Download | only in loongarch
loongarch-opts.cc revision 1.1
      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
     58 is_multilib_enabled (struct loongarch_abi abi)
     59 {
     60   return enabled_abi_types[abi.base][abi.ext];
     61 }
     62 
     63 static void
     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
    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
    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
    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
    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
    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
    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*
    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*
    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*
    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*
    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
    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