Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Kinney, Michael D
Hi Brian,

This is a good idea.  I will have to study it some more 
to figure out what the EBC versions of these macros would
map to.

Mike

> -Original Message-
> From: Brian J. Johnson [mailto:bjohn...@sgi.com]
> Sent: Tuesday, September 27, 2016 10:14 AM
> To: Andrew Fish ; Eugene Cohen 
> Cc: Kinney, Michael D ; Alexei Fedorov
> ; edk2-devel@lists.01.org ; 
> Laszlo
> Ersek 
> Subject: Re: [edk2] What is the right way to print a UINTN?
> 
> On 09/27/2016 11:47 AM, Andrew Fish wrote:
> >
> >> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene  wrote:
> >>
> >>> Printing UINTN with %x *or* with %d are equally bugs.
> >>>
> >>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
> >>> work most of the time).
> >>
> >> Feel free to file a Bugzilla on the extensive usage of this in
> >> edk2 [ducking and running]. :)
> >>
>  I'm envisioning having to create a slide in the future for UEFI
>  training about the proper use of UINTNs and describing "If you think
>  it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
>  about it" and it makes me squirm.
> >>>
> >>> It makes me squirm too. I think the slide should recommend the
> >>> casting
> >>> that I proposed. ;) "There is no conversion specifier dedicated to
> >>> UINTN; the portable way to print it is to cast it to UINT64, then print
> >>> it with %Lx."
> >>
> >> This is reasonable although I expect to get asked why a lot of the
> >> other code doesn't adhere to this recommendation.
> >>
> >
> > I think this is a historical artifact. The older version of %x in
> > the EDK (and early edk2) implied UINTN. We hit an issue with C
> > integer math resulting in an int and that seemed to bork some
> > toolchains. That is when things changed from UINTN to int. I guess
> > the cleanup was practical vs. pedantic.
> 
> Thanks for the historical context, Andrew.  It's interesting to hear,
> if very unfortunate.
> 
> I've written code in the past which uses a #defined value for the
> UINTN format character as a way to work around this issue without
> casting everything to 64 bits.  Something like:
> 
> // Format string for a naturally-sized unsigned integer
> #if defined (MDE_CPU_IA32)
> #define UINTN_FMT  "0x%08x"
> #elif defined (MDE_CPU_X64)
> #define UINTN_FMT  "0x%016lx"
> #elif ...
>...
> #endif
> 
> UINTN Val;
> Val = Foo ();
> DEBUG((DEBUG_INFO, "Value is " UINTN_FMT "\n", Val));
> 
> 
> I guess it's a matter of opinion if that's preferable to adding casts;
> in my particular situation, I had to print values with that particular
> format string in a lot of places, so it was convenient to #define it
> once.
> 
> >
> > Thanks,
> >
> > Andrew Fish
> >
> >> Thanks,
> >>
> >> Eugene
> >> ___
> >> edk2-devel mailing list
> >> edk2-devel@lists.01.org
> >> https://lists.01.org/mailman/listinfo/edk2-devel
> >
> > ___
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
> >
> 
> 
> --
> 
>   Brian J. Johnson
> 
> 
> 
>My statements are my own, are not authorized by SGI, and do not
>necessarily represent SGI's positions.
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Kinney, Michael D
Eugene,

I agree.  There are use cases for using UINTN so values can scale to CPU arch.

Casting those specific use cases from UINTN to UINT64 when used in a print call 
is likely the safest method.

There are many use case of UINTN where the value is limited to 32-bits, and
a typecast is not required.

The format specifier idea is interesting.  I need to lookup the ANSI C versions
of those.  Looks like they were introduced in C99.

Mike


> -Original Message-
> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Cohen, 
> Eugene
> Sent: Tuesday, September 27, 2016 12:29 PM
> To: Kinney, Michael D ; af...@apple.com
> Cc: Alexei Fedorov ; edk2-devel@lists.01.org  de...@ml01.01.org>; Laszlo Ersek 
> Subject: Re: [edk2] What is the right way to print a UINTN?
> 
> MIke,
> 
> > Portable sources that use type UINTN must never use values larger
> > than
> > 32-bits.  Same for type INTN.  Only use values in signed 32-bit range.
> 
> If the value is something like an enumeration or bitmask then I agree, but 
> not if it's
> something numeric that is supposed to scale to larger numbers on 64-bit 
> platforms like
> the Length field of CopyMem.
> 
> I like the proposals to use a custom format specifier (although the 
> concatenated string
> with macro will take some getting used to).
> 
> Thanks,
> 
> Eugene
> ___
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Cohen, Eugene
MIke,

