diff options
Diffstat (limited to 'gcc/config/loongarch/loongarch.cc')
-rw-r--r-- | gcc/config/loongarch/loongarch.cc | 91 |
1 files changed, 85 insertions, 6 deletions
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index c90b701..6b92e70 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -7570,15 +7570,19 @@ loongarch_global_init (void) 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, @@ -7605,20 +7609,92 @@ 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. */ @@ -10935,6 +11011,9 @@ loongarch_asm_code_end (void) #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 |