mirror of
https://github.com/intel/llvm.git
synced 2026-02-05 04:46:27 +08:00
Basic support for referring to captured variables from lambdas. Some simple examples seem to work. Tests coming up soon.
llvm-svn: 150293
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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>())
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user