forked from OSchip/llvm-project
Fixes an IRgen bug where __block variable is
referenced in the block-literal initializer of that variable. // rdar://8893785 llvm-svn: 124332
This commit is contained in:
parent
fb4ee9bbde
commit
2f2fa7284b
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks -triple x86_64-apple-darwin10 | FileCheck %s
|
||||
// rdar://8893785
|
||||
|
||||
void MYFUNC() {
|
||||
// CHECK: [[T1:%.*]] = bitcast i8* ()*
|
||||
// CHECK-NEXT: [[FORWARDING:%.*]] = getelementptr inbounds [[N_T:%.*]]* [[N:%.*]], i32 0, i32 1
|
||||
// CHECK-NEXT: [[T0:%.*]] = load [[N_T]]** [[FORWARDING]]
|
||||
// CHECK-NEXT: [[OBSERVER:%.*]] = getelementptr inbounds [[N_T]]* [[T0]], i32 0, i32 6
|
||||
// CHECK-NEXT: store i8* [[T1]], i8** [[OBSERVER]]
|
||||
__block id observer = ^{ return observer; };
|
||||
}
|
||||
|
Loading…
Reference in New Issue