diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-02-11 02:57:39 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-02-11 02:57:39 +0000 |
commit | cec5ebd4a6a89a7023d04cec728fd340b541ed61 (patch) | |
tree | ba89ba17ed6bc4f88a8cbb9e393a0d9979e5f58a | |
parent | 668165ab1e604b063c0aa0df8ff91c80879670bf (diff) |
Basic support for referring to captured variables from lambdas. Some simple examples seem to work. Tests coming up soon.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150293 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 34 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 6 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 2 |
6 files changed, 42 insertions, 11 deletions
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index 760068a9cb..5e21bb0c9f 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -49,10 +49,10 @@ protected: protected: ImplicitParamDecl *&getThisDecl(CodeGenFunction &CGF) { - return CGF.CXXThisDecl; + return CGF.CXXABIThisDecl; } llvm::Value *&getThisValue(CodeGenFunction &CGF) { - return CGF.CXXThisValue; + return CGF.CXXABIThisValue; } ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) { diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 85b01387e8..ae4084ba6c 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1396,6 +1396,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { llvm::Value *V = LocalDeclMap[VD]; if (!V && VD->isStaticLocal()) V = CGM.getStaticLocalDeclAddress(VD); + + // Use special handling for lambdas. + if (!V) + if (FieldDecl *FD = LambdaCaptureFields.lookup(VD)) + return EmitLValueForField(CXXABIThisValue, FD, 0); + assert(V && "DeclRefExpr not entered in LocalDeclMap?"); if (VD->hasAttr<BlocksAttr>()) diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index f13cae11a6..c5383b6704 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -329,6 +329,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, SourceLocation()); CGM.getCXXABI().EmitInstanceFunctionProlog(*this); + CXXThisValue = CXXABIThisValue; // Adjust the 'this' pointer if necessary. llvm::Value *AdjustedThisPtr = diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index e59794c71c..5c269ff06a 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -29,15 +29,16 @@ using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) : CodeGenTypeCache(cgm), CGM(cgm), - Target(CGM.getContext().getTargetInfo()), Builder(cgm.getModule().getContext()), + Target(CGM.getContext().getTargetInfo()), + Builder(cgm.getModule().getContext()), AutoreleaseResult(false), BlockInfo(0), BlockPointer(0), - NormalCleanupDest(0), NextCleanupDestIndex(1), FirstBlockInfo(0), - EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0), + LambdaThisCaptureField(0), NormalCleanupDest(0), NextCleanupDestIndex(1), + FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0), DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), - CXXThisDecl(0), CXXThisValue(0), CXXVTTDecl(0), CXXVTTValue(0), - OutermostConditional(0), TerminateLandingPad(0), TerminateHandler(0), - TrapBB(0) { + CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), CXXVTTDecl(0), + CXXVTTValue(0), OutermostConditional(0), TerminateLandingPad(0), + TerminateHandler(0), TrapBB(0) { CatchUndefined = getContext().getLangOptions().CatchUndefined; CGM.getCXXABI().getMangleContext().startNewFunction(); @@ -350,8 +351,27 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, PrologueCleanupDepth = EHStack.stable_begin(); EmitFunctionProlog(*CurFnInfo, CurFn, Args); - if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) + if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) { CGM.getCXXABI().EmitInstanceFunctionProlog(*this); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); + if (MD->getParent()->isLambda() && + MD->getOverloadedOperator() == OO_Call) { + // We're in a lambda; figure out the captures. + MD->getParent()->getCaptureFields(LambdaCaptureFields, + LambdaThisCaptureField); + if (LambdaThisCaptureField) { + // If this lambda captures this, load it. + LValue ThisLValue = EmitLValueForField(CXXABIThisValue, + LambdaThisCaptureField, 0); + CXXThisValue = EmitLoadOfLValue(ThisLValue).getScalarVal(); + } + } else { + // Not in a lambda; just use 'this' from the method. + // FIXME: Should we generate a new load for each use of 'this'? The + // fast register allocator would be happier... + CXXThisValue = CXXABIThisValue; + } + } // If any of the arguments have a variably modified type, make sure to // emit the type size. diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index e9766ab933..277640b8ce 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -599,6 +599,9 @@ public: const CodeGen::CGBlockInfo *BlockInfo; llvm::Value *BlockPointer; + llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; + FieldDecl *LambdaThisCaptureField; + /// \brief A mapping from NRVO variables to the flags used to indicate /// when the NRVO has been applied to this variable. llvm::DenseMap<const VarDecl *, llvm::Value *> NRVOFlags; @@ -1164,7 +1167,8 @@ private: /// CXXThisDecl - When generating code for a C++ member function, /// this will hold the implicit 'this' declaration. - ImplicitParamDecl *CXXThisDecl; + ImplicitParamDecl *CXXABIThisDecl; + llvm::Value *CXXABIThisValue; llvm::Value *CXXThisValue; /// CXXVTTDecl - When generating code for a base object constructor or diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 98819e9c25..044b7f0532 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -734,7 +734,7 @@ void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { /// Initialize the return slot to 'this' at the start of the /// function. if (HasThisReturn(CGF.CurGD)) - CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue); + CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); } void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, |