diff options
Diffstat (limited to 'gcc/config/loongarch/loongarch-driver.cc')
-rw-r--r-- | gcc/config/loongarch/loongarch-driver.cc | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/gcc/config/loongarch/loongarch-driver.cc b/gcc/config/loongarch/loongarch-driver.cc new file mode 100644 index 0000000..0adcc92 --- /dev/null +++ b/gcc/config/loongarch/loongarch-driver.cc @@ -0,0 +1,187 @@ +/* Subroutines for the gcc driver. + Copyright (C) 2021-2022 Free Software Foundation, Inc. + Contributed by Loongson Ltd. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "obstack.h" +#include "diagnostic-core.h" + +#include "loongarch-opts.h" +#include "loongarch-driver.h" + +static int + opt_arch_driver = M_OPTION_NOT_SEEN, + opt_tune_driver = M_OPTION_NOT_SEEN, + opt_fpu_driver = M_OPTION_NOT_SEEN, + opt_abi_base_driver = M_OPTION_NOT_SEEN, + opt_abi_ext_driver = M_OPTION_NOT_SEEN, + opt_cmodel_driver = M_OPTION_NOT_SEEN; + +int opt_switches = 0; + +/* This flag is set to 1 if we believe that the user might be avoiding + linking (implicitly) against something from the startfile search paths. */ +static int no_link = 0; + +#define LARCH_DRIVER_SET_M_FLAG(OPTS_ARRAY, N_OPTS, FLAG, STR) \ + for (int i = 0; i < (N_OPTS); i++) \ + { \ + if ((OPTS_ARRAY)[i] != 0) \ + if (strcmp ((STR), (OPTS_ARRAY)[i]) == 0) \ + (FLAG) = i; \ + } + +/* Use the public obstack from the gcc driver (defined in gcc.c). + This is for allocating space for the returned string. */ +extern struct obstack opts_obstack; + +#define APPEND_LTR(S) \ + obstack_grow (&opts_obstack, (const void*) (S), \ + sizeof ((S)) / sizeof (char) -1) + +#define APPEND_VAL(S) \ + obstack_grow (&opts_obstack, (const void*) (S), strlen ((S))) + + +const char* +driver_set_m_flag (int argc, const char **argv) +{ + int parm_off = 0; + + if (argc != 1) + return "%eset_m_flag requires exactly 1 argument."; + +#undef PARM +#define PARM (argv[0] + parm_off) + +/* Note: sizeof (OPTSTR_##NAME) equals the length of "<option>=". */ +#undef MATCH_OPT +#define MATCH_OPT(NAME) \ + (strncmp (argv[0], OPTSTR_##NAME "=", \ + (parm_off = sizeof (OPTSTR_##NAME))) == 0) + + if (strcmp (argv[0], "no_link") == 0) + { + no_link = 1; + } + else if (MATCH_OPT (ABI_BASE)) + { + LARCH_DRIVER_SET_M_FLAG ( + loongarch_abi_base_strings, N_ABI_BASE_TYPES, + opt_abi_base_driver, PARM) + } + else if (MATCH_OPT (ISA_EXT_FPU)) + { + LARCH_DRIVER_SET_M_FLAG (loongarch_isa_ext_strings, N_ISA_EXT_FPU_TYPES, + opt_fpu_driver, PARM) + } + else if (MATCH_OPT (ARCH)) + { + LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_ARCH_TYPES, + opt_arch_driver, PARM) + } + else if (MATCH_OPT (TUNE)) + { + LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_TUNE_TYPES, + opt_tune_driver, PARM) + } + else if (MATCH_OPT (CMODEL)) + { + LARCH_DRIVER_SET_M_FLAG (loongarch_cmodel_strings, N_CMODEL_TYPES, + opt_cmodel_driver, PARM) + } + else /* switches */ + { + int switch_idx = M_OPTION_NOT_SEEN; + + LARCH_DRIVER_SET_M_FLAG (loongarch_switch_strings, N_SWITCH_TYPES, + switch_idx, argv[0]) + + if (switch_idx != M_OPTION_NOT_SEEN) + opt_switches |= loongarch_switch_mask[switch_idx]; + } + return ""; +} + +const char* +driver_get_normalized_m_opts (int argc, const char **argv) +{ + if (argc != 0) + { + (void) argv; /* To make compiler shut up about unused argument. */ + return " %eget_normalized_m_opts requires no argument.\n"; + } + + loongarch_config_target (& la_target, + opt_switches, + opt_arch_driver, + opt_tune_driver, + opt_fpu_driver, + opt_abi_base_driver, + opt_abi_ext_driver, + opt_cmodel_driver, + !no_link /* follow_multilib_list */); + + /* Output normalized option strings. */ + obstack_blank (&opts_obstack, 0); + +#undef APPEND_LTR +#define APPEND_LTR(S) \ + obstack_grow (&opts_obstack, (const void*) (S), \ + sizeof ((S)) / sizeof (char) -1) + +#undef APPEND_VAL +#define APPEND_VAL(S) \ + obstack_grow (&opts_obstack, (const void*) (S), strlen ((S))) + +#undef APPEND_OPT +#define APPEND_OPT(NAME) \ + APPEND_LTR (" %<m" OPTSTR_##NAME "=* " \ + " -m" OPTSTR_##NAME "=") + + for (int i = 0; i < N_SWITCH_TYPES; i++) + { + APPEND_LTR (" %<m"); + APPEND_VAL (loongarch_switch_strings[i]); + } + + APPEND_OPT (ABI_BASE); + APPEND_VAL (loongarch_abi_base_strings[la_target.abi.base]); + + APPEND_OPT (ARCH); + APPEND_VAL (loongarch_cpu_strings[la_target.cpu_arch]); + + APPEND_OPT (ISA_EXT_FPU); + APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.fpu]); + + APPEND_OPT (CMODEL); + APPEND_VAL (loongarch_cmodel_strings[la_target.cmodel]); + + APPEND_OPT (TUNE); + APPEND_VAL (loongarch_cpu_strings[la_target.cpu_tune]); + + obstack_1grow (&opts_obstack, '\0'); + + return XOBFINISH (&opts_obstack, const char *); +} |