[PATCH] CodeGen for CapturedStmt

John McCall rjmccall at apple.com
Mon Apr 29 12:55:37 PDT 2013


On Apr 8, 2013, at 12:41 PM, Ben Langmuir <ben.langmuir at intel.com> wrote:
> Hi rjmccall, ABataev,
> 
> CodeGen for CapturedStmts
> 
> - EmitCapturedStmt creates a captured struct containing all of the captured
>  variables, and then emits a call to the outlined function.  This is similar
>  in principle to EmitBlockLiteral.
> 
> - GenerateCapturedFunction actually produces the outlined function.  It is based
>  on GenerateBlockFunction, but is much simpler.  The function type is currently
>  fixed, and the function contains only the body of the captured statement.
> 
> - When this is extended for different kinds of captured statements, I imagine
>  that hooks will be added to customize the function type/parameters, and insert
>  prologue/epilogue code.

Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -1684,6 +1684,9 @@
   assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
   DMEntry = DeclPtr;
 
+  if (CapturedStmtInfo && CapturedStmtInfo->isThisParmVarDecl(&D))
+    CapturedStmtInfo->setThisValue(Builder.CreateLoad(DeclPtr));
+

Is there a reason you can't do this in GenerateCapturedFunction?

+  // If CFG is emitting a captured statement and 'this' is captured,
+  // load it into CXXThisValue.
+  if (CapturedStmtInfo && CapturedStmtInfo->isCXXThisExprCaptured()) {
+    FieldDecl *FD = CapturedStmtInfo->getThisFieldDecl();
+    QualType TagType = getContext().getTagDeclType(FD->getParent());
+    LValue LV = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getThisValue(),
+                                           TagType);
+    LValue ThisLValue = EmitLValueForField(LV, FD);
+
+    CXXThisValue = EmitLoadOfLValue(ThisLValue).getScalarVal();
+  }
+

Similarly, this seems like something to do in GenerateCapturedFunction.

+      } else if (CapturedStmtInfo) {
+        if (const FieldDecl *FD = CapturedStmtInfo->lookup(VD)) {
+          QualType TagType = getContext().getTagDeclType(FD->getParent());
+          LValue LV
+            = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getThisValue(),
+                                         TagType);
+
+          return EmitLValueForField(LV, FD);
+        }

Please extract out a function to do this;  it's basically the same as the
lambda case right above it.

+  AggValueSlot Slot = CreateAggTemp(RecordTy, "agg.captured");
+  LValue SlotLV = MakeAddrLValue(Slot.getAddr(), RecordTy, Slot.getAlignment());

This is a weird use of AggValueSlot.  There should probably be a way to
create a variable as an l-value, but for now, please just do:
  SlotLV = MakeNaturalAlignAddrLValue(CreateMemTemp(...))

+    ArrayRef<VarDecl *> ArrayIndexes;
+    EmitInitializerForField(*CurField, LV, *I, ArrayIndexes);

Just pass ArrayRef<VarDecl*>() as an argument.

+CodeGenFunction::GenerateCapturedFunction(GlobalDecl GD,

I'd call this GenerateCapturedStmtFunction.

+  StartFunction(CD, Ctx.VoidTy, F, FuncInfo, Args, CD->getBody()->getLocStart());
+  // TODO: lots of code here in GenerateBlockFunction - is any of it needed here?

I'd look at what gets done for the start of a lambda function instead;
it's closer to the model you have.

It doesn't look like you map the ObjC 'self' variable.

Otherwise, this looks good, but please add some more recursive-capture
tests, most notably CapturedStmts inside CapturedStmts, but also (for
completeness) CapturedStmts inside blocks and vice-versa.

John.



More information about the cfe-commits mailing list