> Portable sources that use type UINTN must never use values larger
> than
> 32-bits.  Same for type INTN.  Only use values in signed 32-bit range.

If the value is something like an enumeration or bitmask then I agree, but not 
if it's something numeric that is supposed to scale to larger numbers on 64-bit 
platforms like the Length field of CopyMem.

I like the proposals to use a custom format specifier (although the 
concatenated string with macro will take some getting used to).

Thanks,

Eugene
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Laszlo Ersek
On 09/27/16 19:14, Brian J. Johnson wrote:
> On 09/27/2016 11:47 AM, Andrew Fish wrote:
>>
>>> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene  wrote:
>>>
 Printing UINTN with %x *or* with %d are equally bugs.

 For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
 work most of the time).
>>>
>>> Feel free to file a Bugzilla on the extensive usage of this in
>>> edk2 [ducking and running]. :)
>>>
> I'm envisioning having to create a slide in the future for UEFI
> training about the proper use of UINTNs and describing "If you think
> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> about it" and it makes me squirm.

 It makes me squirm too. I think the slide should recommend the
 casting
 that I proposed. ;) "There is no conversion specifier dedicated to
 UINTN; the portable way to print it is to cast it to UINT64, then print
 it with %Lx."
>>>
>>> This is reasonable although I expect to get asked why a lot of the
>>> other code doesn't adhere to this recommendation.
>>>
>>
>> I think this is a historical artifact. The older version of %x in
>> the EDK (and early edk2) implied UINTN. We hit an issue with C
>> integer math resulting in an int and that seemed to bork some
>> toolchains. That is when things changed from UINTN to int. I guess
>> the cleanup was practical vs. pedantic.
> 
> Thanks for the historical context, Andrew.  It's interesting to hear,
> if very unfortunate.
> 
> I've written code in the past which uses a #defined value for the
> UINTN format character as a way to work around this issue without
> casting everything to 64 bits.  Something like:
> 
> // Format string for a naturally-sized unsigned integer
> #if defined (MDE_CPU_IA32)
> #define UINTN_FMT  "0x%08x"
> #elif defined (MDE_CPU_X64)
> #define UINTN_FMT  "0x%016lx"
> #elif ...
>   ...
> #endif
> 
> UINTN Val;
> Val = Foo ();
> DEBUG((DEBUG_INFO, "Value is " UINTN_FMT "\n", Val));
> 
> 
> I guess it's a matter of opinion if that's preferable to adding casts;
> in my particular situation, I had to print values with that particular
> format string in a lot of places, so it was convenient to #define it
> once.

I find this great; standard C also has macros for format specifiers, for
example PRIu64, PRId32, PRIx64, and so on.

PrintLib.h could be extended with PRIuN ("u"/"Lu"), PRIxN ("x"/"Lx"),
PRIdN ("d"/"Ld") and PRIiN ("i"/"Li"), to be defined similarly to your
code above (covering all supported CPU architectures). Then code could
use them like

DEBUG ((DEBUG_INFO, "Value is 0x%" PRIxN "\n", Val));

The field width, if necessary, can be passed in as an argument,

DEBUG ((DEBUG_INFO, "Value is 0x%0*" PRIxN "\n", 2 * sizeof Val, Val));

If this is deemed too messy, we could define further macros for the
zero-padded conversions.

Thanks,
Laszlo
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Kinney, Michael D
Andrew,

Yes.  Using fixed with base types instead of natural width base types is clearer
and very portable.

We do use UINTN in UEFI/PI spec APIs on purpose when the range of the argument 
does need vary for different CPU widths.  Using UINTN in function args 
and local variables also generates smaller code in most cases because UINTN
usually matches the stack and register width.  So there are good reasons to 
use UINTN/INTN.

I did find the commit where the use of 'int' was added to pull arguments from 
the 
var arg list.  Dated 6/3/2006.

  SHA-1: 1d580c14473896b5b593a7f60a21f532008265d0

  * 1) Add support for %p to print pointers
  2) Fix %d,%x,%X to pull values off the vararg stack using (int) and (unsigned 
int) 
 types to resolve compatibility issues with X64

Best regards,

Mike

