public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>, edk2-devel@lists.01.org
Subject: Re: [PATCH] EmbeddedPkg/GdbSerialLib: avoid left shift of negative quantity
Date: Tue, 19 Jun 2018 14:51:41 +0200	[thread overview]
Message-ID: <6e536d26-a1bb-52f2-ceca-8b39e35fe5ce@redhat.com> (raw)
In-Reply-To: <20180619095411.52siakmtbfokc6mu@bivouac.eciton.net>

On 06/19/18 11:54, Leif Lindholm wrote:
> On Tue, Jun 19, 2018 at 12:51:49AM +0200, Laszlo Ersek wrote:
>> On 06/18/18 23:57, Leif Lindholm wrote:
>>> On Mon, Jun 18, 2018 at 10:49:18PM +0200, Ard Biesheuvel wrote:
>>>> Clang complains about left shifting a negative value being undefined.
>>>
>>> As well it should.
>>>
>>>>   EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.c:151:30:
>>>>   error: shifting a negative signed value is undefined [-Werror,-Wshift-negative-value]
>>>>   OutputData = (UINT8)((~DLAB<<7)|((BreakSet<<6)|((Parity<<3)|((StopBits<<2)| Data))));
>>>>
>>>> Redefine all bit pattern constants as unsigned to work around this.
>>>
>>> So, I'm totally OK with this and
>>> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
>>> but ...
>>> would it be worth fixing up BIT0-31 in Base.h and use those?
>>
>> If we started with the BITxx macros now, I'd agree. Given the current
>> tree, I don't :) I've made an argument against the suggestion earlier:
>>
>>   UINT64 Value64;
>>
>>   Value64 = ~0x1;
>>   Value64 = ~0x1U;
>>
>> The two assignments produce different results.
>>
>> In the first case, the integer constant 0x1 has type "int". Our C
>> language implementation uses, for type "int", two's complement
>> representation, 1 sign bit, 31 value bits, and no padding bits. So after
>> the bitwise complement, we get 0x1111_1111_1111_1110, also with type
>> int, and with value (-2). Taking UINT64 for "unsigned long int" or
>> "unsigned long long int", after the conversion implied by the assignment
>> we get ((UINT64_MAX + 1) + (-2)), aka (UINT64_MAX - 1).
> 
> Err, if by UINT64_MAX + 1 you mean 0,

No, I don't.

> as a way of introducing the
> second part, I'm with you. Otherwise I think I need to go back to
> school.

I really meant (UINT64_MAX + 1) as the mathematical integer
18,446,744,073,709,551,616; without the modular wrap-around that occurs
in C. The modular wrap-around of C is defined in terms of the
mathematical values. This is how the ISO C99 standard defines the behavior:

------
6.3.1.3 Signed and unsigned integers

1 When a value with integer type is converted to another integer type
  other than _Bool, if the value can be represented by the new type, it
  is unchanged.

2 Otherwise, if the new type is unsigned, the value is converted by
  repeatedly adding or subtracting one more than the maximum value that
  can be represented in the new type until the value is in the range of
  the new type. [footnote 49]

3 Otherwise, the new type is signed and the value cannot be represented
  in it; either the result is implementation-defined or an
  implementation-defined signal is raised.

[footnote 49] The rules describe arithmetic on the mathematical value,
not the value of a given type of expression.
------

Therefore we really have (18,446,744,073,709,551,616 + (-2)) in the
above reasoning.

> 
>> In the second case, the constant 0x1U has type "unsigned int". After the
>> bitwise complement, we get (UINT32_MAX - 1), also of type "unsigned
>> int". Taking UINT64 for "unsigned long int" or "unsigned long long int",
>> after the conversion implied by assignment we get the exact same value,
>> (UINT32_MAX - 1).
> 
> But these examples make it look like the differences are an
> unobservable internal side effect. That's not the case.

Hm, sorry, I don't understand. My point was that the difference was
extremely observable, because in the first assignment, we end up with
value 18,446,744,073,709,551,614; in the second, we end up with
4,294,967,294.

Perhaps my expression "exact same value" was misleading. There I
referred to 6.3.1.3p1, which I've now quoted above as well -- I meant
that converting 4,294,967,294 from "unsigned int" to either of "unsigned
long int" or "unsigned long long int" didn't change the value.

Thanks!
Laszlo


  reply	other threads:[~2018-06-19 12:51 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-18 20:49 [PATCH] EmbeddedPkg/GdbSerialLib: avoid left shift of negative quantity Ard Biesheuvel
2018-06-18 21:57 ` Leif Lindholm
2018-06-18 22:07   ` Ard Biesheuvel
2018-06-18 22:51   ` Laszlo Ersek
2018-06-19  6:37     ` Ard Biesheuvel
2018-06-19  9:54     ` Leif Lindholm
2018-06-19 12:51       ` Laszlo Ersek [this message]
2018-06-19 13:06         ` Leif Lindholm

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6e536d26-a1bb-52f2-ceca-8b39e35fe5ce@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox