Hi All,

The following patch has been bootstrapped and regtested on powerpc64le-linux.

After r12-5752-gd08236359eb229, a new bif infrastructure was introduced
which stopped using opaque vector types (e.g. opaque_V4SI_type_node)
for overloaded built-in functions, which led to incorrect and
misleading diagnostics when argument types didn’t exactly match.

This patch reinstates the opaque overload variant for entries with
multiple arguments where at least one is a vector, inserting it
at the beginning of each stanza. This helps recover the intended
fallback behavior and ensures clearer, type-generic error reporting.

2025-05-23  Kishan Parmar  <kis...@linux.ibm.com>

gcc:
        PR target/104930
        * config/rs6000/rs6000-c.cc (altivec_resolve_overloaded_builtin):
        Skip the first overload entry during iteration if it uses opaque type
        parameters.
        * config/rs6000/rs6000-gen-builtins.cc
        (maybe_generate_opaque_variant): New function.
        (parse_first_ovld_entry): New function.
        (parse_ovld_stanza): call parse_first_ovld_entry.
---
 gcc/config/rs6000/rs6000-c.cc            |   9 +-
 gcc/config/rs6000/rs6000-gen-builtins.cc | 180 ++++++++++++++++++++++-
 2 files changed, 187 insertions(+), 2 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc
index d3b0a566821..6217d585b40 100644
--- a/gcc/config/rs6000/rs6000-c.cc
+++ b/gcc/config/rs6000/rs6000-c.cc
@@ -1972,7 +1972,14 @@ altivec_resolve_overloaded_builtin (location_t loc, tree 
fndecl,
               arg_i++)
            {
              tree parmtype = TREE_VALUE (nextparm);
-             if (!rs6000_builtin_type_compatible (types[arg_i], parmtype))
+             /* Since we only need opaque vector type for the default
+                prototype which is the same as the first instance, we
+                only expect to see it in the first instance.  */
+             gcc_assert (instance == 
rs6000_overload_info[adj_fcode].first_instance
+                         || parmtype != opaque_V4SI_type_node);
+             if ((instance == rs6000_overload_info[adj_fcode].first_instance
+                  && parmtype == opaque_V4SI_type_node)
+                 || !rs6000_builtin_type_compatible (types[arg_i], parmtype))
                {
                  mismatch = true;
                  break;
diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc 
b/gcc/config/rs6000/rs6000-gen-builtins.cc
index f77087e0452..d442b93138e 100644
--- a/gcc/config/rs6000/rs6000-gen-builtins.cc
+++ b/gcc/config/rs6000/rs6000-gen-builtins.cc
@@ -353,6 +353,7 @@ struct typeinfo
   char isunsigned;
   char isbool;
   char ispixel;
+  char isopaque;
   char ispointer;
   basetype base;
   restriction restr;
@@ -579,6 +580,7 @@ static typemap type_map[] =
     { "v4sf",          "V4SF" },
     { "v4si",          "V4SI" },
     { "v8hi",          "V8HI" },
+    { "vop4si",        "opaque_V4SI" },
     { "vp8hi",         "pixel_V8HI" },
   };
 
@@ -1058,6 +1060,7 @@ match_type (typeinfo *typedata, int voidok)
        vd      vector double
        v256    __vector_pair
        v512    __vector_quad
+       vop     vector opaque
 
      For simplicity, We don't support "short int" and "long long int".
      We don't currently support a <basetype> of "_Float16".  "signed"
@@ -1496,6 +1499,12 @@ complete_vector_type (typeinfo *typeptr, char *buf, int 
*bufi)
       *bufi += 4;
       return;
     }
+  else if (typeptr->isopaque)
+    {
+      memcpy (&buf[*bufi], "op4si", 5);
+      *bufi += 5;
+      return;
+    }
   switch (typeptr->base)
     {
     case BT_CHAR:
@@ -1661,7 +1670,8 @@ construct_fntype_id (prototype *protoptr)
          buf[bufi++] = '_';
          if (argptr->info.isconst
              && argptr->info.base == BT_INT
-             && !argptr->info.ispointer)
+             && !argptr->info.ispointer
+             && !argptr->info.isopaque)
            {
              buf[bufi++] = 'c';
              buf[bufi++] = 'i';
@@ -1969,6 +1979,168 @@ create_bif_order (void)
   rbt_inorder_callback (&bifo_rbt, bifo_rbt.rbt_root, set_bif_order);
 }
 