> -Original Message-
> From: af...@apple.com [mailto:af...@apple.com]
> Sent: Tuesday, September 27, 2016 10:47 AM
> To: Kinney, Michael D 
> Cc: Eugene Cohen ; Alexei Fedorov ; 
> edk2-
> de...@lists.01.org ; Laszlo Ersek 
> Subject: Re: [edk2] What is the right way to print a UINTN?
> 
> 
> > On Sep 27, 2016, at 10:27 AM, Kinney, Michael D 
> >  wrote:
> >
> > Andrew,
> >
> > Here is the comment in current code that explains some of the why.
> >
> >  case 'd':
> >if ((Flags & LONG_TYPE) == 0) {
> >  //
> >  // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are 
> > assumed to
> be type "int".
> >  // This assumption is made so the format string definition is 
> > compatible
> with the ANSI C
> >  // Specification for formatted strings.  It is recommended that 
> > the Base
> Types be used
> >  // everywhere, but in this one case, compliance with ANSI C is more
> important, and
> >  // provides an implementation that is compatible with that largest 
> > possible
> set of CPU
> >  // architectures.  This is why the type "int" is used in this one 
> > case.
> >  //
> >
> > If code uses type UINTN or INTN, then the max value that can be used
> > for portable sources is max value for the CPU arch with the smallest
> > UINTN width.  For the CPU archs in UEFI/PI specs today, the smallest UINTN
> > width is 32-bits.
> >
> > Portable sources that use type UINTN must never use values larger than
> > 32-bits.  Same for type INTN.  Only use values in signed 32-bit range.
> >
> > It is possible for 64-bit specific sources to use type UINTN with values
> > larger than 32-bits, but those sources would not be portable and would
> > need to be changed to UINT64 to be portable.  Is this the case that are
> > really discussing here?
> >
> 
> If you have a UINTN that can only represent 32-bits is that not a UINT32 :).
> 
> Thanks,
> 
> Andrew Fish
> 
> > Thanks,
> >
> > Mike
> >
> >
> >> -Original Message-
> >> From: af...@apple.com [mailto:af...@apple.com]
> >> Sent: Tuesday, September 27, 2016 9:47 AM
> >> To: Eugene Cohen 
> >> Cc: Laszlo Ersek ; Kinney, Michael D
> ;
> >> Alexei Fedorov ; edk2-devel@lists.01.org  >> de...@ml01.01.org>
> >> Subject: Re: [edk2] What is the right way to print a UINTN?
> >>
> >>
> >>> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene  wrote:
> >>>
>  Printing UINTN with %x *or* with %d are equally bugs.
> 
>  For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
>  work most of the time).
> >>>
> >>> Feel free to file a Bugzilla on the extensive usage of this in edk2 
> >>> [ducking and
> >> running].  :)
> >>>
> > I'm envisioning having to create a slide in the future for UEFI
> > training about the proper use of UINTNs and describing "If you think
> > it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> > about it" and it makes me squirm.
> 
>  It makes me squirm too. I think the slide should recommend the
>  casting
>  that I proposed. ;) "There is no conversion specifier dedicated to
>  UINTN; the portable way to print it is to cast it to UINT64, then print
>  it with %Lx."
> >>>
> >>> This is reasonable although I expect to get asked why a lot of the other 
> >>> code
> doesn't
> >> adhere to this recommendation.
> >>>
> >>
> >> I think this is a historical artifact. The older version of %x in the EDK 
> >> (and early
> >> edk2) implied UINTN. We hit an issue with C integer math resulting in an 
> >> int and
> that
> >> seemed to bork some toolchains. That is when things changed from UINTN to 
> >> int. I
> guess
> >> the cleanup was practical vs. pedantic.
> >>
> >> Thanks,
> >>
> >> Andrew Fish
> >>
> >>> Thanks,
> >>>
> >>> Eugene
> >>> ___
> >>> edk2-devel mailing list
> >>> edk2-devel@lists.01.org
> >>> 

Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Andrew Fish

> On Sep 27, 2016, at 10:27 AM, Kinney, Michael D  
> wrote:
> 
> Andrew,
> 
> Here is the comment in current code that explains some of the why.
> 
>  case 'd':
>if ((Flags & LONG_TYPE) == 0) {
>  //
>  // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are 
> assumed to be type "int".
>  // This assumption is made so the format string definition is 
> compatible with the ANSI C
>  // Specification for formatted strings.  It is recommended that the 
> Base Types be used 
>  // everywhere, but in this one case, compliance with ANSI C is more 
> important, and 
>  // provides an implementation that is compatible with that largest 
> possible set of CPU 
>  // architectures.  This is why the type "int" is used in this one 
> case.
>  //
> 
> If code uses type UINTN or INTN, then the max value that can be used 
> for portable sources is max value for the CPU arch with the smallest
> UINTN width.  For the CPU archs in UEFI/PI specs today, the smallest UINTN
> width is 32-bits.
> 
> Portable sources that use type UINTN must never use values larger than
> 32-bits.  Same for type INTN.  Only use values in signed 32-bit range.
> 
> It is possible for 64-bit specific sources to use type UINTN with values
> larger than 32-bits, but those sources would not be portable and would
> need to be changed to UINT64 to be portable.  Is this the case that are
> really discussing here?
> 

If you have a UINTN that can only represent 32-bits is that not a UINT32 :). 

Thanks,

Andrew Fish

> Thanks,
> 
> Mike
> 
> 
>> -Original Message-
>> From: af...@apple.com [mailto:af...@apple.com]
>> Sent: Tuesday, September 27, 2016 9:47 AM
>> To: Eugene Cohen 
>> Cc: Laszlo Ersek ; Kinney, Michael D 
>> ;
>> Alexei Fedorov ; edk2-devel@lists.01.org > de...@ml01.01.org>
>> Subject: Re: [edk2] What is the right way to print a UINTN?
>> 
>> 
>>> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene  wrote:
>>> 
 Printing UINTN with %x *or* with %d are equally bugs.
 
 For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
 work most of the time).
>>> 
>>> Feel free to file a Bugzilla on the extensive usage of this in edk2 
>>> [ducking and
>> running].  :)
>>> 
> I'm envisioning having to create a slide in the future for UEFI
> training about the proper use of UINTNs and describing "If you think
> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> about it" and it makes me squirm.
 
 It makes me squirm too. I think the slide should recommend the
 casting
 that I proposed. ;) "There is no conversion specifier dedicated to
 UINTN; the portable way to print it is to cast it to UINT64, then print
 it with %Lx."
>>> 
>>> This is reasonable although I expect to get asked why a lot of the other 
>>> code doesn't
>> adhere to this recommendation.
>>> 
>> 
>> I think this is a historical artifact. The older version of %x in the EDK 
>> (and early
>> edk2) implied UINTN. We hit an issue with C integer math resulting in an int 
>> and that
>> seemed to bork some toolchains. That is when things changed from UINTN to 
>> int. I guess
>> the cleanup was practical vs. pedantic.
>> 
>> Thanks,
>> 
>> Andrew Fish
>> 
>>> Thanks,
>>> 
>>> Eugene
>>> ___
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org
>>> https://lists.01.org/mailman/listinfo/edk2-devel
> 
> ___
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Kinney, Michael D
Andrew,

Here is the comment in current code that explains some of the why.

  case 'd':
if ((Flags & LONG_TYPE) == 0) {
  //
  // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are 
assumed to be type "int".
  // This assumption is made so the format string definition is 
compatible with the ANSI C
  // Specification for formatted strings.  It is recommended that the 
Base Types be used 
  // everywhere, but in this one case, compliance with ANSI C is more 
important, and 
  // provides an implementation that is compatible with that largest 
possible set of CPU 
  // architectures.  This is why the type "int" is used in this one 
case.
  //

If code uses type UINTN or INTN, then the max value that can be used 
for portable sources is max value for the CPU arch with the smallest
UINTN width.  For the CPU archs in UEFI/PI specs today, the smallest UINTN
width is 32-bits.

Portable sources that use type UINTN must never use values larger than
32-bits.  Same for type INTN.  Only use values in signed 32-bit range.

It is possible for 64-bit specific sources to use type UINTN with values
larger than 32-bits, but those sources would not be portable and would
need to be changed to UINT64 to be portable.  Is this the case that are
really discussing here?

Thanks,

Mike


> -Original Message-
> From: af...@apple.com [mailto:af...@apple.com]
> Sent: Tuesday, September 27, 2016 9:47 AM
> To: Eugene Cohen 
> Cc: Laszlo Ersek ; Kinney, Michael D 
> ;
> Alexei Fedorov ; edk2-devel@lists.01.org  de...@ml01.01.org>
> Subject: Re: [edk2] What is the right way to print a UINTN?
> 
> 
> > On Sep 27, 2016, at 9:03 AM, Cohen, Eugene  wrote:
> >
> >> Printing UINTN with %x *or* with %d are equally bugs.
> >>
> >> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
> >> work most of the time).
> >
> > Feel free to file a Bugzilla on the extensive usage of this in edk2 
> > [ducking and
> running].  :)
> >
> >>> I'm envisioning having to create a slide in the future for UEFI
> >>> training about the proper use of UINTNs and describing "If you think
> >>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> >>> about it" and it makes me squirm.
> >>
> >> It makes me squirm too. I think the slide should recommend the
> >> casting
> >> that I proposed. ;) "There is no conversion specifier dedicated to
> >> UINTN; the portable way to print it is to cast it to UINT64, then print
> >> it with %Lx."
> >
> > This is reasonable although I expect to get asked why a lot of the other 
> > code doesn't
> adhere to this recommendation.
> >
> 
> I think this is a historical artifact. The older version of %x in the EDK 
> (and early
> edk2) implied UINTN. We hit an issue with C integer math resulting in an int 
> and that
> seemed to bork some toolchains. That is when things changed from UINTN to 
> int. I guess
> the cleanup was practical vs. pedantic.
> 
> Thanks,
> 
> Andrew Fish
> 
> > Thanks,
> >
> > Eugene
> > ___
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel

___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Brian J. Johnson

On 09/27/2016 11:47 AM, Andrew Fish wrote:



On Sep 27, 2016, at 9:03 AM, Cohen, Eugene  wrote:


Printing UINTN with %x *or* with %d are equally bugs.

For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
work most of the time).


Feel free to file a Bugzilla on the extensive usage of this in
edk2 [ducking and running]. :)


I'm envisioning having to create a slide in the future for UEFI
training about the proper use of UINTNs and describing "If you think
it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
about it" and it makes me squirm.


It makes me squirm too. I think the slide should recommend the
casting
that I proposed. ;) "There is no conversion specifier dedicated to
UINTN; the portable way to print it is to cast it to UINT64, then print
it with %Lx."


This is reasonable although I expect to get asked why a lot of the
other code doesn't adhere to this recommendation.



I think this is a historical artifact. The older version of %x in
the EDK (and early edk2) implied UINTN. We hit an issue with C
integer math resulting in an int and that seemed to bork some
toolchains. That is when things changed from UINTN to int. I guess
the cleanup was practical vs. pedantic.


Thanks for the historical context, Andrew.  It's interesting to hear,
if very unfortunate.

I've written code in the past which uses a #defined value for the
UINTN format character as a way to work around this issue without
casting everything to 64 bits.  Something like:

// Format string for a naturally-sized unsigned integer
#if defined (MDE_CPU_IA32)
#define UINTN_FMT  "0x%08x"
#elif defined (MDE_CPU_X64)
#define UINTN_FMT  "0x%016lx"
#elif ...
  ...
#endif

UINTN Val;
Val = Foo ();
DEBUG((DEBUG_INFO, "Value is " UINTN_FMT "\n", Val));


I guess it's a matter of opinion if that's preferable to adding casts;
in my particular situation, I had to print values with that particular
format string in a lot of places, so it was convenient to #define it
once.



Thanks,

Andrew Fish


Thanks,

Eugene
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel




--

Brian J. Johnson



  My statements are my own, are not authorized by SGI, and do not
  necessarily represent SGI’s positions.
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Andrew Fish

> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene  wrote:
> 
>> Printing UINTN with %x *or* with %d are equally bugs.
>> 
>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
>> work most of the time).
> 
> Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking 
> and running].  :)
> 
>>> I'm envisioning having to create a slide in the future for UEFI
>>> training about the proper use of UINTNs and describing "If you think
>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
>>> about it" and it makes me squirm.
>> 
>> It makes me squirm too. I think the slide should recommend the
>> casting
>> that I proposed. ;) "There is no conversion specifier dedicated to
>> UINTN; the portable way to print it is to cast it to UINT64, then print
>> it with %Lx."
> 
> This is reasonable although I expect to get asked why a lot of the other code 
> doesn't adhere to this recommendation.
> 

I think this is a historical artifact. The older version of %x in the EDK (and 
early edk2) implied UINTN. We hit an issue with C integer math resulting in an 
int and that seemed to bork some toolchains. That is when things changed from 
UINTN to int. I guess the cleanup was practical vs. pedantic. 

Thanks,

Andrew Fish

> Thanks,
> 
> Eugene
> ___
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Laszlo Ersek
On 09/27/16 18:03, Cohen, Eugene wrote:
>> Printing UINTN with %x *or* with %d are equally bugs.
>>
>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
>> work most of the time).
> 
> Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking 
> and running].  :)

Not a bad idea, but it's not practical. I take care to use the right
casts and conversion specifiers whenever I write new code, but for
identifying existent incorrect calls, compiler support would be necessary.

I guess we could add the GCC function attribute that I mentioned earlier
to some of the PrintLib functions, and then address the resultant
warning messages. The problem is that some of the edk2-defined
conversion specifiers

