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 (©->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 = ©->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