]> granicus.if.org Git - clang/commitdiff
Basic support for referring to captured variables from lambdas. Some simple examples...
authorEli Friedman <eli.friedman@gmail.com>
Sat, 11 Feb 2012 02:57:39 +0000 (02:57 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sat, 11 Feb 2012 02:57:39 +0000 (02:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150293 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXXABI.h
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGVTables.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/ItaniumCXXABI.cpp

index 760068a9cb469716c10e5e48b5c0bcf7592ad5a7..5e21bb0c9f121fd0354bd961027273cc0f47c262 100644 (file)
@@ -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) {
index 85b01387e8346b09db5332fcb59d24d22cb2812f..ae4084ba6ce7cc464e54c54b0fffa37bd05106fb 100644 (file)
@@ -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>())
index f13cae11a6e209c971f47c20e902a2baf0d2eb4a..c5383b670450f887211bbb08d3a1c83f351401f0 100644 (file)
@@ -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 = 
index e59794c71c701d9de30f3288d826369100afd2fa..5c269ff06ada3417326e002e0be4fed362dc0fff 100644 (file)
@@ -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.
index e9766ab9335f4c8560af499d601b5c178613f924..277640b8ce513c46de3bed67de9b94714f10ece8 100644 (file)
@@ -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
index 98819e9c2587c5b425312c3b8db53928a66eba39..044b7f0532eda490f1014e7d404707807594ade7 100644 (file)
@@ -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,