Mercurial > hg > CbC > CbC_gcc
diff gcc/common/config/arm/arm-common.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/common/config/arm/arm-common.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/common/config/arm/arm-common.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Common hooks for ARM. - Copyright (C) 1991-2017 Free Software Foundation, Inc. + Copyright (C) 1991-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -18,6 +18,7 @@ <http://www.gnu.org/licenses/>. */ #define INCLUDE_LIST +#define INCLUDE_VECTOR #include "config.h" #include "system.h" #include "coretypes.h" @@ -30,13 +31,13 @@ #include "flags.h" #include "sbitmap.h" #include "diagnostic.h" +#include <algorithm> /* Set default optimization options. */ static const struct default_options arm_option_optimization_table[] = { /* Enable section anchors by default at -O1 or higher. */ { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 }, - { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, { OPT_LEVELS_NONE, 0, NULL, 0 } }; @@ -115,26 +116,99 @@ return arm_rewrite_selected_cpu (argv[argc - 1]); } -/* Truncate NAME at the first '+' character seen, or return - NAME unmodified. Similar to arm_rewrite_selected_cpu, but we must - preserve '.' as that is part of some architecture names. */ +/* Comparator for arm_rewrite_selected_arch. Compare the two arch extension + strings FIRST and SECOND and return TRUE if FIRST is less than SECOND + alphabetically. */ + +static bool +compare_opt_names (const char *first, const char *second) +{ + return strcmp (first, second) <= 0; +} +/* Rewrite the architecture string for passing to the assembler. + Although the syntax is similar we cannot assume that it supports + the newer FP related options. So strip any option that only + defines features in the standard -mfpu options out. We'll generate + a suitable -mfpu option elsewhere to carry that information. NAME + should already have been canonicalized, so we do not expect to + encounter +no.. options that remove features. A final problem is + that the assembler expects the feature extensions to be listed + alphabetically, so we build a list of required options and then + sort them into canonical order in the resulting string. */ const char * arm_rewrite_selected_arch (const char *name) { - static char output_buf[ARM_CPU_NAME_LENGTH + 1] = {0}; - char *arg_pos; + /* The result we return needs to be semi persistent, so handle being + re-invoked. */ + static char *asm_arch = NULL; + + if (asm_arch) + { + free (asm_arch); + asm_arch = NULL; + } + + const char *arg_pos = strchr (name, '+'); + + /* No extension options? just return the original string. */ + if (arg_pos == NULL) + return name; - strncpy (output_buf, name, ARM_CPU_NAME_LENGTH); - output_buf[ARM_CPU_NAME_LENGTH] = 0; + const arch_option *arch_opt + = arm_parse_arch_option_name (all_architectures, "-march", name); + + auto_sbitmap fpu_bits (isa_num_bits); + static const enum isa_feature fpu_bitlist[] + = { ISA_ALL_FPU_INTERNAL, isa_nobit }; + + arm_initialize_isa (fpu_bits, fpu_bitlist); + + auto_sbitmap opt_bits (isa_num_bits); + + /* Ensure that the resulting string is large enough for the result. We + never add options, so using strdup here will ensure that. */ + asm_arch = xstrdup (name); + asm_arch[arg_pos - name] = '\0'; + + std::vector<const char *>optlist; - arg_pos = strchr (output_buf, '+'); + while (arg_pos) + { + const char *end = strchr (arg_pos + 1, '+'); + size_t len = end ? end - arg_pos : strlen (arg_pos); - /* If we found a '+' truncate the entry at that point. */ - if (arg_pos) - *arg_pos = '\0'; + for (const cpu_arch_extension *entry = arch_opt->common.extensions; + entry->name != NULL; + entry++) + { + if (strncmp (entry->name, arg_pos + 1, len - 1) == 0 + && entry->name[len - 1] == '\0') + { + /* Don't expect removal options. */ + gcc_assert (!entry->remove); + arm_initialize_isa (opt_bits, entry->isa_bits); + if (!bitmap_subset_p (opt_bits, fpu_bits)) + optlist.push_back (entry->name); + bitmap_clear (opt_bits); + break; + } + } - return output_buf; + arg_pos = end; + } + + std::sort (optlist.begin (), optlist.end (), compare_opt_names); + + for (std::vector<const char *>::iterator opt_iter = optlist.begin (); + opt_iter != optlist.end (); + ++opt_iter) + { + strcat (asm_arch, "+"); + strcat (asm_arch, (*opt_iter)); + } + + return asm_arch; } /* Called by the driver to rewrite a name passed to the -march @@ -205,7 +279,8 @@ if (arch) { const arch_option *arch_opt - = arm_parse_arch_option_name (all_architectures, "-march", arch); + = arm_parse_arch_option_name (all_architectures, "-march", arch, + false); if (arch_opt && !check_isa_bits_for (arch_opt->common.isa_bits, isa_bit_notm)) @@ -214,7 +289,7 @@ else if (cpu) { const cpu_option *cpu_opt - = arm_parse_cpu_option_name (all_cores, "-mcpu", cpu); + = arm_parse_cpu_option_name (all_cores, "-mcpu", cpu, false); if (cpu_opt && !check_isa_bits_for (cpu_opt->common.isa_bits, isa_bit_notm)) @@ -235,6 +310,12 @@ auto_vec<const char*> candidates; for (; list->common.name != NULL; list++) candidates.safe_push (list->common.name); + +#ifdef HAVE_LOCAL_CPU_DETECT + /* Add also "native" as possible value. */ + candidates.safe_push ("native"); +#endif + char *s; const char *hint = candidates_list_and_hint (target, s, candidates); if (hint) @@ -249,10 +330,11 @@ /* Parse the base component of a CPU selection in LIST. Return a pointer to the entry in the architecture table. OPTNAME is the name of the option we are parsing and can be used if a diagnostic - is needed. */ + is needed. If COMPLAIN is true (the default) emit error + messages and hints on invalid input. */ const cpu_option * arm_parse_cpu_option_name (const cpu_option *list, const char *optname, - const char *target) + const char *target, bool complain) { const cpu_option *entry; const char *end = strchr (target, '+'); @@ -265,8 +347,11 @@ return entry; } - error_at (input_location, "unrecognized %s target: %s", optname, target); - arm_print_hint_for_cpu_option (target, list); + if (complain) + { + error_at (input_location, "unrecognized %s target: %s", optname, target); + arm_print_hint_for_cpu_option (target, list); + } return NULL; } @@ -279,6 +364,12 @@ auto_vec<const char*> candidates; for (; list->common.name != NULL; list++) candidates.safe_push (list->common.name); + +#ifdef HAVE_LOCAL_CPU_DETECT + /* Add also "native" as possible value. */ + candidates.safe_push ("native"); +#endif + char *s; const char *hint = candidates_list_and_hint (target, s, candidates); if (hint) @@ -293,10 +384,11 @@ /* Parse the base component of a CPU or architecture selection in LIST. Return a pointer to the entry in the architecture table. OPTNAME is the name of the option we are parsing and can be used if - a diagnostic is needed. */ + a diagnostic is needed. If COMPLAIN is true (the default) emit error + messages and hints on invalid input. */ const arch_option * arm_parse_arch_option_name (const arch_option *list, const char *optname, - const char *target) + const char *target, bool complain) { const arch_option *entry; const char *end = strchr (target, '+'); @@ -309,8 +401,11 @@ return entry; } - error_at (input_location, "unrecognized %s target: %s", optname, target); - arm_print_hint_for_arch_option (target, list); + if (complain) + { + error_at (input_location, "unrecognized %s target: %s", optname, target); + arm_print_hint_for_arch_option (target, list); + } return NULL; } @@ -824,6 +919,86 @@ return ""; } +/* Generate a -mfpu= option for passing to the assembler. This is + only called when -mfpu was set (possibly defaulted) to auto and is + needed to ensure that the assembler knows the correct FPU to use. + It wouldn't really be needed except that the compiler can be used + to invoke the assembler directly on hand-written files that lack + the necessary internal .fpu directives. We assume that the architecture + canonicalization calls have already been made so that we have a final + -march= option to derive the fpu from. */ +const char* +arm_asm_auto_mfpu (int argc, const char **argv) +{ + static char *auto_fpu = NULL; + const char *arch = NULL; + static const enum isa_feature fpu_bitlist[] + = { ISA_ALL_FPU_INTERNAL, isa_nobit }; + const arch_option *selected_arch; + static const char* fpuname = "softvfp"; + + /* Handle multiple calls to this routine. */ + if (auto_fpu) + { + free (auto_fpu); + auto_fpu = NULL; + } + + while (argc) + { + if (strcmp (argv[0], "arch") == 0) + arch = argv[1]; + else + fatal_error (input_location, + "unrecognized operand to %%:asm_auto_mfpu"); + argc -= 2; + argv += 2; + } + + auto_sbitmap target_isa (isa_num_bits); + auto_sbitmap fpubits (isa_num_bits); + + gcc_assert (arch != NULL); + selected_arch = arm_parse_arch_option_name (all_architectures, + "-march", arch); + if (selected_arch == NULL) + return ""; + + arm_initialize_isa (target_isa, selected_arch->common.isa_bits); + arm_parse_option_features (target_isa, &selected_arch->common, + strchr (arch, '+')); + arm_initialize_isa (fpubits, fpu_bitlist); + + bitmap_and (fpubits, fpubits, target_isa); + + /* The logic below is essentially identical to that in + arm.c:arm_identify_fpu_from_isa(), but that only works in the main + part of the compiler. */ + + /* If there are no FPU capability bits, we just pass -mfpu=softvfp. */ + if (!bitmap_empty_p (fpubits)) + { + unsigned int i; + auto_sbitmap cand_fpubits (isa_num_bits); + for (i = 0; i < TARGET_FPU_auto; i++) + { + arm_initialize_isa (cand_fpubits, all_fpus[i].isa_bits); + if (bitmap_equal_p (fpubits, cand_fpubits)) + { + fpuname = all_fpus[i].name; + break; + } + } + + gcc_assert (i != TARGET_FPU_auto); + } + + auto_fpu = (char *) xmalloc (strlen (fpuname) + sizeof ("-mfpu=")); + strcpy (auto_fpu, "-mfpu="); + strcat (auto_fpu, fpuname); + return auto_fpu; +} + #undef ARM_CPU_NAME_LENGTH