- are not defined in standard (or GNU) C -- for example, %t --, which
might prevent GCC from pairing the corresponding argument with any
conversion specifier at all,

- and/or work differently from their standard (or GNU) C counterparts:
  - for example %g is entirely different between edk2 and standard C
((EFI_GUID *) vs. double),
  - the "L" length modifier is invalid for %x in standard C,
  - etc.

If someone is into GCC or CLANG plugin development, creating an "edk2
PrintLib" function attribute could be a good task :)

>>> I'm envisioning having to create a slide in the future for UEFI
>>> training about the proper use of UINTNs and describing "If you think
>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
>>> about it" and it makes me squirm.
>>
>> It makes me squirm too. I think the slide should recommend the
>> casting
>> that I proposed. ;) "There is no conversion specifier dedicated to
>> UINTN; the portable way to print it is to cast it to UINT64, then print
>> it with %Lx."
> 
> This is reasonable although I expect to get asked why a lot of the other code 
> doesn't adhere to this recommendation.

"Because people didn't realize it was a bug and it worked in practice"? :)

Thanks
Laszlo
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Cohen, Eugene
> Printing UINTN with %x *or* with %d are equally bugs.
> 
> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
> work most of the time).

Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking 
and running].  :)
 
> > I'm envisioning having to create a slide in the future for UEFI
> > training about the proper use of UINTNs and describing "If you think
> > it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> > about it" and it makes me squirm.
> 
> It makes me squirm too. I think the slide should recommend the
> casting
> that I proposed. ;) "There is no conversion specifier dedicated to
> UINTN; the portable way to print it is to cast it to UINT64, then print
> it with %Lx."

This is reasonable although I expect to get asked why a lot of the other code 
doesn't adhere to this recommendation.

Thanks,

Eugene
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Laszlo Ersek
On 09/27/16 14:29, Cohen, Eugene wrote:
> Laszlo,
>  
>> I print INTN / UINTN values with:
>> - casting them unconditionally to INT64 / UINT64,
>> - printing the converted values with the matching conversion
>> specifiers,
>> such as %Ld (for INT64) and %Lu or %Lx (for UINT64).
>>
>> This solution requires a bit more typing, and it is a bit pessimistic
>> for 32-bit builds. On the positive side, it is robust / portable, and
>> completely valid C.
>>
>> It is inspired by the standard C types intmax_t / uintmax_t. If you
>> write portable C code and want to print a value of some integer type,
>> where the spec only states "signed" or "unsigned integer type", but
>> the
>> actual type is either implementation defined or unspecified,
>> converting
>> the value to intmax_t / uintmax_t, and then printing it with %jd vs. %ju
>> / %jx, is safe.
> 
> Thanks - this makes sense.  If this methodology is consistent with
> standard C then perhaps it's the best compromise even if it's messy
> to read.
> 
> From a consistency perspective I see a lot of variation in usage -
> often UINTNs are printed with %x / %d (technically it should be %u
> but this is a common error - just compare the number of occurrences
> of %u in MdeModulePkg versus %d).

Printing UINTN with %x *or* with %d are equally bugs.

For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
work most of the time).

For Ia32 / ARM builds, %x is not an actual bug, just a portability one /
code smell. And %d may or may not be an actual bug, dependent on the
value being printed.

> This means that the caller is
> expecting that the value will never exceed 2^32-1 on 64-bit systems
> since we are doing 64-bit to 32-bit truncation through the cast in
> the VA_ARG macro.

I think that the specifics why printing UINTN with %x (or %d) happens to
work on X64 / AARCH64, for a subset of the UINTN values, are not
interesting. As far as I'm concerned, even the argument *sizes* are
wrong, which might as well lead to incorrect accesses to the stack.

> I'm concerned that this requires the developer to
> know the constraints on the value in all circumstances which seems
> dubious - after all that's why we have types in the first place, so
> the tools can help us do the right thing.

The developer is first and foremost required to match the conversion
specifiers to the types of the arguments being passed. For UINTN there
is no dedicated conversion specifier, hence my recommendation for the
casting.

> I'm envisioning having to create a slide in the future for UEFI
> training about the proper use of UINTNs and describing "If you think
> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> about it" and it makes me squirm.

It makes me squirm too. I think the slide should recommend the casting
that I proposed. ;) "There is no conversion specifier dedicated to
UINTN; the portable way to print it is to cast it to UINT64, then print
it with %Lx."

Thanks
Laszlo
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-27 Thread Cohen, Eugene
Laszlo,
 
