Commit 24531cd6 by Richard Earnshaw Committed by Richard Earnshaw

[arm] Don't strip off all architecture features from -march passed to assembler

When GCC invokes the assembler it generates a sanitized version of the
user-specified -march option to pass through, since the assembler does
not understand all the new FPU-related architectural options.
Unfortunately it goes too far and strips off all the architectural
extensions, including some that are unrelated to the -mfpu variant
selected.

Again, this doesn't really matter when compiling C code because the
compiler will override the command-line specified architecture with
directives in the assembly file itself, but when using the compiler
driver to invoke the assembler the only indiciation of the desired
architecture might come from the command line.

We fix this by adjusting the canonicalization pass to remove any
option that only specifies features that can be expressed by -mfpu
(any that go beyond that are already supported by the assembler).  We
do have to take care to re-order the options, though as the assembler
expects feature options to be in a canonical order (unlike the
compiler, where ordering is handled left-to-right: there's only a
difference if there are negation options, but a canonicalized
architecture string shouldn't have any of those).  We do this by
recording which options we need and then sorting the final list
alphabetically.

	* common/config/arm/arm-common.c: Include <algorithm>.
	(INCLUDE_VECTOR): Define.
	(compare_opt_names): New function.
	(arm_rewrite_selected_arch): Only strip out extensions that can be
	expressed through -mfpu.  Sort the remaining extensions
	alphabetically.

From-SVN: r255503
parent 940269b6
2017-06-08 Richard Earnshaw <rearnsha@arm.com> 2017-06-08 Richard Earnshaw <rearnsha@arm.com>
* common/config/arm/arm-common.c: Include <algorithm>.
(INCLUDE_VECTOR): Define.
(compare_opt_names): New function.
(arm_rewrite_selected_arch): Only strip out extensions that can be
expressed through -mfpu. Sort the remaining extensions
alphabetically.
2017-06-08 Richard Earnshaw <rearnsha@arm.com>
* config/arm/arm.h (arm_asm_auto_mfpu): Declare. * config/arm/arm.h (arm_asm_auto_mfpu): Declare.
(ASM_CPU_SPEC_FUNCTIONS): Add new rule asm_auto_mfpu. (ASM_CPU_SPEC_FUNCTIONS): Add new rule asm_auto_mfpu.
(ASM_CPU_SPEC): Use it if -mfpu is set to auto. (ASM_CPU_SPEC): Use it if -mfpu is set to auto.
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#define INCLUDE_LIST #define INCLUDE_LIST
#define INCLUDE_VECTOR
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "coretypes.h" #include "coretypes.h"
...@@ -30,6 +31,7 @@ ...@@ -30,6 +31,7 @@
#include "flags.h" #include "flags.h"
#include "sbitmap.h" #include "sbitmap.h"
#include "diagnostic.h" #include "diagnostic.h"
#include <algorithm>
/* Set default optimization options. */ /* Set default optimization options. */
static const struct default_options arm_option_optimization_table[] = static const struct default_options arm_option_optimization_table[] =
...@@ -114,26 +116,99 @@ arm_rewrite_mcpu (int argc, const char **argv) ...@@ -114,26 +116,99 @@ arm_rewrite_mcpu (int argc, const char **argv)
return arm_rewrite_selected_cpu (argv[argc - 1]); return arm_rewrite_selected_cpu (argv[argc - 1]);
} }
/* Truncate NAME at the first '+' character seen, or return static bool
NAME unmodified. Similar to arm_rewrite_selected_cpu, but we must compare_opt_names (const char *first, const char *second)
preserve '.' as that is part of some architecture names. */ {
for (int i = 0; ; i++)
if (first[i] == 0
|| first[i] < second[i])
return true;
return false;
}
/* 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 * const char *
arm_rewrite_selected_arch (const char *name) arm_rewrite_selected_arch (const char *name)
{ {
static char output_buf[ARM_CPU_NAME_LENGTH + 1] = {0}; /* The result we return needs to be semi persistent, so handle being
char *arg_pos; re-invoked. */
static char *asm_arch = NULL;
strncpy (output_buf, name, ARM_CPU_NAME_LENGTH); if (asm_arch)
output_buf[ARM_CPU_NAME_LENGTH] = 0; {
free (asm_arch);
asm_arch = NULL;
}
arg_pos = strchr (output_buf, '+'); const char *arg_pos = strchr (name, '+');
/* If we found a '+' truncate the entry at that point. */ /* No extension options? just return the original string. */
if (arg_pos) if (arg_pos == NULL)
*arg_pos = '\0'; return name;
return output_buf; 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;
while (arg_pos)
{
const char *end = strchr (arg_pos + 1, '+');
size_t len = end ? end - arg_pos : strlen (arg_pos);
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;
}
}
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 /* Called by the driver to rewrite a name passed to the -march
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment