blob: 0adcc923b7d528d2e575cae4d5555ae755edb108 [file] [log] [blame]
/* 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 *);
}