[nvptx] Replace dots in function names
authorTom de Vries <tdevries@suse.de>
Sat, 10 Oct 2020 15:22:01 +0000 (17:22 +0200)
committerTom de Vries <tdevries@suse.de>
Sat, 10 Oct 2020 21:34:24 +0000 (23:34 +0200)
When function splitting clones a function sinf in the host compiler, the clone
is callled sinf.part.0.  However, ptx does not allows dots in identifiers, so
we run into:
...
ptxas test.o, line 23; fatal   : Parsing error near '.part': syntax error
ptxas fatal   : Ptx assembly aborted due to errors
nvptx-as: ptxas returned 255 exit status
...

Rename such functions by replacing the dots with dollar signs.

Tested check-gcc on nvptx.

Tested libgomp on x86_64-linux with nvptx accelerator.

gcc/ChangeLog:

2020-10-10  Tom de Vries  <tdevries@suse.de>

PR target/97318
* config/nvptx/nvptx.c (nvptx_replace_dot): New function.
(write_fn_proto, write_fn_proto_from_insn, nvptx_output_call_insn):
Use nvptx_replace_dot.

gcc/config/nvptx/nvptx.c

index 0c1d6d112ec89e5dcd1e5328081cda66f2b994ed..17349475fff05b319f418e5b25e6ec75df09df26 100644 (file)
@@ -368,6 +368,22 @@ nvptx_name_replacement (const char *name)
   return name;
 }
 
+/* Return NULL if NAME contains no dot.  Otherwise return a copy of NAME
+   with the dots replaced with dollar signs.  */
+
+static char *
+nvptx_replace_dot (const char *name)
+{
+  if (strchr (name, '.') == NULL)
+    return NULL;
+
+  char *p = xstrdup (name);
+  for (size_t i = 0; i < strlen (p); ++i)
+    if (p[i] == '.')
+      p[i] = '$';
+  return p;
+}
+
 /* If MODE should be treated as two registers of an inner mode, return
    that inner mode.  Otherwise return VOIDmode.  */
 
@@ -926,7 +942,16 @@ static void
 write_fn_proto (std::stringstream &s, bool is_defn,
                const char *name, const_tree decl)
 {
-  name = nvptx_name_replacement (name);
+  const char *replacement = nvptx_name_replacement (name);
+  char *replaced_dots = NULL;
+  if (replacement != name)
+    name = replacement;
+  else
+    {
+      replaced_dots = nvptx_replace_dot (name);
+      if (replaced_dots)
+       name = replaced_dots;
+    }
   if (name[0] == '*')
     name++;
 
@@ -935,6 +960,9 @@ write_fn_proto (std::stringstream &s, bool is_defn,
     write_fn_proto_1 (s, false, name, decl);
 
   write_fn_proto_1 (s, is_defn, name, decl);
+
+  if (replaced_dots)
+    XDELETE (replaced_dots);
 }
 
 /* Construct a function declaration from a call insn.  This can be
@@ -946,6 +974,8 @@ static void
 write_fn_proto_from_insn (std::stringstream &s, const char *name,
                          rtx result, rtx pat)
 {
+  char *replaced_dots = NULL;
+
   if (!name)
     {
       s << "\t.callprototype ";
@@ -953,7 +983,15 @@ write_fn_proto_from_insn (std::stringstream &s, const char *name,
     }
   else
     {
-      name = nvptx_name_replacement (name);
+      const char *replacement = nvptx_name_replacement (name);
+      if (replacement != name)
+       name = replacement;
+      else
+       {
+         replaced_dots = nvptx_replace_dot (name);
+         if (replaced_dots)
+           name = replaced_dots;
+       }
       write_fn_marker (s, false, true, name);
       s << "\t.extern .func ";
     }
@@ -962,6 +1000,8 @@ write_fn_proto_from_insn (std::stringstream &s, const char *name,
     write_return_mode (s, true, GET_MODE (result));
 
   s << name;
+  if (replaced_dots)
+    XDELETE (replaced_dots);
 
   int arg_end = XVECLEN (pat, 0);
   for (int i = 1; i < arg_end; i++)
@@ -2467,9 +2507,20 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee)
   
   if (decl)
     {
+      char *replaced_dots = NULL;
       const char *name = get_fnname_from_decl (decl);
-      name = nvptx_name_replacement (name);
+      const char *replacement = nvptx_name_replacement (name);
+      if (replacement != name)
+       name = replacement;
+      else
+       {
+         replaced_dots = nvptx_replace_dot (name);
+         if (replaced_dots)
+           name = replaced_dots;
+       }
       assemble_name (asm_out_file, name);
+      if (replaced_dots)
+       XDELETE (replaced_dots);
     }
   else
     output_address (VOIDmode, callee);