aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDecl.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-01-26 23:08:27 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-01-26 23:08:27 +0000
commit52a80e19ad688091723a52ad53337767bb0ac684 (patch)
tree1f7640e3e6f00ff3c289fbf968d3b22ff2cc2b6b /lib/CodeGen/CGDecl.cpp
parentd1a2643a045b428ea3095f9fe18e7a0b54d61470 (diff)
Fixes an IRgen bug where __block variable is
referenced in the block-literal initializer of that variable. // rdar://8893785 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124332 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGDecl.cpp')
-rw-r--r--lib/CodeGen/CGDecl.cpp30
1 files changed, 27 insertions, 3 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 8270e84cb5..f12be98510 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -305,6 +305,15 @@ unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
return ByRefValueInfo.find(VD)->second.second;
}
+llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
+ const VarDecl *V) {
+ llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding");
+ Loc = Builder.CreateLoad(Loc);
+ Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V),
+ V->getNameAsString());
+ return Loc;
+}
+
/// BuildByRefType - This routine changes a __block variable declared as T x
/// into:
///
@@ -795,9 +804,6 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
SpecialInit(*this, D, DeclPtr);
} else if (Init) {
llvm::Value *Loc = DeclPtr;
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
bool isVolatile = getContext().getCanonicalType(Ty).isVolatileQualified();
@@ -844,13 +850,31 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
}
} else if (Ty->isReferenceType()) {
RValue RV = EmitReferenceBindingToExpr(Init, &D);
+ if (isByRef)
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Alignment, Ty);
} else if (!hasAggregateLLVMType(Init->getType())) {
llvm::Value *V = EmitScalarExpr(Init);
+ if (isByRef) {
+ // When RHS has side-effect, must go through "forwarding' field
+ // to get to the address of the __block variable descriptor.
+ if (Init->HasSideEffects(getContext()))
+ Loc = BuildBlockByrefAddress(DeclPtr, &D);
+ else
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
+ }
EmitStoreOfScalar(V, Loc, isVolatile, Alignment, Ty);
} else if (Init->getType()->isAnyComplexType()) {
+ if (isByRef)
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
EmitComplexExprIntoAddr(Init, Loc, isVolatile);
} else {
+ if (isByRef)
+ Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
+ D.getNameAsString());
EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false));
}
}