Leif, What are the specific warnings that are being triggered by CLANG -Weverything for the unaligned access APIs in BaseLib?
Are there other options than changing the BaseLib API definitions? My two concerns are: 1) Impacts to modules/libs that call the unaligned access functions in BaseLib. Changing I am not sure if changing a parameter from UINTx * to VOID * is backwards compatible for All caller use cases or not. 2) Loss of some type checking as I mentioned below. Thanks, Mike > -----Original Message----- > From: [email protected] [mailto:[email protected]] > Sent: Thursday, May 12, 2016 4:27 PM > To: Kinney, Michael D <[email protected]> > Cc: Leif Lindholm <[email protected]>; [email protected]; Gao, > Liming > <[email protected]>; Ard Biesheuvel <[email protected]> > Subject: Re: [edk2] [RFC] MdePkg: BaseLib: don't use aligned pointers for > unaligned > accessors > > > > On May 12, 2016, at 4:01 PM, Kinney, Michael D <[email protected]> > > wrote: > > > > Leif, > > > > Yes. Typecasts are used by the caller if the type does not match. Here is > > an > > example from the PciCfg2.c that you referenced. > > > > IN OUT VOID *Buffer > > > > // > > // Aligned Pci address access > > // > > WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress)); > > > > > > Since Buffer is type VOID *, a typecast to UINT16 * is made. That is valid > > C > > code. > > Mike, > > Leif may be talking about: > > The C Standard, 6.3.2.3, paragraph 7 [ISO/IEC 9899:2011], states: > A pointer to an object or incomplete type may be converted to a pointer to a > different object or incomplete type. If the resulting pointer is not correctly > aligned for the referenced type, the behavior is undefined. > > I always like to reference Chris Lattner's LLVM blog post on undefined > behavior, but > this is not an example of the specific case. But the restrictions on type > conversions > exist to enable TBAA. > http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html > Violating Type Rules: It is undefined behavior to cast an int* to a float* and > dereference it (accessing the "int" as if it were a "float"). C requires that > these > sorts of type conversions happen through memcpy: using pointer casts is not > correct > and undefined behavior results. The rules for this are quite nuanced and I > don't want > to go into the details here (there is an exception for char*, vectors have > special > properties, unions change things, etc). This behavior enables an analysis > known as > "Type-Based Alias Analysis" (TBAA) which is used by a broad range of memory > access > optimizations in the compiler, and can significantly improve performance of > the > generated code. For example, this rule allows clang to optimize this function: > > float *P; > void zero_array() { > int i; > for (i = 0; i < 10000; ++i) > P[i] = 0.0f; > } > > into "memset(P, 0, 40000)". This optimization also allows many loads to be > hoisted > out of loops, common subexpressions to be eliminated, etc. This class of > undefined > behavior can be disabled by passing the -fno-strict-aliasing flag, which > disallows > this analysis. When this flag is passed, Clang is required to compile this > loop into > 10000 4-byte stores (which is several times slower), because it has to assume > that it > is possible for any of the stores to change the value of P, as in something > like > this: > > int main() { > P = (float*)&P; // cast causes TBAA violation in zero_array. > zero_array(); > } > > > This sort of type abuse is pretty uncommon, which is why the standard > committee > decided that the significant performance wins were worth the unexpected > result for > "reasonable" type casts. It is worth pointing out that Java gets the benefits > of > type-based optimizations without these drawbacks because it doesn't have > unsafe > pointer casting in the language at all. > > Thanks, > > Andrew Fish > > > One use case where making these APIs type specific is when a data structure > > is used that is either byte packed or the start of the structure is not > > aligned > (e.g. > > network packet processing). In these cases, the fields may have explicit > > types > such > > as UINT16, UINT32, UINT64, and the compiler does type checking when a > > pointer to > the > > field is passed into the unaligned access functions. > > > > By changing the APIs to be VOID* instead of UINT16*, UINT32*, or UINT64*, > > some type > > checking is lost. The APIs as they are defines now have worked for IPF. > > What is > > different about ARM and AArch64? Are you wanting to remove the requirement > > for the > > explicit typecast by the caller? > > > > > > > > You are correct. PatchCheck.py does not check EDK II C style. The ECC > > tool can be > > used for that. We have discussed adding ECC to PatchCheck.py, but have not > > done > that > > yet. > > > > > > > > Thanks, > > > > Mike > > > > > > > > > >> -----Original Message----- > >> From: Leif Lindholm [mailto:[email protected]] > >> Sent: Thursday, May 12, 2016 3:49 PM > >> To: Kinney, Michael D <[email protected]> > >> Cc: [email protected]; Gao, Liming <[email protected]>; Ard > >> Biesheuvel > >> <[email protected]> > >> Subject: Re: [RFC] MdePkg: BaseLib: don't use aligned pointers for > >> unaligned > >> accessors > >> > >> On Thu, May 12, 2016 at 10:29:34PM +0000, Kinney, Michael D wrote: > >>> Leif, > >>> > >>> Why does the current definition strictly require alignment? > >>> > >>> I know we have used this for a long time with many compilers passing in > >>> unaligned pointers to UINT16, UINT32, UINT64 values without any compiler > >>> warnings/errors. > >> > >> Sure, but that does not make it valid C. > >> > >> Specifying an input argument to be a UINT32 * at least in ARM, AArch64 > >> and IPF land means that the programmer provides an explicit guarantee > >> that the pointer references a naturally aligned location. > >> > >> Also, the reason that edk2 compiles without warnings is that code in > >> the tree makes (also invalid) casts at the call sites to these > >> functions in order to get rid of said warnings. See for example > >> MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c > >> > >> (A naive grep throws up 129 instances of explicit casts on lines > >> calling a ReadUnaligned function and 211 instances of ones calling a > >> WriteUnaligned function.) > >> > >>> Also, the patch contains locals that are initialized in the declaration > >>> of the local. We prefer locals to be initialized in the body of the > >>> function. > >> > >> Understood - PatchCheck.py didn't warn me about that :) > >> > >> Regards, > >> > >> Leif > >> > >>> Thanks, > >>> > >>> Mike > >>> > >>>> -----Original Message----- > >>>> From: Leif Lindholm [mailto:[email protected]] > >>>> Sent: Thursday, May 12, 2016 3:22 PM > >>>> To: [email protected] > >>>> Cc: Kinney, Michael D <[email protected]>; Gao, Liming > >>>> <[email protected]>; Ard Biesheuvel <[email protected]> > >>>> Subject: [RFC] MdePkg: BaseLib: don't use aligned pointers for unaligned > >> accessors > >>>> > >>>> The ReadUnaligned##/WriteUnaligned## functions provide a portable way of > >>>> accessing potentially unaligned locations, but the prototypes in > >>>> BaseLib.h all specify strictly aligned pointers. > >>>> > >>>> Change the prototypes as well as the implementations across Ia32/X64, > >>>> ARM/AArch64 and IPF to use VOID * pointers instead. > >>>> > >>>> Contributed-under: TianoCore Contribution Agreement 1.0 > >>>> Signed-off-by: Leif Lindholm <[email protected]> > >>>> --- > >>>> > >>>> Built and tested for ArmVirtPkg for AArch64/ARM DEBUG/RELEASE. > >>>> Build tested only for OvmfPkg for Ia32/X64 DEBUG/RELEASE. > >>>> Not tested at all for IPF. > >>>> > >>>> I am not entirely convinced by the BitFieldWrite32 logic in > >>>> WriteUnaligned24, but this patch is not the place to fix this. > >>>> > >>>> I am also not convinced there is much point in keeping separate > >>>> implementations for IPF and ARM* - the optimization issues mentioned > >>>> in the git log could even have been affected by the incorrect > >>>> pointer types. > >>>> > >>>> This is the first patch triggered by my CLANG -Weverything exercises > >>>> earlier this year. More to come. > >>>> > >>>> MdePkg/Include/Library/BaseLib.h | 16 ++++++------ > >>>> MdePkg/Library/BaseLib/Arm/Unaligned.c | 16 ++++++------ > >>>> MdePkg/Library/BaseLib/Ipf/Unaligned.c | 16 ++++++------ > >>>> MdePkg/Library/BaseLib/Unaligned.c | 48 > >>>> ++++++++++++++++++++++------------ > >>>> 4 files changed, 56 insertions(+), 40 deletions(-) > >>>> > >>>> diff --git a/MdePkg/Include/Library/BaseLib.h > >>>> b/MdePkg/Include/Library/BaseLib.h > >>>> index c41fa78..133656a 100644 > >>>> --- a/MdePkg/Include/Library/BaseLib.h > >>>> +++ b/MdePkg/Include/Library/BaseLib.h > >>>> @@ -2549,7 +2549,7 @@ DivS64x64Remainder ( > >>>> UINT16 > >>>> EFIAPI > >>>> ReadUnaligned16 ( > >>>> - IN CONST UINT16 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ); > >>>> > >>>> > >>>> @@ -2571,7 +2571,7 @@ ReadUnaligned16 ( > >>>> UINT16 > >>>> EFIAPI > >>>> WriteUnaligned16 ( > >>>> - OUT UINT16 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT16 Value > >>>> ); > >>>> > >>>> @@ -2592,7 +2592,7 @@ WriteUnaligned16 ( > >>>> UINT32 > >>>> EFIAPI > >>>> ReadUnaligned24 ( > >>>> - IN CONST UINT32 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ); > >>>> > >>>> > >>>> @@ -2614,7 +2614,7 @@ ReadUnaligned24 ( > >>>> UINT32 > >>>> EFIAPI > >>>> WriteUnaligned24 ( > >>>> - OUT UINT32 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT32 Value > >>>> ); > >>>> > >>>> @@ -2635,7 +2635,7 @@ WriteUnaligned24 ( > >>>> UINT32 > >>>> EFIAPI > >>>> ReadUnaligned32 ( > >>>> - IN CONST UINT32 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ); > >>>> > >>>> > >>>> @@ -2657,7 +2657,7 @@ ReadUnaligned32 ( > >>>> UINT32 > >>>> EFIAPI > >>>> WriteUnaligned32 ( > >>>> - OUT UINT32 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT32 Value > >>>> ); > >>>> > >>>> @@ -2678,7 +2678,7 @@ WriteUnaligned32 ( > >>>> UINT64 > >>>> EFIAPI > >>>> ReadUnaligned64 ( > >>>> - IN CONST UINT64 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ); > >>>> > >>>> > >>>> @@ -2700,7 +2700,7 @@ ReadUnaligned64 ( > >>>> UINT64 > >>>> EFIAPI > >>>> WriteUnaligned64 ( > >>>> - OUT UINT64 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT64 Value > >>>> ); > >>>> > >>>> diff --git a/MdePkg/Library/BaseLib/Arm/Unaligned.c > >>>> b/MdePkg/Library/BaseLib/Arm/Unaligned.c > >>>> index 34f1732..ef9efbc 100644 > >>>> --- a/MdePkg/Library/BaseLib/Arm/Unaligned.c > >>>> +++ b/MdePkg/Library/BaseLib/Arm/Unaligned.c > >>>> @@ -33,7 +33,7 @@ > >>>> UINT16 > >>>> EFIAPI > >>>> ReadUnaligned16 ( > >>>> - IN CONST UINT16 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> volatile UINT8 LowerByte; > >>>> @@ -65,7 +65,7 @@ ReadUnaligned16 ( > >>>> UINT16 > >>>> EFIAPI > >>>> WriteUnaligned16 ( > >>>> - OUT UINT16 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT16 Value > >>>> ) > >>>> { > >>>> @@ -93,7 +93,7 @@ WriteUnaligned16 ( > >>>> UINT32 > >>>> EFIAPI > >>>> ReadUnaligned24 ( > >>>> - IN CONST UINT32 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> ASSERT (Buffer != NULL); > >>>> @@ -122,7 +122,7 @@ ReadUnaligned24 ( > >>>> UINT32 > >>>> EFIAPI > >>>> WriteUnaligned24 ( > >>>> - OUT UINT32 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT32 Value > >>>> ) > >>>> { > >>>> @@ -149,7 +149,7 @@ WriteUnaligned24 ( > >>>> UINT32 > >>>> EFIAPI > >>>> ReadUnaligned32 ( > >>>> - IN CONST UINT32 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> UINT16 LowerBytes; > >>>> @@ -181,7 +181,7 @@ ReadUnaligned32 ( > >>>> UINT32 > >>>> EFIAPI > >>>> WriteUnaligned32 ( > >>>> - OUT UINT32 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT32 Value > >>>> ) > >>>> { > >>>> @@ -208,7 +208,7 @@ WriteUnaligned32 ( > >>>> UINT64 > >>>> EFIAPI > >>>> ReadUnaligned64 ( > >>>> - IN CONST UINT64 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> UINT32 LowerBytes; > >>>> @@ -240,7 +240,7 @@ ReadUnaligned64 ( > >>>> UINT64 > >>>> EFIAPI > >>>> WriteUnaligned64 ( > >>>> - OUT UINT64 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT64 Value > >>>> ) > >>>> { > >>>> diff --git a/MdePkg/Library/BaseLib/Ipf/Unaligned.c > >>>> b/MdePkg/Library/BaseLib/Ipf/Unaligned.c > >>>> index 7d0d8dd..5ba8029 100644 > >>>> --- a/MdePkg/Library/BaseLib/Ipf/Unaligned.c > >>>> +++ b/MdePkg/Library/BaseLib/Ipf/Unaligned.c > >>>> @@ -30,7 +30,7 @@ > >>>> UINT16 > >>>> EFIAPI > >>>> ReadUnaligned16 ( > >>>> - IN CONST UINT16 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> ASSERT (Buffer != NULL); > >>>> @@ -56,7 +56,7 @@ ReadUnaligned16 ( > >>>> UINT16 > >>>> EFIAPI > >>>> WriteUnaligned16 ( > >>>> - OUT UINT16 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT16 Value > >>>> ) > >>>> { > >>>> @@ -84,7 +84,7 @@ WriteUnaligned16 ( > >>>> UINT32 > >>>> EFIAPI > >>>> ReadUnaligned24 ( > >>>> - IN CONST UINT32 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> ASSERT (Buffer != NULL); > >>>> @@ -113,7 +113,7 @@ ReadUnaligned24 ( > >>>> UINT32 > >>>> EFIAPI > >>>> WriteUnaligned24 ( > >>>> - OUT UINT32 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT32 Value > >>>> ) > >>>> { > >>>> @@ -140,7 +140,7 @@ WriteUnaligned24 ( > >>>> UINT32 > >>>> EFIAPI > >>>> ReadUnaligned32 ( > >>>> - IN CONST UINT32 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> UINT16 LowerBytes; > >>>> @@ -172,7 +172,7 @@ ReadUnaligned32 ( > >>>> UINT32 > >>>> EFIAPI > >>>> WriteUnaligned32 ( > >>>> - OUT UINT32 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT32 Value > >>>> ) > >>>> { > >>>> @@ -199,7 +199,7 @@ WriteUnaligned32 ( > >>>> UINT64 > >>>> EFIAPI > >>>> ReadUnaligned64 ( > >>>> - IN CONST UINT64 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> UINT32 LowerBytes; > >>>> @@ -231,7 +231,7 @@ ReadUnaligned64 ( > >>>> UINT64 > >>>> EFIAPI > >>>> WriteUnaligned64 ( > >>>> - OUT UINT64 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT64 Value > >>>> ) > >>>> { > >>>> diff --git a/MdePkg/Library/BaseLib/Unaligned.c > >> b/MdePkg/Library/BaseLib/Unaligned.c > >>>> index 68dafa6..ed58861 100644 > >>>> --- a/MdePkg/Library/BaseLib/Unaligned.c > >>>> +++ b/MdePkg/Library/BaseLib/Unaligned.c > >>>> @@ -32,12 +32,14 @@ > >>>> UINT16 > >>>> EFIAPI > >>>> ReadUnaligned16 ( > >>>> - IN CONST UINT16 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> + CONST UINT16 *Input = Buffer; > >>>> + > >>>> ASSERT (Buffer != NULL); > >>>> > >>>> - return *Buffer; > >>>> + return *Input; > >>>> } > >>>> > >>>> /** > >>>> @@ -58,13 +60,15 @@ ReadUnaligned16 ( > >>>> UINT16 > >>>> EFIAPI > >>>> WriteUnaligned16 ( > >>>> - OUT UINT16 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT16 Value > >>>> ) > >>>> { > >>>> + UINT16 *Output = Buffer; > >>>> + > >>>> ASSERT (Buffer != NULL); > >>>> > >>>> - return *Buffer = Value; > >>>> + return *Output = Value; > >>>> } > >>>> > >>>> /** > >>>> @@ -83,12 +87,14 @@ WriteUnaligned16 ( > >>>> UINT32 > >>>> EFIAPI > >>>> ReadUnaligned24 ( > >>>> - IN CONST UINT32 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> + CONST UINT32 *Input = Buffer; > >>>> + > >>>> ASSERT (Buffer != NULL); > >>>> > >>>> - return *Buffer & 0xffffff; > >>>> + return *Input & 0xffffff; > >>>> } > >>>> > >>>> /** > >>>> @@ -109,13 +115,15 @@ ReadUnaligned24 ( > >>>> UINT32 > >>>> EFIAPI > >>>> WriteUnaligned24 ( > >>>> - OUT UINT32 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT32 Value > >>>> ) > >>>> { > >>>> + UINT32 *Output = Buffer; > >>>> + > >>>> ASSERT (Buffer != NULL); > >>>> > >>>> - *Buffer = BitFieldWrite32 (*Buffer, 0, 23, Value); > >>>> + *Output = BitFieldWrite32 (*Output, 0, 23, Value); > >>>> return Value; > >>>> } > >>>> > >>>> @@ -135,12 +143,14 @@ WriteUnaligned24 ( > >>>> UINT32 > >>>> EFIAPI > >>>> ReadUnaligned32 ( > >>>> - IN CONST UINT32 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> + CONST UINT32 *Input = Buffer; > >>>> + > >>>> ASSERT (Buffer != NULL); > >>>> > >>>> - return *Buffer; > >>>> + return *Input; > >>>> } > >>>> > >>>> /** > >>>> @@ -161,13 +171,15 @@ ReadUnaligned32 ( > >>>> UINT32 > >>>> EFIAPI > >>>> WriteUnaligned32 ( > >>>> - OUT UINT32 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT32 Value > >>>> ) > >>>> { > >>>> + UINT32 *Output = Buffer; > >>>> + > >>>> ASSERT (Buffer != NULL); > >>>> > >>>> - return *Buffer = Value; > >>>> + return *Output = Value; > >>>> } > >>>> > >>>> /** > >>>> @@ -186,12 +198,14 @@ WriteUnaligned32 ( > >>>> UINT64 > >>>> EFIAPI > >>>> ReadUnaligned64 ( > >>>> - IN CONST UINT64 *Buffer > >>>> + IN CONST VOID *Buffer > >>>> ) > >>>> { > >>>> + CONST UINT64 *Input = Buffer; > >>>> + > >>>> ASSERT (Buffer != NULL); > >>>> > >>>> - return *Buffer; > >>>> + return *Input; > >>>> } > >>>> > >>>> /** > >>>> @@ -212,11 +226,13 @@ ReadUnaligned64 ( > >>>> UINT64 > >>>> EFIAPI > >>>> WriteUnaligned64 ( > >>>> - OUT UINT64 *Buffer, > >>>> + OUT VOID *Buffer, > >>>> IN UINT64 Value > >>>> ) > >>>> { > >>>> + UINT64 *Output = Buffer; > >>>> + > >>>> ASSERT (Buffer != NULL); > >>>> > >>>> - return *Buffer = Value; > >>>> + return *Output = Value; > >>>> } > >>>> -- > >>>> 2.1.4 > >>> > > _______________________________________________ > > edk2-devel mailing list > > [email protected] > > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