> I print INTN / UINTN values with:
> - casting them unconditionally to INT64 / UINT64,
> - printing the converted values with the matching conversion
> specifiers,
> such as %Ld (for INT64) and %Lu or %Lx (for UINT64).
> 
> This solution requires a bit more typing, and it is a bit pessimistic
> for 32-bit builds. On the positive side, it is robust / portable, and
> completely valid C.
> 
> It is inspired by the standard C types intmax_t / uintmax_t. If you
> write portable C code and want to print a value of some integer type,
> where the spec only states "signed" or "unsigned integer type", but
> the
> actual type is either implementation defined or unspecified,
> converting
> the value to intmax_t / uintmax_t, and then printing it with %jd vs. %ju
> / %jx, is safe.

Thanks - this makes sense.  If this methodology is consistent with standard C 
then perhaps it's the best compromise even if it's messy to read.

>From a consistency perspective I see a lot of variation in usage - often 
>UINTNs are printed with %x / %d (technically it should be %u but this is a 
>common error - just compare the number of occurrences of %u in MdeModulePkg 
>versus %d).  This means that the caller is expecting that the value will never 
>exceed 2^32-1 on 64-bit systems since we are doing 64-bit to 32-bit truncation 
>through the cast in the VA_ARG macro.  I'm concerned that this requires the 
>developer to know the constraints on the value in all circumstances which 
>seems dubious - after all that's why we have types in the first place, so the 
>tools can help us do the right thing.

I'm envisioning having to create a slide in the future for UEFI training about 
the proper use of UINTNs and describing "If you think it may exceed 2^32-1 then 
upcast to UINT64, otherwise don't worry about it" and it makes me squirm.

Eugene
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-26 Thread Laszlo Ersek
On 09/26/16 15:46, Cohen, Eugene wrote:
> Get ready for a potentially stupid question (or at least a question I
> probably should know the answer to by now)...

This is a perfectly valid question.

I print INTN / UINTN values with:
- casting them unconditionally to INT64 / UINT64,
- printing the converted values with the matching conversion specifiers,
such as %Ld (for INT64) and %Lu or %Lx (for UINT64).

This solution requires a bit more typing, and it is a bit pessimistic
for 32-bit builds. On the positive side, it is robust / portable, and
completely valid C.

It is inspired by the standard C types intmax_t / uintmax_t. If you
write portable C code and want to print a value of some integer type,
where the spec only states "signed" or "unsigned integer type", but the
actual type is either implementation defined or unspecified, converting
the value to intmax_t / uintmax_t, and then printing it with %jd vs. %ju
/ %jx, is safe.

Regarding %p (relayed by Alexei as a recommendation from years ago),
that's a bug. %p takes a pointer to void. If we ever enable format
string checking in edk2, for example with GCC's
__attribute__((format(printf, ..., ...))), all those calls will blow up.

Thanks
Laszlo
___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


Re: [edk2] What is the right way to print a UINTN?

2016-09-26 Thread Alexei Fedorov
I raised this issue a few years ago & was advised to use %p notation.

Alexei.

-Original Message-
From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Cohen, 
Eugene
Sent: 26 September 2016 14:46
To: edk2-devel@lists.01.org; Kinney, Michael D
Subject: [edk2] What is the right way to print a UINTN?

Get ready for a potentially stupid question (or at least a question I probably 
should know the answer to by now)...

The implementation of BasePrintLib treats types like %d and %x as the size of 
the compiler's "int" type.  On many 64-bit architectures the size of int is 
32-bits.  On these same architectures we declare a "UINTN" type as 64-bits.

The handling for integral types (%d, %x, %u, etc) in BasePrintLib is as 
follows, note the use of 'int':

  if (BaseListMarker == NULL) {
Value = VA_ARG (VaListMarker, int);
  } else {
Value = BASE_ARG (BaseListMarker, int);
  }

So it would seem to be improper to try to Print/DEBUG a UINTN value with 
%d/%u/%x since the size will be mismatched on some architecture (INTN 64 bits, 
int 32 bits).  But it also would be improper to try to print this as %ld/%lx 
because the size will be mismatched on 32-bit architectures (INTN 32 bits and 
print will use a INT64 with the 'l' prefix).  It's not obvious then how to 
create a portable format specifier that works for UINTN.

