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  <jakub@redhat.com>

	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.
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6048a8f..1d62d16 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
 2020-01-22  Jakub Jelinek  <jakub@redhat.com>
 
+	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  Jakub Jelinek  <jakub@redhat.com>
+
 	Backported from mainline
 	2020-01-21  Jakub Jelinek  <jakub@redhat.com>
 
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 934352d..95e1733 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2205,6 +2205,31 @@
 #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 835d635..e4017bb 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -236,6 +236,12 @@
    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 d0d8279..bebe9a75 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
 2020-01-22  Jakub Jelinek  <jakub@redhat.com>
 
+	PR target/91298
+	* gcc.target/i386/pr91298-1.c: New test.
+	* gcc.target/i386/pr91298-2.c: New test.
+
+2020-01-22  Jakub Jelinek  <jakub@redhat.com>
+
 	* 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 0000000..45ef553
--- /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 0000000..20e47ab
--- /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 cb43248..8f006dc 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -2585,20 +2585,16 @@
     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;
@@ -2610,7 +2606,18 @@
       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