Skip to content

Commit

Permalink
Implement IRGen of lambda expressions which capture arrays.
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150452 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
eefriedman committed Feb 14, 2012
1 parent 0bdb5aa commit b74ed08
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 63 deletions.
50 changes: 22 additions & 28 deletions lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,10 +534,6 @@ static bool hasTrivialCopyOrMoveConstructor(const CXXRecordDecl *Record,
Record->hasTrivialCopyConstructor();
}

static void EmitInitializerForField(CodeGenFunction &CGF, FieldDecl *Field,
LValue LHS, Expr *Init,
ArrayRef<VarDecl *> ArrayIndexes);

static void EmitMemberInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXCtorInitializer *MemberInit,
Expand Down Expand Up @@ -594,54 +590,52 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
ArrayRef<VarDecl *> ArrayIndexes;
if (MemberInit->getNumArrayIndices())
ArrayIndexes = MemberInit->getArrayIndexes();
EmitInitializerForField(CGF, Field, LHS, MemberInit->getInit(), ArrayIndexes);
CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes);
}

static void EmitInitializerForField(CodeGenFunction &CGF, FieldDecl *Field,
LValue LHS, Expr *Init,
ArrayRef<VarDecl *> ArrayIndexes) {
void CodeGenFunction::EmitInitializerForField(FieldDecl *Field,
LValue LHS, Expr *Init,
ArrayRef<VarDecl *> ArrayIndexes) {
QualType FieldType = Field->getType();
if (!CGF.hasAggregateLLVMType(FieldType)) {
if (!hasAggregateLLVMType(FieldType)) {
if (LHS.isSimple()) {
CGF.EmitExprAsInit(Init, Field, LHS, false);
EmitExprAsInit(Init, Field, LHS, false);
} else {
RValue RHS = RValue::get(CGF.EmitScalarExpr(Init));
CGF.EmitStoreThroughLValue(RHS, LHS);
RValue RHS = RValue::get(EmitScalarExpr(Init));
EmitStoreThroughLValue(RHS, LHS);
}
} else if (FieldType->isAnyComplexType()) {
CGF.EmitComplexExprIntoAddr(Init, LHS.getAddress(),
LHS.isVolatileQualified());
EmitComplexExprIntoAddr(Init, LHS.getAddress(), LHS.isVolatileQualified());
} else {
llvm::Value *ArrayIndexVar = 0;
if (ArrayIndexes.size()) {
llvm::Type *SizeTy
= CGF.ConvertType(CGF.getContext().getSizeType());
llvm::Type *SizeTy = ConvertType(getContext().getSizeType());

// The LHS is a pointer to the first object we'll be constructing, as
// a flat array.
QualType BaseElementTy = CGF.getContext().getBaseElementType(FieldType);
llvm::Type *BasePtr = CGF.ConvertType(BaseElementTy);
QualType BaseElementTy = getContext().getBaseElementType(FieldType);
llvm::Type *BasePtr = ConvertType(BaseElementTy);
BasePtr = llvm::PointerType::getUnqual(BasePtr);
llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(LHS.getAddress(),
BasePtr);
LHS = CGF.MakeAddrLValue(BaseAddrPtr, BaseElementTy);
llvm::Value *BaseAddrPtr = Builder.CreateBitCast(LHS.getAddress(),
BasePtr);
LHS = MakeAddrLValue(BaseAddrPtr, BaseElementTy);

// Create an array index that will be used to walk over all of the
// objects we're constructing.
ArrayIndexVar = CGF.CreateTempAlloca(SizeTy, "object.index");
ArrayIndexVar = CreateTempAlloca(SizeTy, "object.index");
llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
CGF.Builder.CreateStore(Zero, ArrayIndexVar);
Builder.CreateStore(Zero, ArrayIndexVar);


// Emit the block variables for the array indices, if any.
for (unsigned I = 0, N = ArrayIndexes.size(); I != N; ++I)
CGF.EmitAutoVarDecl(*ArrayIndexes[I]);
EmitAutoVarDecl(*ArrayIndexes[I]);
}

EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar, FieldType,
EmitAggMemberInitializer(*this, LHS, Init, ArrayIndexVar, FieldType,
ArrayIndexes, 0);

if (!CGF.CGM.getLangOptions().Exceptions)
if (!CGM.getLangOptions().Exceptions)
return;

// FIXME: If we have an array of classes w/ non-trivial destructors,
Expand All @@ -653,8 +647,8 @@ static void EmitInitializerForField(CodeGenFunction &CGF, FieldDecl *Field,

CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (!RD->hasTrivialDestructor())
CGF.EHStack.pushCleanup<CallMemberDtor>(EHCleanup, LHS.getAddress(),
RD->getDestructor());
EHStack.pushCleanup<CallMemberDtor>(EHCleanup, LHS.getAddress(),
RD->getDestructor());
}
}

Expand Down
39 changes: 4 additions & 35 deletions lib/CodeGen/CGExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1765,49 +1765,18 @@ 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) {
RunCleanupsScope Scope(*this);

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());
ArrayRef<VarDecl *> ArrayIndexes;
if (CurField->getType()->isArrayType())
ArrayIndexes = E->getCaptureInitIndexVars(i);
EmitInitializerForField(*CurField, LV, *i, ArrayIndexes);
}
}
3 changes: 3 additions & 0 deletions lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,9 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type,
FunctionArgList &Args);

void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init,
ArrayRef<VarDecl *> ArrayIndexes);

/// InitializeVTablePointer - Initialize the vtable pointer of the given
/// subobject.
///
Expand Down

0 comments on commit b74ed08

Please sign in to comment.