[arm] Generate a -mfpu= option for passing to the assembler
authorRichard Earnshaw <rearnsha@arm.com>
Fri, 8 Dec 2017 10:55:01 +0000 (10:55 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Fri, 8 Dec 2017 10:55:01 +0000 (10:55 +0000)
When gcc runs with the new -mfpu=auto option (either explicitly or
when that's the default behaviour) then this option is not passed
through to the assembler as we cannot rely on the assembler
understanding it (currently it doesn't understand it at all, but in
future that might change).  That means that the assembler falls back
to its builtin default, which may not correspond to what the user
expected based on the command-line options they passed.

Normally that wouldn't matter because assembler files generated by the
compiler will contain explicit directives that set the FPU type
directly and override any internal defaults; but when the compiler
driver is used to invoke the assembler directly (because the source
file ends in .s or .S) then this might cause a problem if that assumes
the FPU matches the compiler.

To address this, this patch makes the driver construct a -mfpu= option
for the assembler in the same way as the compiler generates an
internal .fpu directive.  As mentioned, this makes no difference if
the assembler file explicitly overrides the command line options, but
helps in the case where this is implicit.

* config/arm/arm.h (arm_asm_auto_mfpu): Declare.
(ASM_CPU_SPEC_FUNCTIONS): Add new rule asm_auto_mfpu.
(ASM_CPU_SPEC): Use it if -mfpu is set to auto.
* common/config/arm/arm-common.c (arm_asm_auto_mfpu): New function.
-- This line, and those below, will be ignored--

M    gcc/ChangeLog
M    gcc/common/config/arm/arm-common.c
M    gcc/config/arm/arm.h

From-SVN: r255502

gcc/ChangeLog
gcc/common/config/arm/arm-common.c
gcc/config/arm/arm.h

index e34e182..435a230 100644 (file)
@@ -1,3 +1,10 @@
+2017-06-08  Richard Earnshaw  <rearnsha@arm.com>
+
+       * config/arm/arm.h (arm_asm_auto_mfpu): Declare.
+       (ASM_CPU_SPEC_FUNCTIONS): Add new rule asm_auto_mfpu.
+       (ASM_CPU_SPEC): Use it if -mfpu is set to auto.
+       * common/config/arm/arm-common.c (arm_asm_auto_mfpu): New function.
+
 2017-06-08  Tristan Gingold  <gindold@adacore.com>
 
        PR ada/81470
index 5ae20fe..90b04f1 100644 (file)
@@ -823,6 +823,86 @@ arm_be8_option (int argc, const char **argv)
   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
 
 
index b189951..ac51412 100644 (file)
@@ -2166,13 +2166,16 @@ extern int making_const_table;
 
 extern const char *arm_rewrite_mcpu (int argc, const char **argv);
 extern const char *arm_rewrite_march (int argc, const char **argv);
+extern const char *arm_asm_auto_mfpu (int argc, const char **argv);
 #define ASM_CPU_SPEC_FUNCTIONS                 \
   { "rewrite_mcpu", arm_rewrite_mcpu },        \
-  { "rewrite_march", arm_rewrite_march },
+  { "rewrite_march", arm_rewrite_march },      \
+  { "asm_auto_mfpu", arm_asm_auto_mfpu },
 
 #define ASM_CPU_SPEC                                                   \
+  " %{mfpu=auto:%<mfpu=auto %:asm_auto_mfpu(%{march=*: arch %*})}"     \
   " %{mcpu=generic-*:-march=%:rewrite_march(%{mcpu=generic-*:%*});"    \
-  "   march=*:-march=%:rewrite_march(%{march=*:%*});"          \
+  "   march=*:-march=%:rewrite_march(%{march=*:%*});"                  \
   "   mcpu=*:-mcpu=%:rewrite_mcpu(%{mcpu=*:%*})"                       \
   " }"