Refactor lambda IRGen so AggExprEmitter::VisitLambdaExpr does the right thing.

llvm-svn: 150146
This commit is contained in:
Eli Friedman 2012-02-09 03:32:31 +00:00
parent 5a294e6a2c
commit c370a7eec7
4 changed files with 57 additions and 47 deletions

View File

@ -2361,55 +2361,10 @@ CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
return MakeAddrLValue(Slot.getAddr(), E->getType());
}
namespace {
struct CallLambdaMemberDtor : EHScopeStack::Cleanup {
FieldDecl *Field;
CXXDestructorDecl *Dtor;
llvm::Value *Lambda;
CallLambdaMemberDtor(FieldDecl *Field, CXXDestructorDecl *Dtor,
llvm::Value *Lambda)
: Field(Field), Dtor(Dtor), Lambda(Lambda) {}
void Emit(CodeGenFunction &CGF, Flags flags) {
LValue LHS = CGF.EmitLValueForField(Lambda, Field, 0);
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
LHS.getAddress());
}
};
}
LValue
CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) {
AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin();
CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
for (LambdaExpr::capture_init_iterator i = E->capture_init_begin(),
e = E->capture_init_end();
i != e; ++i, ++CurField) {
// FIXME: Add array handling
// FIXME: Try to refactor with CodeGenFunction::EmitCtorPrologue
// Emit initialization
LValue LV = EmitLValueForFieldInitialization(Slot.getAddr(), *CurField, 0);
EmitExprAsInit(*i, *CurField, LV, false);
// Add temporary cleanup to handle the case where a later initialization
// throws.
if (!CGM.getLangOptions().Exceptions)
continue;
const RecordType *RT = CurField->getType()->getAs<RecordType>();
if (!RT)
continue;
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (!RD->hasTrivialDestructor())
EHStack.pushCleanup<CallLambdaMemberDtor>(EHCleanup, *CurField,
RD->getDestructor(),
Slot.getAddr());
}
PopCleanupBlocks(CleanupDepth);
EmitLambdaExpr(E, Slot);
return MakeAddrLValue(Slot.getAddr(), E->getType());
}

View File

@ -142,12 +142,12 @@ public:
}
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
void VisitCXXConstructExpr(const CXXConstructExpr *E);
void VisitLambdaExpr(LambdaExpr *E);
void VisitExprWithCleanups(ExprWithCleanups *E);
void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
void VisitCXXTypeidExpr(CXXTypeidExpr *E) { EmitAggLoadOfLValue(E); }
void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
void VisitOpaqueValueExpr(OpaqueValueExpr *E);
void VisitLambdaExpr(LambdaExpr *E) { EmitAggLoadOfLValue(E); }
void VisitPseudoObjectExpr(PseudoObjectExpr *E) {
if (E->isGLValue()) {
@ -539,6 +539,12 @@ AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) {
CGF.EmitCXXConstructExpr(E, Slot);
}
void
AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) {
AggValueSlot Slot = EnsureSlot(E->getType());
CGF.EmitLambdaExpr(E, Slot);
}
void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
CGF.enterFullExpression(E);
CodeGenFunction::RunCleanupsScope cleanups(CGF);

View File

@ -1764,3 +1764,50 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
return Value;
}
namespace {
struct CallLambdaMemberDtor : EHScopeStack::Cleanup {
FieldDecl *Field;
CXXDestructorDecl *Dtor;
llvm::Value *Lambda;
CallLambdaMemberDtor(FieldDecl *Field, CXXDestructorDecl *Dtor,
llvm::Value *Lambda)
: Field(Field), Dtor(Dtor), Lambda(Lambda) {}
void Emit(CodeGenFunction &CGF, Flags flags) {
LValue LHS = CGF.EmitLValueForField(Lambda, Field, 0);
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
LHS.getAddress());
}
};
}
void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin();
CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
for (LambdaExpr::capture_init_iterator i = E->capture_init_begin(),
e = E->capture_init_end();
i != e; ++i, ++CurField) {
// FIXME: Add array handling
// FIXME: Try to refactor with CodeGenFunction::EmitCtorPrologue
// Emit initialization
LValue LV = EmitLValueForFieldInitialization(Slot.getAddr(), *CurField, 0);
EmitExprAsInit(*i, *CurField, LV, false);
// Add temporary cleanup to handle the case where a later initialization
// throws.
if (!CGM.getLangOptions().Exceptions)
continue;
const RecordType *RT = CurField->getType()->getAs<RecordType>();
if (!RT)
continue;
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (!RD->hasTrivialDestructor())
EHStack.pushCleanup<CallLambdaMemberDtor>(EHCleanup, *CurField,
RD->getDestructor(),
Slot.getAddr());
}
PopCleanupBlocks(CleanupDepth);
}

View File

@ -2400,6 +2400,8 @@ public:
void EmitCXXThrowExpr(const CXXThrowExpr *E);
void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest);
RValue EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest = 0);
//===--------------------------------------------------------------------===//