aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGBlocks.cpp2
-rw-r--r--lib/CodeGen/CGDecl.cpp79
-rw-r--r--lib/CodeGen/CGExpr.cpp9
-rw-r--r--test/CodeGen/blocks-aligned-byref-variable.c11
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;
+ }();
+}
+