for (i = 0; i < ARRAY_SIZE (loongarch_builtins); i++)
{
d = &loongarch_builtins[i];
- if (d->avail ())
- {
- type = loongarch_build_function_type (d->function_type);
- loongarch_builtin_decls[i]
- = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL,
- NULL);
- loongarch_get_builtin_decl_index[d->icode] = i;
- }
+ type = loongarch_build_function_type (d->function_type);
+ loongarch_builtin_decls[i]
+ = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL,
+ NULL);
+ loongarch_get_builtin_decl_index[d->icode] = i;
}
}
int ignore ATTRIBUTE_UNUSED)
{
tree fndecl;
- unsigned int fcode, avail;
+ unsigned int fcode;
const struct loongarch_builtin_description *d;
fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
fcode = DECL_MD_FUNCTION_CODE (fndecl);
gcc_assert (fcode < ARRAY_SIZE (loongarch_builtins));
d = &loongarch_builtins[fcode];
- avail = d->avail ();
- gcc_assert (avail != 0);
+
+ if (!d->avail ())
+ {
+ error_at (EXPR_LOCATION (exp),
+ "built-in function %qD is not enabled", fndecl);
+ return target;
+ }
+
switch (d->builtin_type)
{
case LARCH_BUILTIN_DIRECT:
loongarch_dwarf_regno[i] = INVALID_REGNUM;
}
+ /* Function to allocate machine-dependent function status. */
+ init_machine_status = &loongarch_init_machine_status;
+};
+
+static void
+loongarch_reg_init (void)
+{
/* Set up loongarch_hard_regno_mode_ok. */
for (int mode = 0; mode < MAX_MACHINE_MODE; mode++)
for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
loongarch_hard_regno_mode_ok_p[mode][regno]
= loongarch_hard_regno_mode_ok_uncached (regno, (machine_mode) mode);
-
- /* Function to allocate machine-dependent function status. */
- init_machine_status = &loongarch_init_machine_status;
-};
+}
static void
loongarch_option_override_internal (struct loongarch_target *target,
/* Override some options according to the resolved target. */
loongarch_target_option_override (target, opts, opts_set);
+
+ target_option_default_node = target_option_current_node
+ = build_target_option_node (opts, opts_set);
+
+ loongarch_reg_init ();
+}
+
+/* Remember the last target of loongarch_set_current_function. */
+
+static GTY(()) tree loongarch_previous_fndecl;
+
+/* Restore or save the TREE_TARGET_GLOBALS from or to new_tree.
+ Used by loongarch_set_current_function to
+ make sure optab availability predicates are recomputed when necessary. */
+
+static void
+loongarch_save_restore_target_globals (tree new_tree)
+{
+ if (TREE_TARGET_GLOBALS (new_tree))
+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+ else if (new_tree == target_option_default_node)
+ restore_target_globals (&default_target_globals);
+ else
+ TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
+}
+
+/* Implement TARGET_SET_CURRENT_FUNCTION. */
+
+static void
+loongarch_set_current_function (tree fndecl)
+{
+ if (fndecl == loongarch_previous_fndecl)
+ return;
+
+ tree old_tree;
+ if (loongarch_previous_fndecl == NULL_TREE)
+ old_tree = target_option_current_node;
+ else if (DECL_FUNCTION_SPECIFIC_TARGET (loongarch_previous_fndecl))
+ old_tree = DECL_FUNCTION_SPECIFIC_TARGET (loongarch_previous_fndecl);
+ else
+ old_tree = target_option_default_node;
+
+ if (fndecl == NULL_TREE)
+ {
+ if (old_tree != target_option_current_node)
+ {
+ loongarch_previous_fndecl = NULL_TREE;
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION
+ (target_option_current_node));
+ }
+ return;
+ }
+
+ tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+ if (new_tree == NULL_TREE)
+ new_tree = target_option_default_node;
+
+ loongarch_previous_fndecl = fndecl;
+
+ if (new_tree == old_tree)
+ return;
+
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (new_tree));
+
+ loongarch_reg_init ();
+
+ loongarch_save_restore_target_globals (new_tree);
}
+
+
/* Implement TARGET_OPTION_OVERRIDE. */
static void
loongarch_option_override (void)
{
+ /* Global initializations. */
+ loongarch_global_init ();
+
/* Setting up the target configuration. */
loongarch_option_override_internal (&la_target,
&global_options,
&global_options_set);
- /* Global initializations. */
- loongarch_global_init ();
}
/* Implement TARGET_OPTION_SAVE. */
#undef TARGET_OPTION_RESTORE
#define TARGET_OPTION_RESTORE loongarch_option_restore
+#undef TARGET_SET_CURRENT_FUNCTION
+#define TARGET_SET_CURRENT_FUNCTION loongarch_set_current_function
+
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address