summaryrefslogtreecommitdiffstats
path: root/clang/lib
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
commit2f2fa7284bd949310b69692cbca921bbdac956a0 (patch)
tree8b240cd158892162850ccc42814b41f5991cc2f2 /clang/lib
parentfb4ee9bbde8b3f1511f245eaef996f3fcc3e4d6b (diff)
downloadbcm5719-llvm-2f2fa7284bd949310b69692cbca921bbdac956a0.tar.gz
bcm5719-llvm-2f2fa7284bd949310b69692cbca921bbdac956a0.zip
Fixes an IRgen bug where __block variable is
referenced in the block-literal initializer of that variable. // rdar://8893785 llvm-svn: 124332
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp30
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp9
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h6
3 files changed, 35 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 8270e84cb5d..f12be985101 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/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));
}
}
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index afc1e0709ed..ca80d3dd38e 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1164,12 +1164,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
V = CGM.getStaticLocalDeclAddress(VD);
assert(V && "DeclRefExpr not entered in LocalDeclMap?");
- if (VD->hasAttr<BlocksAttr>()) {
- V = Builder.CreateStructGEP(V, 1, "forwarding");
- V = Builder.CreateLoad(V);
- V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD),
- VD->getNameAsString());
- }
+ if (VD->hasAttr<BlocksAttr>())
+ V = BuildBlockByrefAddress(V, VD);
+
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index dcd61737633..834a1cfa2f9 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -811,7 +811,11 @@ public:
/// getByrefValueFieldNumber - Given a declaration, returns the LLVM field
/// number that holds the value.
unsigned getByRefValueLLVMField(const ValueDecl *VD) const;
-
+
+ /// BuildBlockByrefAddress - Computes address location of the
+ /// variable which is declared as __block.
+ llvm::Value *BuildBlockByrefAddress(llvm::Value *BaseAddr,
+ const VarDecl *V);
private:
CGDebugInfo *DebugInfo;
OpenPOWER on IntegriCloud