+/* Attempt to generate an opaque variant if needed and valid.  */
+static void
+maybe_generate_opaque_variant (ovlddata* entry)
+{
+  /* If no vector arg, no need to create opaque variant.  */
+  bool has_vector_arg = false;
+  for (typelist* arg = entry->proto.args; arg; arg = arg->next)
+    {
+      if (arg->info.isvector)
+       {
+         has_vector_arg = true;
+         break;
+       }
+    }
+
+  if (!has_vector_arg || entry->proto.nargs <= 1)
+    return;
+
+  /* Construct the opaque variant.  */
+  ovlddata* opaque_entry = &ovlds[curr_ovld];
+  memcpy (opaque_entry, entry, sizeof (*entry));
+
+  /* Deep-copy and override vector args.  */
+  typelist** dst = &opaque_entry->proto.args;
+  for (typelist* src = entry->proto.args; src; src = src->next)
+    {
+      typelist* copy = (typelist*) malloc (sizeof (typelist));
+
+      if (src->info.isvector)
+       {
+         memset (&copy->info, 0, sizeof (typeinfo));
+         copy->info.isconst = src->info.isconst;
+         copy->info.isvector = 1;
+         copy->info.issigned = 1;
+         copy->info.isopaque = 1;
+         copy->info.base = BT_INT;
+       }
+      else
+       {
+         memcpy (copy, src, sizeof (typelist));
+       }
+
+      *dst = copy;
+      dst = &copy->next;
+    }
+  *dst = NULL;
+
+  /* Rewrite return type if vector.  */
+  if (entry->proto.rettype.isvector)
+    {
+      memset (&opaque_entry->proto.rettype, 0, sizeof (typeinfo));
+      opaque_entry->proto.rettype.isvector = 1;
+      opaque_entry->proto.rettype.issigned = 1;
+      opaque_entry->proto.rettype.isopaque = 1;
+      opaque_entry->proto.rettype.base = BT_INT;
+    }
+
+  /* Generate unique overload ID.  */
+  const char* base_id = entry->ovld_id_name;
+  size_t id_len = strlen (base_id);
+  const char* suffix = strchr (base_id, '_') ? "_VOP" : "__VOP";
+  char* new_id = (char*) malloc (id_len + strlen (suffix) + 1);
+  memset (new_id, 0, id_len + strlen (suffix) + 1);
+
+  strcpy (new_id, base_id);
+  strcat (new_id, suffix);
+
+  opaque_entry->ovld_id_name = new_id;
+  opaque_entry->fndecl = construct_fntype_id (&opaque_entry->proto);
+
+  curr_ovld = num_ovlds++;
+}
+
+/* Parse the first entry in the stanza.  */
+static parse_codes
+parse_first_ovld_entry (void)
+{
+  pos = 0;
+  consume_whitespace ();
+
+  if (linebuf[pos] == '[')
+    return PC_EOSTANZA;
+
+  if (num_ovlds >= MAXOVLDS - 1)
+    {
+      diag (pos, "too many overloads.\n");
+      return PC_PARSEFAIL;
+    }
+
+  ovlddata ovld_entry;
+  memset (&ovld_entry, 0, sizeof (ovlddata));
+  curr_ovld = num_ovlds++;
+  ovld_entry.stanza = curr_ovld_stanza;
+
+  if (parse_prototype (&ovld_entry.proto) == PC_PARSEFAIL)
+    return PC_PARSEFAIL;
+
+  if (ovld_entry.proto.nargs > max_ovld_args)
+    max_ovld_args = ovld_entry.proto.nargs;
+
+  if (!advance_line (ovld_file))
+    {
+      diag (0, "unexpected EOF.\n");
+      return PC_EOFILE;
+    }
+
+  pos = 0;
+  consume_whitespace ();
+  int oldpos = pos;
+
+  char* id = match_identifier ();
+  if (!id)
+    {
+      diag (pos, "missing overload id.\n");
+      return PC_PARSEFAIL;
+    }
+
+  ovld_entry.bif_id_name = id;
+  ovld_entry.ovld_id_name = id;
+
+#ifdef DEBUG
+  diag (pos, "ID name is '%s'.\n", id);
+#endif
+
+  if (!rbt_find (&bif_rbt, id))
+    {
+      diag (pos, "builtin ID '%s' not found in bif file.\n", id);
+      return PC_PARSEFAIL;
+    }
+
+  consume_whitespace ();
+  if (linebuf[pos] != '\n')
+    {
+      char* alt_id = match_identifier ();
+      if (alt_id)
+       ovld_entry.ovld_id_name = alt_id;
+      consume_whitespace ();
+    }
+
+  /* Attempt to generate opaque variant, if eligible.  */
+  maybe_generate_opaque_variant (&ovld_entry);
+
+  /* Build a function type descriptor identifier from the return type
+     and argument types, and store it if it does not already exist.  */
+  ovld_entry.fndecl = construct_fntype_id (&ovld_entry.proto);
+
+  if (!rbt_insert (&ovld_rbt, ovld_entry.ovld_id_name))
+    {
+      diag (oldpos, "duplicate overload ID '%s'.\n", ovld_entry.ovld_id_name);
+      return PC_PARSEFAIL;
+    }
+
+  if (linebuf[pos] != '\n')
+    {
+      diag (pos, "garbage at end of line.\n");
+      return PC_PARSEFAIL;
+    }
+
+  memcpy (&ovlds[curr_ovld], &ovld_entry, sizeof ovld_entry);
+  return PC_OK;
+}
+
 /* Parse one two-line entry in the overload file.  */
 static parse_codes
 parse_ovld_entry (void)
@@ -2155,6 +2327,12 @@ parse_ovld_stanza (void)
 
   parse_codes result = PC_OK;
 
+  if (!advance_line(ovld_file))
+    return PC_EOFILE;
+  result = parse_first_ovld_entry();
+  if (result == PC_EOFILE || result == PC_PARSEFAIL)
+    return result;
+
   while (result != PC_EOSTANZA)
     {
       if (!advance_line (ovld_file))
-- 
2.43.5

Reply via email to