Hello,

Attached is a patch for PR 53929, but is also required by PR 80881.


With native Windows thread-local storage (TLS) on master, GCC may generate 
assembly like:

    mov eax, [rdx + my_variable@secrel32]

GAS doesn't parse this correctly. Since `@` is a valid character in symbols of `__fastcall` and `__vectorcall` functions, the `@secrel32` relocation is mistaken as part of the symbol, so this is parsed as:

    mov eax, [rdx + "my_variable@secrel32"]

Instead, it's necessary to quote the variable name in this case, to make GAS 
parser stop right before `@`:

    mov eax, [rdx + "my_variable"@secrel32]

This also solves the ambiguity if a user declares a function or variable as a 
register.


Attached are also test results of GCC master branch on x86_64-pc-linux-gnu, with and without this patch. It is not possible to bootstrap GCC with intel syntax, as some Linux headers contain inline assembly with only AT&T templates. It is however possible to bootstrap GCC on {i686,x86_64}-w64-mingw32.


--
Best regards,
LIU Hao




 From d733676c742f9af9b9ab34317433db242128e53d Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mo...@126.com>
Date: Sat, 22 Feb 2025 13:11:51 +0800
Subject: [PATCH] i386: Quote user-defined symbols in assembly in Intel syntax

With `-masm=intel`, GCC generates registers without % prefixes. If a
user-declared symbol happens to match a register, it will confuse the
assembler. User-defined symbols should be quoted, so they are not to
be mistaken for registers or operators.

Support for quoted symbols were added in Binutils 2.26, originally
for ARM assembly, where registers are also unprefixed:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d02603dc201f80cd9d2a1f4b1a16110b1e04222b

This change is required for `@SECREL32` to work in Intel syntax when
targeting Windows, where `@` is allowed as part of a symbol. GNU AS
fails to parse a plain symbol with that suffix:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80881#c79

gcc/config/:
        PR target/53929
        PR target/80881
        * gcc/config/i386/i386-protos.h (ix86_asm_output_labelref): Declare new
        function for quoting user-defined symbols in Intel syntax.
        * gcc/config/i386/i386.cc (ix86_asm_output_labelref): Implement it.
        * gcc/config/i386/i386.h (ASM_OUTPUT_LABELREF): Use it.
        * gcc/config/i386/cygming.h (ASM_OUTPUT_LABELREF): Use it.
---
  gcc/config/i386/cygming.h     |  5 +++--
  gcc/config/i386/i386-protos.h |  1 +
  gcc/config/i386/i386.cc       | 13 +++++++++++++
  gcc/config/i386/i386.h        |  7 +++++++
  4 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index 743cc38f5852..0a3173c4e937 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -246,9 +246,10 @@ do {                                                       
\
  #undef ASM_OUTPUT_LABELREF
  #define  ASM_OUTPUT_LABELREF(STREAM, NAME)    \
  do {                                          \
+  const char *prefix = "";                   \
    if ((NAME)[0] != FASTCALL_PREFIX)           \
-    fputs (user_label_prefix, (STREAM));       \
-  fputs ((NAME), (STREAM));                    \
+    prefix = user_label_prefix;                        \
+  ix86_asm_output_labelref ((STREAM), prefix, (NAME)); \
  } while (0)

  /* This does much the same in memory rather than to a stream.  */
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index e85b925704ba..10863ab9e9de 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -199,6 +199,7 @@ extern int ix86_attr_length_vex_default (rtx_insn *, bool, 
bool);
  extern rtx ix86_libcall_value (machine_mode);
  extern bool ix86_function_arg_regno_p (int);
  extern void ix86_asm_output_function_label (FILE *, const char *, tree);
+extern void ix86_asm_output_labelref (FILE *, const char *, const char *);
  extern void ix86_call_abi_override (const_tree);
  extern int ix86_reg_parm_stack_space (const_tree);

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 3d629b06094a..59114d4aa15e 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -1716,6 +1716,19 @@ ix86_asm_output_function_label (FILE *out_file, const 
char *fname,
      }
  }

+/* Output a user-defined label.  In AT&T syntax, registers are prefixed
+   with %, so labels require no punctuation.  In Intel syntax, registers
+   are unprefixed, so labels may clash with registers or other operators,
+   and require quoting.  */
+void
+ix86_asm_output_labelref (FILE *file, const char *prefix, const char *label)
+{
+  if (ASSEMBLER_DIALECT == ASM_ATT)
+    fprintf (file, "%s%s", prefix, label);
+  else
+    fprintf (file, "\"%s%s\"", prefix, label);
+}
+
  /* Implementation of call abi switching target hook. Specific to FNDECL
     the specific call register sets are set.  See also
     ix86_conditional_register_usage for more details.  */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 18fa97a9eb0d..b9fb1017498f 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2267,6 +2267,13 @@ extern unsigned int const 
