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/ChangeLog:
PR target/53929
PR target/80881
* config/i386/i386-protos.h (ix86_asm_output_labelref): Declare new
function for quoting user-defined symbols in Intel syntax.
* config/i386/i386.cc (ix86_asm_output_labelref): Implement it.
* config/i386/i386.h (ASM_OUTPUT_LABELREF): Use it.
* config/i386/cygming.h (ASM_OUTPUT_LABELREF): Use it.
#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. */
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);
}
}
+/* 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. */
} 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. */