r306364 - [CodeGen][ObjC] Fix GNU's encoding of bit-field ivars.
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 26 21:34:05 PDT 2017
Author: ahatanak
Date: Mon Jun 26 21:34:04 2017
New Revision: 306364
URL: http://llvm.org/viewvc/llvm-project?rev=306364&view=rev
Log:
[CodeGen][ObjC] Fix GNU's encoding of bit-field ivars.
According to the documentation, when encoding a bit-field, GNU runtime
needs its starting position in addition to its type and size.
https://gcc.gnu.org/onlinedocs/gcc/Type-encoding.html
Prior to r297702, the starting position information was not being
encoded, which is incorrect, and after r297702, an assertion started to
fail because an ObjCIvarDecl was being passed to a function expecting a
FieldDecl.
This commit moves LookupFieldBitOffset to ASTContext and uses the
function to encode the starting position of bit-fields.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp
cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=306364&r1=306363&r2=306364&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Jun 26 21:34:04 2017
@@ -2050,6 +2050,11 @@ public:
/// Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
uint64_t getFieldOffset(const ValueDecl *FD) const;
+ /// Get the offset of an ObjCIvarDecl in bits.
+ uint64_t lookupFieldBitOffset(const ObjCInterfaceDecl *OID,
+ const ObjCImplementationDecl *ID,
+ const ObjCIvarDecl *Ivar) const;
+
bool isNearlyEmpty(const CXXRecordDecl *RD) const;
VTableContextBase *getVTableContext();
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=306364&r1=306363&r2=306364&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Jun 26 21:34:04 2017
@@ -5990,9 +5990,19 @@ static void EncodeBitField(const ASTCont
// compatibility with GCC, although providing it breaks anything that
// actually uses runtime introspection and wants to work on both runtimes...
if (Ctx->getLangOpts().ObjCRuntime.isGNUFamily()) {
- const RecordDecl *RD = FD->getParent();
- const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
- S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex()));
+ uint64_t Offset;
+
+ if (const auto *IVD = dyn_cast<ObjCIvarDecl>(FD)) {
+ Offset = Ctx->lookupFieldBitOffset(IVD->getContainingInterface(), nullptr,
+ IVD);
+ } else {
+ const RecordDecl *RD = FD->getParent();
+ const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
+ Offset = RL.getFieldOffset(FD->getFieldIndex());
+ }
+
+ S += llvm::utostr(Offset);
+
if (const EnumType *ET = T->getAs<EnumType>())
S += ObjCEncodingForEnumType(Ctx, ET);
else {
Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=306364&r1=306363&r2=306364&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Mon Jun 26 21:34:04 2017
@@ -3073,6 +3073,41 @@ uint64_t ASTContext::getFieldOffset(cons
return OffsetInBits;
}
+uint64_t ASTContext::lookupFieldBitOffset(const ObjCInterfaceDecl *OID,
+ const ObjCImplementationDecl *ID,
+ const ObjCIvarDecl *Ivar) const {
+ const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
+
+ // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
+ // in here; it should never be necessary because that should be the lexical
+ // decl context for the ivar.
+
+ // If we know have an implementation (and the ivar is in it) then
+ // look up in the implementation layout.
+ const ASTRecordLayout *RL;
+ if (ID && declaresSameEntity(ID->getClassInterface(), Container))
+ RL = &getASTObjCImplementationLayout(ID);
+ else
+ RL = &getASTObjCInterfaceLayout(Container);
+
+ // Compute field index.
+ //
+ // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
+ // implemented. This should be fixed to get the information from the layout
+ // directly.
+ unsigned Index = 0;
+
+ for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
+ IVD; IVD = IVD->getNextIvar()) {
+ if (Ivar == IVD)
+ break;
+ ++Index;
+ }
+ assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
+
+ return RL->getFieldOffset(Index);
+}
+
/// getObjCLayout - Get or compute information about the layout of the
/// given interface.
///
Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp?rev=306364&r1=306363&r2=306364&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.cpp Mon Jun 26 21:34:04 2017
@@ -26,61 +26,27 @@
using namespace clang;
using namespace CodeGen;
-static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
- const ObjCInterfaceDecl *OID,
- const ObjCImplementationDecl *ID,
- const ObjCIvarDecl *Ivar) {
- const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
-
- // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
- // in here; it should never be necessary because that should be the lexical
- // decl context for the ivar.
-
- // If we know have an implementation (and the ivar is in it) then
- // look up in the implementation layout.
- const ASTRecordLayout *RL;
- if (ID && declaresSameEntity(ID->getClassInterface(), Container))
- RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
- else
- RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
-
- // Compute field index.
- //
- // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
- // implemented. This should be fixed to get the information from the layout
- // directly.
- unsigned Index = 0;
-
- for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin();
- IVD; IVD = IVD->getNextIvar()) {
- if (Ivar == IVD)
- break;
- ++Index;
- }
- assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
-
- return RL->getFieldOffset(Index);
-}
-
uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *OID,
const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, OID, nullptr, Ivar) /
- CGM.getContext().getCharWidth();
+ return CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar) /
+ CGM.getContext().getCharWidth();
}
uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
const ObjCImplementationDecl *OID,
const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) /
- CGM.getContext().getCharWidth();
+ return CGM.getContext().lookupFieldBitOffset(OID->getClassInterface(), OID,
+ Ivar) /
+ CGM.getContext().getCharWidth();
}
unsigned CGObjCRuntime::ComputeBitfieldBitOffset(
CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, ID, ID->getImplementation(), Ivar);
+ return CGM.getContext().lookupFieldBitOffset(ID, ID->getImplementation(),
+ Ivar);
}
LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
@@ -119,7 +85,8 @@ LValue CGObjCRuntime::EmitValueForIvarAt
// Note, there is a subtle invariant here: we can only call this routine on
// non-synthesized ivars but we may be called for synthesized ivars. However,
// a synthesized ivar can never be a bit-field, so this is safe.
- uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, nullptr, Ivar);
+ uint64_t FieldBitOffset =
+ CGF.CGM.getContext().lookupFieldBitOffset(OID, nullptr, Ivar);
uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth();
uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign();
uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext());
Modified: cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m?rev=306364&r1=306363&r2=306364&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m (original)
+++ cfe/trunk/test/CodeGenObjC/ivar-type-encoding.m Mon Jun 26 21:34:04 2017
@@ -33,3 +33,19 @@ int main() {
// CHECK: @1 = private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
// CHECK: @2 = private unnamed_addr constant [9 x i8] c"_intIvar\00"
// CHECK: @3 = private unnamed_addr constant [2 x i8] c"i\00"
+
+ at interface Class1 {
+ int : 3;
+ short : 2;
+ long long ll;
+ char : 1;
+}
+ at end
+
+ at implementation Class1
+ at end
+
+// CHECK: @{{.*}} = private unnamed_addr constant [5 x i8] c"b0i3\00"
+// CHECK: @{{.*}} = private unnamed_addr constant [5 x i8] c"b3s2\00"
+// CHECK: @{{.*}} = private unnamed_addr constant [2 x i8] c"q\00"
+// CHECK: @{{.*}} = private unnamed_addr constant [7 x i8] c"b128c1\00"
More information about the cfe-commits
mailing list