diff options
author | Anders Carlsson <andersca@mac.com> | 2009-09-12 02:44:18 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-09-12 02:44:18 +0000 |
commit | 18be84c37b2b796fddfb36447c2b29141d7fdd18 (patch) | |
tree | 0871e8d92d16b24197e130876a07b8860a691e99 | |
parent | 7dfa4079f4b37507048b19bfc693d3b015d9dd11 (diff) |
Add support for __block variables with alignment greater than __alignof(void *).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81602 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 79 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 9 | ||||
-rw-r--r-- | test/CodeGen/blocks-aligned-byref-variable.c | 11 |
4 files changed, 70 insertions, 31 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index b8827793d6..ad03e368e0 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -227,11 +227,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF | // FIXME: Someone double check this. (VD->getType().isObjCGCWeak() ? BLOCK_FIELD_IS_WEAK : 0); - const llvm::Type *Ty = Types[i+5]; llvm::Value *Loc = LocalDeclMap[VD]; Loc = Builder.CreateStructGEP(Loc, 1, "forwarding"); Loc = Builder.CreateLoad(Loc, false); - Loc = Builder.CreateBitCast(Loc, Ty); Builder.CreateStore(Loc, Addr); ++helpersize; continue; diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index eae5a0d113..05c2533d6f 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -224,41 +224,76 @@ const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) { return Info.first; QualType Ty = D->getType(); - uint64_t Align = getContext().getDeclAlignInBytes(D); - (void) Align; - const llvm::Type *LTy = ConvertType(Ty); - bool needsCopyDispose = BlockRequiresCopying(Ty); - std::vector<const llvm::Type *> Types(needsCopyDispose*2+5); - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext)); + std::vector<const llvm::Type *> Types; + const llvm::PointerType *Int8PtrTy + = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext)); + llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(VMContext); - Types[0] = PtrToInt8Ty; - Types[1] = llvm::PointerType::getUnqual(ByRefTypeHolder); - Types[2] = llvm::Type::getInt32Ty(VMContext); - Types[3] = llvm::Type::getInt32Ty(VMContext); - if (needsCopyDispose) { - Types[4] = PtrToInt8Ty; - Types[5] = PtrToInt8Ty; - } - // FIXME: Align this on at least an Align boundary, assert if we can't. - assert((Align <= unsigned(Target.getPointerAlign(0))/8) - && "Can't align more than pointer yet"); + // void *__isa; + Types.push_back(Int8PtrTy); - unsigned FieldNumber = needsCopyDispose*2 + 4; + // void *__forwarding; + Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder)); - Types[FieldNumber] = LTy; + // int32_t __flags; + Types.push_back(llvm::Type::getInt32Ty(VMContext)); + + // int32_t __size; + Types.push_back(llvm::Type::getInt32Ty(VMContext)); + + bool HasCopyAndDispose = BlockRequiresCopying(Ty); + if (HasCopyAndDispose) { + /// void *__copy_helper; + Types.push_back(Int8PtrTy); + + /// void *__destroy_helper; + Types.push_back(Int8PtrTy); + } + + bool Packed = false; + unsigned Align = getContext().getDeclAlignInBytes(D); + if (Align > Target.getPointerAlign(0) / 8) { + // We have to insert padding. + + // The struct above has 2 32-bit integers. + unsigned CurrentOffsetInBytes = 4 * 2; + + // And either 2 or 4 pointers. + CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) * + CGM.getTargetData().getTypeAllocSize(Int8PtrTy); + + // Align the offset. + unsigned AlignedOffsetInBytes = + llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align); + + unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; + assert(NumPaddingBytes > 0 && "Can't append any padding!"); + + const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext); + if (NumPaddingBytes > 1) + Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); + + Types.push_back(Ty); + + // We want a packed struct. + Packed = true; + } + + // T x; + Types.push_back(ConvertType(Ty)); - const llvm::Type *T = llvm::StructType::get(VMContext, Types, false); + const llvm::Type *T = llvm::StructType::get(VMContext, Types, Packed); cast<llvm::OpaqueType>(ByRefTypeHolder.get())->refineAbstractTypeTo(T); CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), ByRefTypeHolder.get()); Info.first = ByRefTypeHolder.get(); - Info.second = FieldNumber; + + Info.second = Types.size() - 1; return Info.first; } diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index c6d5b24b11..1141dd6b02 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -716,15 +716,10 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (!NonGCable) attr = getContext().getObjCGCAttrKind(E->getType()); if (VD->hasAttr<BlocksAttr>()) { - bool needsCopyDispose = BlockRequiresCopying(VD->getType()); - const llvm::Type *PtrStructTy = V->getType(); - const llvm::Type *Ty = PtrStructTy; - Ty = llvm::PointerType::get(Ty, 0); V = Builder.CreateStructGEP(V, 1, "forwarding"); - V = Builder.CreateBitCast(V, Ty); V = Builder.CreateLoad(V, false); - V = Builder.CreateBitCast(V, PtrStructTy); - V = Builder.CreateStructGEP(V, needsCopyDispose*2 + 4, "x"); + V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD), + VD->getNameAsString()); } if (VD->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); diff --git a/test/CodeGen/blocks-aligned-byref-variable.c b/test/CodeGen/blocks-aligned-byref-variable.c new file mode 100644 index 0000000000..975c03a43c --- /dev/null +++ b/test/CodeGen/blocks-aligned-byref-variable.c @@ -0,0 +1,11 @@ +// RUN: clang-cc -emit-llvm -o - +typedef int __attribute__((aligned(32))) ai; + +void f() { + __block ai a = 10; + + ^{ + a = 20; + }(); +} + |