[cfe-dev] Managing bugfixes that cause struct-layout changes

David Majnemer david.majnemer at gmail.com
Mon Jul 13 16:55:54 PDT 2015


Shouldn't a diagnostic be given if the path returning the incorrect
calculation would return a result that disagrees from the correct
calculation?

On Mon, Jul 13, 2015 at 1:45 AM, Ristow, Warren <
warren_ristow at playstation.sony.com> wrote:

>  Hi,
>
>
>
> We at Sony have a particularly strong interest in not breaking object file
> compatibility from release to release.  So when a bug exists in release X,
> which gets fixed in release Y, where that bugfix is an ABI-breaking change,
> we generally have to weigh the pluses of fixing the bug against the minuses
> of breaking our object compatibility goal.  The impact of object file
> incompatibility is quite bad for us, and so we likely are more concerned
> than most toolchain providers about this issue.  But that said, I would
> imagine there are others out there that have some concerns along these
> lines.  I'm curious to hear about preferred methods of dealing with this.
>
>
>
> A straightforward solution is for us simply to guard an ABI-breaking
> bugfix with our PS4-triple.  Conceptually:
>
>
>
>   if (TargetIsPS4) {
>
>     // old way, with known bug, to retain object compatibility
>
>   } else {
>
>     // new way, that fixes bug, but breaks object compatibility
>
>   }
>
>
>
> But if others are interested in retaining the compatibility, then instead,
> something like the following may be preferred:
>
>
>
>   if (TargetUsesBuggyApproachX) {
>
>     // old way, with known bug, to retain object compatibility
>
>   } else {
>
>     // new way, that fixes bug, but breaks object compatibility
>
>   }
>
>
>
> where the concept of "Target Uses Buggy Approach X" is implemented by, for
> example, adding another single-bit bitfield to the TargetInfo class, and
> initializing it appropriately for different targets.
>
>
>
> To be more specific, a current example of an ABI-breaking issue for us is
> PR22279:
>
>
>
>   https://llvm.org/bugs/show_bug.cgi?id=22279
>
>
>
> As described there, a bugfix in the handling of alignment attributes (and
> alignas()) for enums causes a change in object layout.  For our customers,
> and hence for us, the fix in proper alignment of enum types in these cases
> isn't as important as retaining object compatibility.  So we need to
> suppress that fix.  It's easy enough for us to suppress the change by
> checking whether the target is PS4, but adding a bit to TargetInfo like:
>
>
>
>   unsigned IgnoreEnumTypeAlignment : 1;
>
>
>
> seems better.  I'm appending a patch on clang below, that shows this
> approach concretely.
>
>
>
> Or possibly there is some other preferred approach?  I'm curious to hear
> people's opinions.
>
>
>
> Thanks,
>
> -Warren
>
>
>
> --
>
> Warren Ristow
>
> SN Systems - Sony Computer Entertainment Group
>
>
>
>
>
> diff --git include/clang/Basic/TargetInfo.h
> include/clang/Basic/TargetInfo.h
>
> index fed69a8..7aca509 100644
>
> --- include/clang/Basic/TargetInfo.h
>
> +++ include/clang/Basic/TargetInfo.h
>
> @@ -84,6 +84,7 @@ protected:
>
>    mutable VersionTuple PlatformMinVersion;
>
>
>
>    unsigned HasAlignMac68kSupport : 1;
>
> +  unsigned IgnoreEnumTypeAlignment : 1;
>
>    unsigned RealTypeUsesObjCFPRet : 3;
>
>    unsigned ComplexLongDoubleUsesFP2Ret : 1;
>
>
>
> @@ -463,6 +464,11 @@ public:
>
>      return HasAlignMac68kSupport;
>
>    }
>
>
>
> +  /// \brief Ignore alignment specifier on definitions of enum types
>
> +  bool ignoreEnumTypeAlignment() const {
>
> +    return IgnoreEnumTypeAlignment;
>
> +  }
>
> +
>
>    /// \brief Return the user string for the specified integer type enum.
>
>    ///
>
>    /// For example, SignedShort -> "short".
>
> diff --git lib/AST/ASTContext.cpp lib/AST/ASTContext.cpp
>
> index fb96301..6a76ef3 100644
>
> --- lib/AST/ASTContext.cpp
>
> +++ lib/AST/ASTContext.cpp
>
> @@ -1705,6 +1705,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T)
> const {
>
>
>
>      if (const EnumType *ET = dyn_cast<EnumType>(TT)) {
>
>        const EnumDecl *ED = ET->getDecl();
>
> +      if (getTargetInfo().ignoreEnumTypeAlignment())
>
> +        return getTypeInfo(ED->getIntegerType());
>
>        TypeInfo Info =
>
>
> getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType());
>
>        if (unsigned AttrAlign = ED->getMaxAlignment()) {
>
> @@ -1846,7 +1848,8 @@ unsigned ASTContext::getPreferredTypeAlign(const
> Type *T) const {
>
>    if (const ComplexType *CT = T->getAs<ComplexType>())
>
>      T = CT->getElementType().getTypePtr();
>
>    if (const EnumType *ET = T->getAs<EnumType>())
>
> -    T = ET->getDecl()->getIntegerType().getTypePtr();
>
> +    if (!getTargetInfo().ignoreEnumTypeAlignment())
>
> +      T = ET->getDecl()->getIntegerType().getTypePtr();
>
>    if (T->isSpecificBuiltinType(BuiltinType::Double) ||
>
>        T->isSpecificBuiltinType(BuiltinType::LongLong) ||
>
>        T->isSpecificBuiltinType(BuiltinType::ULongLong))
>
> diff --git lib/Basic/TargetInfo.cpp lib/Basic/TargetInfo.cpp
>
> index 856ad50..99ed923 100644
>
> --- lib/Basic/TargetInfo.cpp
>
> +++ lib/Basic/TargetInfo.cpp
>
> @@ -76,6 +76,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) :
> TargetOpts(), Triple(T) {
>
>    RegParmMax = 0;
>
>    SSERegParmMax = 0;
>
>    HasAlignMac68kSupport = false;
>
> +  IgnoreEnumTypeAlignment = false;
>
>
>
>    // Default to no types using fpret.
>
>    RealTypeUsesObjCFPRet = 0;
>
> diff --git lib/Basic/Targets.cpp lib/Basic/Targets.cpp
>
> index c5bf90f..b93343b 100644
>
> --- lib/Basic/Targets.cpp
>
> +++ lib/Basic/Targets.cpp
>
> @@ -580,6 +580,14 @@ public:
>
>    PS4OSTargetInfo(const llvm::Triple &Triple) :
> OSTargetInfo<Target>(Triple) {
>
>      this->WCharType = this->UnsignedShort;
>
>
>
> +    // On PS4, for object compatibility with compilers prior to the fix of
>
> +    // PR22279, we ignore alignment specifiers on definitions of enum
> types.
>
> +    // For example, in the following fragment, the alignment of 'y' will
>
> +    // be 4, rather than 16:
>
> +    //    enum Y { val1, val2, val3 } __attribute__((aligned(16)));
>
> +    //    Y y;
>
> +    IgnoreEnumTypeAlignment = true;
>
> +
>
>      this->UserLabelPrefix = "";
>
>
>
>      switch (Triple.getArch()) {
>
> diff --git lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaDeclAttr.cpp
>
> index b8d0830..3843fcb 100644
>
> --- lib/Sema/SemaDeclAttr.cpp
>
> +++ lib/Sema/SemaDeclAttr.cpp
>
> @@ -3024,8 +3024,9 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {
>
>      UnderlyingTy = DiagTy = VD->getType();
>
>    } else {
>
>      UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
>
> -    if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
>
> -      UnderlyingTy = ED->getIntegerType();
>
> +    if (!Context.getTargetInfo().ignoreEnumTypeAlignment())
>
> +      if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
>
> +        UnderlyingTy = ED->getIntegerType();
>
>    }
>
>    if (DiagTy->isDependentType() || DiagTy->isIncompleteType())
>
>      return;
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150713/35d17f8e/attachment.html>


More information about the cfe-dev mailing list