On Mon, 20 Aug 2018, Bernd Edlinger wrote:

> On 08/20/18 12:41, Richard Biener wrote:
> > On Sun, 19 Aug 2018, Bernd Edlinger wrote:
> > 
> >> Hi!
> >>
> >>
> >> This fixes a wrong code issue in expand_expr_real_1 which happens because
> >> a negative bitpos is actually able to reach extract_bit_field which
> >> does all computations with poly_uint64, thus the offset 0x1ffffffffffffff0.
> >>
> >> To avoid that I propose to use Jakub's r204444 patch from the 
> >> expand_assignment
> >> also in the expand_expr_real_1.
> >>
> >> This is a rather unlikely thing to happen, as there are lots of checks 
> >> that are
> >> of course all target dependent between the get_inner_reference and the
> >> actual extract_bit_field call, and all other code paths may or may not 
> >> have a problem
> >> with negative bit offsets.  Most don't have a problem, but the bitpos 
> >> needs to be
> >> folded into offset before it is used, therefore it is necessary to handle 
> >> the negative
> >> bitpos very far away from the extract_bit_field call.  Doing that later is 
> >> IMHO not
> >> possible.
> >>
> >> The fix in CONSTANT_ADDRESS_P is actually unrelated, and I only spotted it 
> >> because
> >> this macro is used in alpha_legitimize_address which is of course what one 
> >> looks
> >> at first if something like that happens.
> >>
> >> I think even with this bogus offset it should not have caused a linker 
> >> error, so there
> >> is probably a second problem in the *movdi code pattern of the alpha.md, 
> >> because it
> >> should be split into instructions that don't cause a link error.
> >>
> >> Once the target is fixed to split the impossible assembler instruction, 
> >> the test case
> >> will probably no longer be able to detect the pattern in the assembly.
> >>
> >> Therefore the test case looks both at the assembler output and the expand 
> >> rtl dump
> >> to spot the bogus offset.  I only check the first 12 digits of the bogus 
> >> constant,
> >> because it is actually dependent on the target configuration:
> >>
> >> I built first a cross-compiler without binutils, and it did used a 
> >> slightly different
> >> offset of 0x2000000000000000, (configured with: --target=alpha-linux-gnu 
> >> --enable-languages=c
> >> --disable-libgcc --disable-libssp --disable-libquadmath --disable-libgomp 
> >> --disable-libatomic)
> >> when the binutils are installed at where --prefix points, the offset is 
> >> 0x1ffffffffffffff0.
> >>
> >> Regarding the alpha target, I could not do more than build a cross 
> >> compiler and run
> >> make check-gcc-c RUNTESTFLAGS="alpha.exp=pr86984.c".
> >>
> >>
> >> Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
> >> Is it OK for trunk?
> > 
> > Hmm, I don't remember why we are inconsistent in get_inner_reference
> > with respect to negative bitpos.  I think we should be consistent
> > here and may not be only by accident?  That is, does
> > 
> > diff --git a/gcc/expr.c b/gcc/expr.c
> > index c071be67783..9dc78587136 100644
> > --- a/gcc/expr.c
> > +++ b/gcc/expr.c
> > @@ -7272,7 +7272,7 @@ get_inner_reference (tree exp, poly_int64_pod
> > *pbitsize,
> >                                        TYPE_PRECISION (sizetype));
> >         tem <<= LOG2_BITS_PER_UNIT;
> >         tem += bit_offset;
> > -      if (tem.to_shwi (pbitpos))
> > +      if (tem.to_shwi (pbitpos) && !maybe_lt (*pbitpos, 0))
> >          *poffset = offset = NULL_TREE;
> >       }
> >   
> > fix the issue?
> > 
> 
> Yes, at first sight, however, I was involved at PR 58970,
> see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58970
> 
> and I proposed a similar patch, which was objected by Jakub:
> 
> see comment #25 of PR 58970:
> "Jakub Jelinek 2013-11-05 19:41:12 UTC
> 
> (In reply to Bernd Edlinger from comment #24)
> > Created attachment 31169 [details] 
> > https://gcc.gnu.org/bugzilla/attachment.cgi?id=31169
> > Another (better) attempt at fixing this ICE.
> > 
> > This avoids any negative bitpos from get_inner_reference.
> > These negative bitpos values are just _very_ dangerous all the
> > way down to expmed.c
> 
> I disagree that it is better, you are forgetting get_inner_reference has 
> other > 20 callers outside of expansion and there is no reason why negative 
> bitpos would be a problem in those cases."
> 
> So that is what Jakub said at that time, and with the
> suggested change in get_inner_reference,
> this part of the r204444 change would be effectively become superfluous:
> 
> @@ -4721,6 +4721,15 @@ expand_assignment (tree to, tree from, bool nontem
>         tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
>                                   &unsignedp, &volatilep, true);
>   
> +      /* Make sure bitpos is not negative, it can wreak havoc later.  */
> +      if (bitpos < 0)
> +       {
> +         gcc_assert (offset == NULL_TREE);
> +         offset = size_int (bitpos >> (BITS_PER_UNIT == 8
> +                                       ? 3 : exact_log2 (BITS_PER_UNIT)));
> +         bitpos &= BITS_PER_UNIT - 1;
> +       }
> +
>         if (TREE_CODE (to) == COMPONENT_REF
>            && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
>          get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, 
> &offset);
> 
> and should be reverted.  I did not really like it then, but I'd respect 
> Jakub's advice.

Hmm.  I agree that there are other callers and yes, replicating Jakubs
fix is certainly more safe.  Still it's somewhat inconsistent in that
get_inner_reference already has code to mitigate negative bitpos, but
only in the case 'offset' wasn't just an INTEGER_CST ...

So your patch is OK (please change the gcc_asserts to 
gcc_checking_asserts though to avoid ICEing for release compilers).

We still might want to revisit get_inner_reference (and make its
bitpos unsigned then!)

Richard.

> 
> Bernd.
> 
> 
> 
> > Richard.
> > 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to