svr4_debugger_register_map[FIRST_PSEUDO_REGISTER];
    } while (0)
  #endif

+/* In Intel syntax, we have to quote user-defined labels that would
+   match (unprefixed) registers or operators.  */
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME)      \
+  ix86_asm_output_labelref ((STREAM), user_label_prefix, (NAME))
+
  /* Under some conditions we need jump tables in the text section,
     because the assembler cannot handle label differences between
     sections.  */
--
2.49.0


From d733676c742f9af9b9ab34317433db242128e53d Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mo...@126.com>
Date: Sat, 22 Feb 2025 13:11:51 +0800
Subject: [PATCH] i386: Quote user-defined symbols in assembly in Intel syntax

With `-masm=intel`, GCC generates registers without % prefixes. If a
user-declared symbol happens to match a register, it will confuse the
assembler. User-defined symbols should be quoted, so they are not to
be mistaken for registers or operators.

Support for quoted symbols were added in Binutils 2.26, originally
for ARM assembly, where registers are also unprefixed:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d02603dc201f80cd9d2a1f4b1a16110b1e04222b

This change is required for `@SECREL32` to work in Intel syntax when
targeting Windows, where `@` is allowed as part of a symbol. GNU AS
fails to parse a plain symbol with that suffix:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80881#c79

gcc/config/:
        PR target/53929
        PR target/80881
        * gcc/config/i386/i386-protos.h (ix86_asm_output_labelref): Declare new
        function for quoting user-defined symbols in Intel syntax.
        * gcc/config/i386/i386.cc (ix86_asm_output_labelref): Implement it.
        * gcc/config/i386/i386.h (ASM_OUTPUT_LABELREF): Use it.
        * gcc/config/i386/cygming.h (ASM_OUTPUT_LABELREF): Use it.
---
 gcc/config/i386/cygming.h     |  5 +++--
 gcc/config/i386/i386-protos.h |  1 +
 gcc/config/i386/i386.cc       | 13 +++++++++++++
 gcc/config/i386/i386.h        |  7 +++++++
 4 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index 743cc38f5852..0a3173c4e937 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -246,9 +246,10 @@ do {                                                       
\
 #undef ASM_OUTPUT_LABELREF
 #define  ASM_OUTPUT_LABELREF(STREAM, NAME)     \
 do {                                           \
+  const char *prefix = "";                     \
   if ((NAME)[0] != FASTCALL_PREFIX)            \
-    fputs (user_label_prefix, (STREAM));       \
-  fputs ((NAME), (STREAM));                    \
+    prefix = user_label_prefix;                        \
+  ix86_asm_output_labelref ((STREAM), prefix, (NAME)); \
 } while (0)
 
 /* This does much the same in memory rather than to a stream.  */
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index e85b925704ba..10863ab9e9de 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -199,6 +199,7 @@ extern int ix86_attr_length_vex_default (rtx_insn *, bool, 
bool);
 extern rtx ix86_libcall_value (machine_mode);
 extern bool ix86_function_arg_regno_p (int);
 extern void ix86_asm_output_function_label (FILE *, const char *, tree);
+extern void ix86_asm_output_labelref (FILE *, const char *, const char *);
 extern void ix86_call_abi_override (const_tree);
 extern int ix86_reg_parm_stack_space (const_tree);
 
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 3d629b06094a..59114d4aa15e 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -1716,6 +1716,19 @@ ix86_asm_output_function_label (FILE *out_file, const 
char *fname,
     }
 }
 
+/* Output a user-defined label.  In AT&T syntax, registers are prefixed
+   with %, so labels require no punctuation.  In Intel syntax, registers
+   are unprefixed, so labels may clash with registers or other operators,
+   and require quoting.  */
+void
+ix86_asm_output_labelref (FILE *file, const char *prefix, const char *label)
+{
+  if (ASSEMBLER_DIALECT == ASM_ATT)
+    fprintf (file, "%s%s", prefix, label);
+  else
+    fprintf (file, "\"%s%s\"", prefix, label);
+}
+
 /* Implementation of call abi switching target hook. Specific to FNDECL
    the specific call register sets are set.  See also
    ix86_conditional_register_usage for more details.  */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 18fa97a9eb0d..b9fb1017498f 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2267,6 +2267,13 @@ extern unsigned int const 
svr4_debugger_register_map[FIRST_PSEUDO_REGISTER];
   } while (0)
 #endif
 
+/* In Intel syntax, we have to quote user-defined labels that would
+   match (unprefixed) registers or operators.  */
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME)      \
+  ix86_asm_output_labelref ((STREAM), user_label_prefix, (NAME))
+
 /* Under some conditions we need jump tables in the text section,
    because the assembler cannot handle label differences between
    sections.  */
-- 
2.49.0

Attachment: gcc_make_check_9001.log.gz
Description: application/gzip

Attachment: gcc_make_check_master.log.gz
Description: application/gzip

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to