Message ID | 0105dcce-8dc7-efe8-97a6-9f3afe10d6ff@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | [v2] rs6000: ICE when using an MMA type as a function param or return value [PR96506] | expand |
Hi! On Wed, Aug 12, 2020 at 03:32:18PM -0500, Peter Bergner wrote: > --- a/gcc/config/rs6000/rs6000-call.c > +++ b/gcc/config/rs6000/rs6000-call.c > @@ -6444,8 +6444,26 @@ machine_mode > rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, > machine_mode mode, > int *punsignedp ATTRIBUTE_UNUSED, > - const_tree, int) > + const_tree, int for_return) > { > + /* Warning: this is a static local variable and not always NULL! */ > + static struct function *fn = NULL; It may be just me that always misses "static" on locals, heh. But please comment what this is *for*: to warn only once per function. You could choose a better variable name to say that, too. "struct function" is GTY, will this work this way, btw? So I am worried about that; other than that, this is just fine (if you tune the comment a bit). Thanks, Segher
On 8/12/20 8:00 PM, Segher Boessenkool wrote: > On Wed, Aug 12, 2020 at 03:32:18PM -0500, Peter Bergner wrote: >> --- a/gcc/config/rs6000/rs6000-call.c >> +++ b/gcc/config/rs6000/rs6000-call.c >> @@ -6444,8 +6444,26 @@ machine_mode >> rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, >> machine_mode mode, >> int *punsignedp ATTRIBUTE_UNUSED, >> - const_tree, int) >> + const_tree, int for_return) >> { >> + /* Warning: this is a static local variable and not always NULL! */ >> + static struct function *fn = NULL; > > It may be just me that always misses "static" on locals, heh. But > please comment what this is *for*: to warn only once per function. You > could choose a better variable name to say that, too. Ok, how about this comment then? @@ -6444,8 +6444,30 @@ machine_mode rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode, int *punsignedp ATTRIBUTE_UNUSED, - const_tree, int) + const_tree, int for_return) { + /* Warning: this is a static local variable and not always NULL! + This function is called multiple times for the same function + and return value. PREV_FUNC is used to keep track of the + first time we encounter a function's return value in order + to not report an error with that return value multiple times. */ + static struct function *prev_func = NULL; + + /* We do not allow MMA types being used as return values. Only report + the invalid return value usage the first time we encounter it. */ + if (for_return + && prev_func != cfun + && (mode == POImode || mode == PXImode)) + { + /* Record we have now handled function CFUN, so the next time we + are called, we do not re-report the same error. */ + prev_func = cfun; + if (TYPE_CANONICAL (type) != NULL_TREE) + type = TYPE_CANONICAL (type); + error ("invalid use of MMA type %qs as a function return value", + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + } + PROMOTE_MODE (mode, *punsignedp, type); return mode; Peter
On 8/12/20 8:59 PM, Peter Bergner wrote: > On 8/12/20 8:00 PM, Segher Boessenkool wrote: >> On Wed, Aug 12, 2020 at 03:32:18PM -0500, Peter Bergner wrote: > Ok, how about this comment then? > > @@ -6444,8 +6444,30 @@ machine_mode > rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, > machine_mode mode, > int *punsignedp ATTRIBUTE_UNUSED, > - const_tree, int) > + const_tree, int for_return) > { > + /* Warning: this is a static local variable and not always NULL! > + This function is called multiple times for the same function > + and return value. PREV_FUNC is used to keep track of the > + first time we encounter a function's return value in order > + to not report an error with that return value multiple times. */ > + static struct function *prev_func = NULL; Approved offline, so I pushed this to trunk. Thanks! Are we ok to backport this to GCC 10? If you don't want this trickery in GCC 10, we could just backport the param handling which doesn't use the trickery and leave the return value unhandled. Peter
On Thu, Aug 13, 2020 at 01:58:31PM -0500, Peter Bergner wrote: > On 8/12/20 8:59 PM, Peter Bergner wrote: > > On 8/12/20 8:00 PM, Segher Boessenkool wrote: > >> On Wed, Aug 12, 2020 at 03:32:18PM -0500, Peter Bergner wrote: > > Ok, how about this comment then? > > > > @@ -6444,8 +6444,30 @@ machine_mode > > rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, > > machine_mode mode, > > int *punsignedp ATTRIBUTE_UNUSED, > > - const_tree, int) > > + const_tree, int for_return) > > { > > + /* Warning: this is a static local variable and not always NULL! > > + This function is called multiple times for the same function > > + and return value. PREV_FUNC is used to keep track of the > > + first time we encounter a function's return value in order > > + to not report an error with that return value multiple times. */ > > + static struct function *prev_func = NULL; > > Approved offline, so I pushed this to trunk. Thanks! > > Are we ok to backport this to GCC 10? If you don't want this > trickery in GCC 10, we could just backport the param handling > which doesn't use the trickery and leave the return value > unhandled. It's okay for backporting as well. It's all kind of wrong, but it will in practice just work anyway: 1) struct function is GTY, and you don't mark the static variable here as root, so the thing it points into might have gone away; but we really only use the pointer here, we don't deref anything explicitly, so the generated program won't either (hopefully, etc.) 2) Similarly, some other struct function for another function may (in theory) be allocated at the same address when next we are called; that other function will then never get the warning. We'd need to store a flag in the struct function (or similarly) itself, to make things kosher. How do similar warnings elsewhere handle this? Anyway, okay for trunk and backports. Thanks! Segher
On 8/13/20 4:27 PM, Segher Boessenkool wrote:
> Anyway, okay for trunk and backports. Thanks!
Ok, I committed this to trunk and waited a few days and then
pushed this to GCC 10 release branch too. Thanks!
Peter
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index 189497efb45..869e4973a16 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -6444,8 +6444,26 @@ machine_mode rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode, int *punsignedp ATTRIBUTE_UNUSED, - const_tree, int) + const_tree, int for_return) { + /* Warning: this is a static local variable and not always NULL! */ + static struct function *fn = NULL; + + /* We do not allow MMA types being used as return values. Only report + the invalid return value usage the first time we encounter it. */ + if (for_return + && fn != cfun + && (mode == POImode || mode == PXImode)) + { + /* Record we have now handled function CFUN, so the next time we + are called, we do not re-report the same error. */ + fn = cfun; + if (TYPE_CANONICAL (type) != NULL_TREE) + type = TYPE_CANONICAL (type); + error ("invalid use of MMA type %qs as a function return value", + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + } + PROMOTE_MODE (mode, *punsignedp, type); return mode; @@ -7396,6 +7414,16 @@ rs6000_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) machine_mode elt_mode; int n_elts; + /* We do not allow MMA types being used as function arguments. */ + if (mode == POImode || mode == PXImode) + { + if (TYPE_CANONICAL (type) != NULL_TREE) + type = TYPE_CANONICAL (type); + error ("invalid use of MMA operand of type %qs as a function parameter", + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + return NULL_RTX; + } + /* Return a marker to indicate whether CR1 needs to set or clear the bit that V.4 uses to say fp args were passed in registers. Assume that we don't need the marker for software floating point, diff --git a/gcc/testsuite/gcc.target/powerpc/pr96506.c b/gcc/testsuite/gcc.target/powerpc/pr96506.c new file mode 100644 index 00000000000..b1b40c5a5c8 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr96506.c @@ -0,0 +1,66 @@ +/* PR target/96506 */ +/* { dg-do compile } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ + +extern void bar0(); +extern void bar1(); +extern void bar2(); +extern void bar3(); + +typedef __vector_pair vpair_t; +typedef __vector_quad vquad_t; + +/* Verify we flag errors on the following. */ + +void +foo0 (void) +{ + __vector_pair v; + bar0 (v); /* { dg-error "invalid use of MMA operand of type .__vector_pair. as a function parameter" } */ +} + +void +foo1 (void) +{ + vpair_t v; + bar1 (v); /* { dg-error "invalid use of MMA operand of type .__vector_pair. as a function parameter" } */ +} + +void +foo2 (void) +{ + __vector_quad v; + bar2 (v); /* { dg-error "invalid use of MMA operand of type .__vector_quad. as a function parameter" } */ +} + +void +foo3 (void) +{ + vquad_t v; + bar3 (v); /* { dg-error "invalid use of MMA operand of type .__vector_quad. as a function parameter" } */ +} + +__vector_pair +foo4 (__vector_pair *src) /* { dg-error "invalid use of MMA type .__vector_pair. as a function return value" } */ +{ + return *src; +} + +vpair_t +foo5 (vpair_t *src) /* { dg-error "invalid use of MMA type .__vector_pair. as a function return value" } */ +{ + return *src; +} + +__vector_quad +foo6 (__vector_quad *src) /* { dg-error "invalid use of MMA type .__vector_quad. as a function return value" } */ +{ + return *src; +} + +vquad_t +foo7 (vquad_t *src) /* { dg-error "invalid use of MMA type .__vector_quad. as a function return value" } */ +{ + return *src; +}