[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