On 08/20/2018 08:52 AM, Bernd Edlinger wrote:
> On 08/20/18 16:16, Jeff Law wrote:
>> On 08/20/2018 07:28 AM, Richard Biener wrote:
>>> 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!)
>> Given this is keeping my tester from running on alpha, I'm going to make
>> the adjustment to Bernd's patch and commit it momentarily.
>>
> 
> Hi Jeff,
> 
> is there a reason why this gcc_assert should not be a gcc_checking_assert?
> 
> @@ -7046,6 +7047,7 @@
>       }
>   
>         /* Store the value in the bitfield.  */
> +      gcc_assert (known_ge (bitpos, 0));
>         store_bit_field (target, bitsize, bitpos,
>                      bitregion_start, bitregion_end,
>                      mode, temp, reverse);
Nope.  I must have missed it.  Go ahead and commit it as obvious.

jeff

Reply via email to