Hello, Please ignore this patch as, v3 of the patch has been sent. https://patchwork.sourceware.org/project/gcc/patch/[email protected]/ This patch was also missing the correct patch version in the subject header. it should have been marked as v2.
Thanks. Kishan On 30/09/26 7:27 pm, Kishan Parmar wrote: > Hello All, > > Changes from V1: > - Dropped rs6000-c.cc change. Resolver needs no modification > since v2 does not have opaque instance entries. > - Dropped isopaque field on typeinfo and the corresponding > complete_vector_type() change; opaque string is now built in > a self-contained helper make_opaque_fndecl(). > - Dropped parse_first_ovld_entry() and > maybe_generate_opaque_variant(). v2 does not insert synthetic > ovlddata entries into the ovlds[] array. > - Removed the _VOP / __VOP enum entries and the wrong bifids > they introduced. > > Thank You, > Kishan > > Before r12-5752 (gd08236359eb229), the public overload declaration for > overloaded PowerPC built-in functions used opaque_V4SI_type_node for all > vector argument and return types. The C front end's compatibility check > (vector_types_convertible_p in c-family/c-common.cc) has an early-exit > for TYPE_VECTOR_OPAQUE types, so mis-typed vector arguments were passed > silently at that stage and left for altivec_resolve_overloaded_builtin() > to diagnose properly. > > r12-5752 switched the new built-in generator to register each overload's > public declaration using the concrete vector type of the first instance > prototype. This reactivated the front end's early vector-type > check, causing a spurious "use -flax-vector-conversions to permit > conversions between vectors with differing element types" > note before the overload resolver ran, obscuring the real diagnostic > such as "too few arguments". > > Fix this in rs6000-gen-builtins.cc by restoring the opaque prototype for > the public overload declaration whenever the overload has by-value > vector arguments or a by-value vector return type. A new "vop4si" > entry is added to type_map[], mapping to opaque_V4SI_type_node, and a > new helper make_opaque_fndecl() builds the function-type identifier > string with every by-value vector position replaced by "vop4si". > Vector-pointer arguments (e.g. vsc *) remain as it was, because > front-end's pointer-type check does not emit the > -flax-vector-conversions note anyway. > > 2026-09-30 Kishan Parmar <[email protected]> > > gcc/ChangeLog: > * config/rs6000/rs6000-gen-builtins.cc (type_map): Add "vop4si" > entry mapping to opaque_V4SI. > (make_opaque_fndecl): New function. Build a function-type > identifier string like construct_fntype_id() but with every > by-value vector position replaced by "vop4si". > (proto_has_vector_arg): New function. Return true if a > prototype has at least one vector argument. > (write_init_ovld_table): Introduce reg_fndecl. Use > make_opaque_fndecl() for the public overload declaration when > the stanza has vector arguments, otherwise use the first > instance's concrete fndecl as before. Update the generated > comment in the output file. Free reg_fndecl after use when > it was malloc'd by make_opaque_fndecl(). > (write_init_file): Add pre-pass loop to call > make_opaque_fndecl() for every stanza with vector arguments > before the fntype_rbt inorder walk, so that the opaque type > strings are declared before they are used. > > gcc/testsuite/ChangeLog: > * gcc.target/powerpc/pr104930.c: New test. > --- > gcc/config/rs6000/rs6000-gen-builtins.cc | 179 ++++++++++++++++++++++- > 1 file changed, 171 insertions(+), 8 deletions(-) > > diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc > b/gcc/config/rs6000/rs6000-gen-builtins.cc > index 08068ba78fd..76dd33bbb90 100644 > --- a/gcc/config/rs6000/rs6000-gen-builtins.cc > +++ b/gcc/config/rs6000/rs6000-gen-builtins.cc > @@ -600,6 +600,7 @@ static typemap type_map[] = > { "v4sf", "V4SF" }, > { "v4si", "V4SI" }, > { "v8hi", "V8HI" }, > + { "vop4si", "opaque_V4SI" }, > { "vp8hi", "pixel_V8HI" }, > }; > > @@ -2772,15 +2773,145 @@ write_init_bif_table (void) > } > } > > +/* Build a function-type identifier string like construct_fntype_id() does, > + but replace every by-value vector position with "vop4si" (opaque_V4SI). > + This string is used as the public overload declaration so the C front end > + does not complain about vector type mismatches before the overload > resolver > + runs (PR target/104930). > + > + Rules for each position: > + - by-value vector (isvector=1, ispointer=0): use "vop4si". > + - vector pointer (isvector=1, ispointer=1): As it was, e.g. "pv16qi". > + Pointer arguments never trigger the -flax-vector-conversions note > anyway. > + - everything else: same as construct_fntype_id(), no change. */ > + > +static char * > +make_opaque_fndecl (prototype *protoptr) > +{ > + /* Use the same size estimate as construct_fntype_id. "vop4si" is 6 chars, > + same worst-case length as "bv16qi", within the 9-char per-type budget. > */ > + int len = protoptr->nargs ? (protoptr->nargs + 1) * 9 + 6 : 17; > + char *buf = (char *) malloc (len); > + int bufi = 0; > + > + // Return type > + if (protoptr->rettype.ispointer) > + buf[bufi++] = 'p'; > + > + if (protoptr->rettype.isvoid) > + buf[bufi++] = 'v'; > + else if (protoptr->rettype.isvector && !protoptr->rettype.ispointer) > + { > + memcpy (&buf[bufi], "vop4si", 6); > + bufi += 6; > + } > + else > + { > + /* Scalar return, or vector-pointer return (e.g. vsc *): emit > + the concrete type, identical to construct_fntype_id(). */ > + if (protoptr->rettype.isunsigned) > + buf[bufi++] = 'u'; > + if (protoptr->rettype.isvector) > + complete_vector_type (&protoptr->rettype, buf, &bufi); > + else > + complete_base_type (&protoptr->rettype, buf, &bufi); > + } > + > + memcpy (&buf[bufi], "_ftype", 6); > + bufi += 6; > + > + // Argument types > + if (!protoptr->nargs) > + { > + memcpy (&buf[bufi], "_v", 2); > + bufi += 2; > + } > + else > + { > + typelist *argptr = protoptr->args; > + for (int i = 0; i < protoptr->nargs; i++, argptr = argptr->next) > + { > + assert (argptr); > + buf[bufi++] = '_'; > + > + if (argptr->info.isvector && !argptr->info.ispointer) > + { > + memcpy (&buf[bufi], "vop4si", 6); > + bufi += 6; > + } > + else > + { > + /* Non-vector argument, or vector-pointer argument (e.g. vsc *, > + const vbc *): emit the concrete type, identical to > + construct_fntype_id(). */ > + if (argptr->info.isconst > + && argptr->info.base == BT_INT > + && !argptr->info.ispointer) > + { > + buf[bufi++] = 'c'; > + buf[bufi++] = 'i'; > + continue; > + } > + if (argptr->info.ispointer) > + { > + if (argptr->info.isvoid) > + { > + if (argptr->info.isconst) > + { > + memcpy (&buf[bufi], "pcvoid", 6); > + bufi += 6; > + continue; > + } > + else > + { > + buf[bufi++] = 'p'; > + buf[bufi++] = 'v'; > + continue; > + } > + } > + else > + buf[bufi++] = 'p'; > + } > + if (argptr->info.isunsigned) > + buf[bufi++] = 'u'; > + if (argptr->info.isvector) > + complete_vector_type (&argptr->info, buf, &bufi); > + else > + complete_base_type (&argptr->info, buf, &bufi); > + } > + } > + assert (!argptr); > + } > + > + buf[bufi] = '\0'; > + > + rbt_insert (&fntype_rbt, buf); > + > + return buf; > +} > + > +/* Return true if PROTOPTR has at least one vector argument. */ > +static bool > +proto_has_vector_arg (prototype *protoptr) > +{ > + for (typelist *arg = protoptr->args; arg; arg = arg->next) > + if (arg->info.isvector) > + return true; > + return false; > +} > + > /* Write code to initialize the overload table. */ > static void > write_init_ovld_table (void) > { > fprintf (init_file, " int base = RS6000_OVLD_NONE;\n\n"); > fprintf (init_file, > - " /* The fndecl for an overload is arbitrarily the first one\n" > - " for the overload. We sort out the real types when\n" > - " processing the overload in the gcc front end. */\n"); > + " /* The fndecl for the public overload declaration is an opaque-\n" > + " typed prototype when the overload has vector arguments. > This\n" > + " avoids a spurious -flax-vector-conversions note in the C/C++\n" > + " front end before altivec_resolve_overloaded_builtin() runs.\n" > + " See PR target/104930. For overloads without vector > arguments\n" > + " the first instance's concrete type is used, as before. */\n"); > > for (int i = 0; i <= curr_ovld; i++) > { > @@ -2794,16 +2925,33 @@ write_init_ovld_table (void) > ovld_stanza *stanza = &ovld_stanzas[ovlds[i].stanza]; > fprintf (init_file, "\n"); > > + /* If this stanza has vector arguments, register its public > + declaration with an opaque prototype so that the front end's > + early argument-type check does not fire before the overload > + resolver can inspect the actual argument types. Otherwise > + use the first instance's concrete fndecl, as before. > + make_opaque_fndecl() returns a malloc'd buffer, on duplicate > + the RBT did not take ownership so we must free it after use. */ > + char *reg_fndecl; > + bool free_reg_fndecl = false; > + if (proto_has_vector_arg (&ovlds[i].proto)) > + { > + reg_fndecl = make_opaque_fndecl (&ovlds[i].proto); > + free_reg_fndecl = true; > + } > + else > + reg_fndecl = ovlds[i].fndecl; > + > /* Check whether we have a "tf" token in this string, representing > a float128_type_node. It's possible that float128_type_node is > undefined (occurs for -maltivec -mno-vsx, for example), so we > must guard against that. */ > - int tf_found = strstr (ovlds[i].fndecl, "tf") != NULL; > + int tf_found = strstr (reg_fndecl, "tf") != NULL; > > /* Similarly, look for decimal float tokens. */ > - int dfp_found = (strstr (ovlds[i].fndecl, "sd") != NULL > - || strstr (ovlds[i].fndecl, "dd") != NULL > - || strstr (ovlds[i].fndecl, "td") != NULL); > + int dfp_found = (strstr (reg_fndecl, "sd") != NULL > + || strstr (reg_fndecl, "dd") != NULL > + || strstr (reg_fndecl, "td") != NULL); > > if (tf_found) > { > @@ -2824,7 +2972,7 @@ write_init_ovld_table (void) > stanza->intern_name); > fprintf (init_file, > " %s,\n", > - ovlds[i].fndecl); > + reg_fndecl); > fprintf (init_file, > " (int)RS6000_OVLD_%s," > " BUILT_IN_MD,\n", > @@ -2844,6 +2992,9 @@ write_init_ovld_table (void) > fprintf (init_file, > " = RS6000_INST_%s;\n\n", > ovlds[i].ovld_id_name); > + > + if (free_reg_fndecl) > + free (reg_fndecl); > } > } > } > @@ -2871,6 +3022,18 @@ write_init_file (void) > write_bif_static_init (); > write_ovld_static_init (); > > + /* We call make_opaque_fndecl() here first (before the RBT walk below) > + so that the opaque type strings land in fntype_rbt in time for > + write_fntype_init() to emit their tree-variable declarations. > + write_init_ovld_table() calls make_opaque_fndecl() a second time to > + get the string for fprintf,that second rbt_insert() is a no-op > + since the string is already in the tree. Two calls, but the second > + one is cheap and avoids storing extra pointers in ovld_stanzas. */ > + for (int i = 0; i <= curr_ovld; i++) > + if (i == 0 || ovlds[i].stanza != ovlds[i-1].stanza) > + if (proto_has_vector_arg (&ovlds[i].proto)) > + make_opaque_fndecl (&ovlds[i].proto); > + > /* The reason to pass pointers to the function instead of accessing > the rs6000_{{builtin,instance}_info_fntype,overload_info,builtin_decls} > arrays directly is to decrease size of the already large function and
