From c892d8f58f6fed46c343bdb6dd4d365f08f801b8 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 22 Jan 2020 10:22:16 +0100 Subject: [PATCH] i386: Fix up -fdollars-in-identifiers with identifiers starting with $ in -masm=att [PR91298] In AT&T syntax leading $ is special, so if we have identifiers that start with dollar, we usually fail to assemble it (or assemble incorrectly). As mentioned in the PR, what works is wrapping the identifiers inside of parens, like: movl $($a), %eax leaq ($a)(,%rdi,4), %rax movl ($a)(%rip), %eax movl ($a)+16(%rip), %eax .globl $a .type $a, @object .size $a, 72 $a: .string "$a" .quad ($a) (this is x86_64 -fno-pic -O2). In some places ($a) is not accepted, like as .globl operand, in .type, .size, so the patch overrides ASM_OUTPUT_SYMBOL_REF rather than e.g. ASM_OUTPUT_LABELREF. I didn't want to duplicate what assemble_name is doing (following transparent aliases), so split assemble_name into two parts; just mere looking at the first character of a name before calling assemble_name wouldn't be good enough, a transparent alias could lead from a name not starting with $ to one starting with it and vice versa. 2020-01-22 Jakub Jelinek PR target/91298 * output.h (assemble_name_resolve): Declare. * varasm.c (assemble_name_resolve): New function. (assemble_name): Use it. * config/i386/i386.h (ASM_OUTPUT_SYMBOL_REF): Define. * gcc.target/i386/pr91298-1.c: New test. * gcc.target/i386/pr91298-2.c: New test. --- gcc/ChangeLog | 8 ++++++ gcc/config/i386/i386.h | 25 +++++++++++++++++ gcc/output.h | 6 +++++ gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.target/i386/pr91298-1.c | 14 ++++++++++ gcc/testsuite/gcc.target/i386/pr91298-2.c | 5 ++++ gcc/varasm.c | 33 ++++++++++++++--------- 7 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr91298-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr91298-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d338a4a9728..d3a7bc25da8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2020-01-22 Jakub Jelinek + + PR target/91298 + * output.h (assemble_name_resolve): Declare. + * varasm.c (assemble_name_resolve): New function. + (assemble_name): Use it. + * config/i386/i386.h (ASM_OUTPUT_SYMBOL_REF): Define. + 2020-01-22 Joseph Myers * doc/sourcebuild.texi (Texinfo Manuals, Front End): Refer to diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 977440638ab..943e9a5c783 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2258,6 +2258,31 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER]; #define ASM_OUTPUT_FUNCTION_LABEL(FILE, NAME, DECL) \ ix86_asm_output_function_label ((FILE), (NAME), (DECL)) +/* A C statement (sans semicolon) to output a reference to SYMBOL_REF SYM. + If not defined, assemble_name will be used to output the name of the + symbol. This macro may be used to modify the way a symbol is referenced + depending on information encoded by TARGET_ENCODE_SECTION_INFO. */ + +#ifndef ASM_OUTPUT_SYMBOL_REF +#define ASM_OUTPUT_SYMBOL_REF(FILE, SYM) \ + do { \ + const char *name \ + = assemble_name_resolve (XSTR (x, 0)); \ + /* In -masm=att wrap identifiers that start with $ \ + into parens. */ \ + if (ASSEMBLER_DIALECT == ASM_ATT \ + && name[0] == '$' \ + && user_label_prefix[0] == '\0') \ + { \ + fputc ('(', (FILE)); \ + assemble_name_raw ((FILE), name); \ + fputc (')', (FILE)); \ + } \ + else \ + assemble_name_raw ((FILE), name); \ + } while (0) +#endif + /* Under some conditions we need jump tables in the text section, because the assembler cannot handle label differences between sections. This is the case for x86_64 on Mach-O for example. */ diff --git a/gcc/output.h b/gcc/output.h index d8d54971eeb..eb253c50329 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -237,6 +237,12 @@ extern void assemble_label (FILE *, const char *); addition of an underscore). */ extern void assemble_name_raw (FILE *, const char *); +/* Return NAME that should actually be emitted, looking through + transparent aliases. If NAME refers to an entity that is also + represented as a tree (like a function or variable), mark the entity + as referenced. */ +extern const char *assemble_name_resolve (const char *); + /* Like assemble_name_raw, but should be used when NAME might refer to an entity that is also represented as a tree (like a function or variable). If NAME does refer to such an entity, that entity will diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 552270d874c..a435fd1b12e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2020-01-22 Jakub Jelinek + PR target/91298 + * gcc.target/i386/pr91298-1.c: New test. + * gcc.target/i386/pr91298-2.c: New test. + * gfortran.dg/gomp/target-parallel1.f90: New test. * gfortran.dg/goacc/pr93329.f90: Enable commented out target parallel test. diff --git a/gcc/testsuite/gcc.target/i386/pr91298-1.c b/gcc/testsuite/gcc.target/i386/pr91298-1.c new file mode 100644 index 00000000000..45ef553fcf1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91298-1.c @@ -0,0 +1,14 @@ +/* PR target/91298 */ +/* { dg-do assemble } */ +/* { dg-options "-O2 -g -fdollars-in-identifiers" } */ + +int $a[18]; +int *foo (void) { return &$a[0]; } +int *bar (int x) { return &$a[x]; } +int baz (void) { return $a[0]; } +int qux (void) { return $a[4]; } +int $quux (void) { return 1; } +int corge (void) { return $quux (); } +int grault (void) { return $quux () + 1; } +typedef int (*fn) (void); +fn foobar (void) { return $quux; } diff --git a/gcc/testsuite/gcc.target/i386/pr91298-2.c b/gcc/testsuite/gcc.target/i386/pr91298-2.c new file mode 100644 index 00000000000..20e47ab6c83 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91298-2.c @@ -0,0 +1,5 @@ +/* PR target/91298 */ +/* { dg-do assemble { target fpic } } */ +/* { dg-options "-O2 -g -fdollars-in-identifiers -fpic" } */ + +#include "pr91298-1.c" diff --git a/gcc/varasm.c b/gcc/varasm.c index 498c5ff9390..dc6da6c0b5b 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2589,20 +2589,16 @@ assemble_name_raw (FILE *file, const char *name) ASM_OUTPUT_LABELREF (file, name); } -/* Like assemble_name_raw, but should be used when NAME might refer to - an entity that is also represented as a tree (like a function or - variable). If NAME does refer to such an entity, that entity will - be marked as referenced. */ - -void -assemble_name (FILE *file, const char *name) +/* Return NAME that should actually be emitted, looking through + transparent aliases. If NAME refers to an entity that is also + represented as a tree (like a function or variable), mark the entity + as referenced. */ +const char * +assemble_name_resolve (const char *name) { - const char *real_name; - tree id; + const char *real_name = targetm.strip_name_encoding (name); + tree id = maybe_get_identifier (real_name); - real_name = targetm.strip_name_encoding (name); - - id = maybe_get_identifier (real_name); if (id) { tree id_orig = id; @@ -2614,7 +2610,18 @@ assemble_name (FILE *file, const char *name) gcc_assert (! TREE_CHAIN (id)); } - assemble_name_raw (file, name); + return name; +} + +/* Like assemble_name_raw, but should be used when NAME might refer to + an entity that is also represented as a tree (like a function or + variable). If NAME does refer to such an entity, that entity will + be marked as referenced. */ + +void +assemble_name (FILE *file, const char *name) +{ + assemble_name_raw (file, assemble_name_resolve (name)); } /* Allocate SIZE bytes writable static space with a gensym name -- 2.30.2