I did some research in how this is handled in edk2 for modules we know to be 
portable and I see multiple conflicting techniques being used.  The predominant 
pattern for this is to try to print a UINTN parameter with the %d/%x format 
specifier anyways like this:

  DEBUG ((EFI_D_ERROR, "FATAL ERROR - RaiseTpl with OldTpl(0x%x) > 
NewTpl(0x%x)\n", OldTpl, NewTpl));

in this case the parameter if EFI_TPL which was typedef'ed as a UINTN.  In this 
case the compiler does the variadic thing and on a 64-bit architecture puts a 
64-bit UINTN on the variadic stack (using the term stack in the abstract sense 
here).

When the print code tries to pop it off the stack using VA_ARG (VaListMarker, 
int) the 'int' gets upgraded in size to UINTN due to this construct in Base.h 
(I'm using GCC):

  #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? 
(TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, 
TYPE)))

since sizeof(int) is 4 and this is less than sizeof(UINTN) at 8 the result will 
be  (TYPE)(__builtin_va_arg (Marker, UINTN)) where TYPE is 'int'.  So we end up 
popping 64-bits off the varidic stack but immediately typecast it to an int (4 
byte) resulting in loss of the upper-64 bits.  If I'm reading this right it 
means we can only print UINTNs whose value is below 2^32 (confirmed with a 
debugger on AArch64 using GCC).  Maybe this seems benign for the simple EFI_TPL 
enumeration but if for some reason you add a new value that exceeds 2^32-1 then 
the print code is broken.  Is every user of Print/DEBUG expected understand 
this range limitation?


What is the preferred pattern for printing a INTN/UINTN then?  Two yucky hacks 
I can think of: upcasting to UINT64/%ld when you "know" the value may exceed 
2^32-1 or using %p for non-pointer types since this happens to get the right 
size treatment although we lose formatting options.

Eugene



___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.

___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


[edk2] What is the right way to print a UINTN?

2016-09-26 Thread Cohen, Eugene
Get ready for a potentially stupid question (or at least a question I probably 
should know the answer to by now)...

The implementation of BasePrintLib treats types like %d and %x as the size of 
the compiler's "int" type.  On many 64-bit architectures the size of int is 
32-bits.  On these same architectures we declare a "UINTN" type as 64-bits.

The handling for integral types (%d, %x, %u, etc) in BasePrintLib is as 
follows, note the use of 'int':

  if (BaseListMarker == NULL) {
Value = VA_ARG (VaListMarker, int);
  } else {
Value = BASE_ARG (BaseListMarker, int);
  }

So it would seem to be improper to try to Print/DEBUG a UINTN value with 
%d/%u/%x since the size will be mismatched on some architecture (INTN 64 bits, 
int 32 bits).  But it also would be improper to try to print this as %ld/%lx 
because the size will be mismatched on 32-bit architectures (INTN 32 bits and 
print will use a INT64 with the 'l' prefix).  It's not obvious then how to 
create a portable format specifier that works for UINTN.

I did some research in how this is handled in edk2 for modules we know to be 
portable and I see multiple conflicting techniques being used.  The predominant 
pattern for this is to try to print a UINTN parameter with the %d/%x format 
specifier anyways like this:

  DEBUG ((EFI_D_ERROR, "FATAL ERROR - RaiseTpl with OldTpl(0x%x) > 
NewTpl(0x%x)\n", OldTpl, NewTpl));

in this case the parameter if EFI_TPL which was typedef'ed as a UINTN.  In this 
case the compiler does the variadic thing and on a 64-bit architecture puts a 
64-bit UINTN on the variadic stack (using the term stack in the abstract sense 
here).

When the print code tries to pop it off the stack using VA_ARG (VaListMarker, 
int) the 'int' gets upgraded in size to UINTN due to this construct in Base.h 
(I'm using GCC):

  #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? 
(TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, 
TYPE)))

since sizeof(int) is 4 and this is less than sizeof(UINTN) at 8 the result will 
be  (TYPE)(__builtin_va_arg (Marker, UINTN)) where TYPE is 'int'.  So we end up 
popping 64-bits off the varidic stack but immediately typecast it to an int (4 
byte) resulting in loss of the upper-64 bits.  If I'm reading this right it 
means we can only print UINTNs whose value is below 2^32 (confirmed with a 
debugger on AArch64 using GCC).  Maybe this seems benign for the simple EFI_TPL 
enumeration but if for some reason you add a new value that exceeds 2^32-1 then 
the print code is broken.  Is every user of Print/DEBUG expected understand 
this range limitation?


What is the preferred pattern for printing a INTN/UINTN then?  Two yucky hacks 
I can think of: upcasting to UINT64/%ld when you "know" the value may exceed 
2^32-1 or using %p for non-pointer types since this happens to get the right 
size treatment although we lose formatting options.

Eugene



___
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel