mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-04 08:16:49 +00:00
Keep track of the set of array index variables we use when we
synthesize a by-copy captured array in a lambda. This information will be needed by IR generation. llvm-svn: 150396
This commit is contained in:
parent
f299a55482
commit
54fcea6e16
@ -561,7 +561,8 @@ class CXXRecordDecl : public RecordDecl {
|
||||
typedef LambdaExpr::Capture Capture;
|
||||
|
||||
LambdaDefinitionData(CXXRecordDecl *D)
|
||||
: DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0), Extra(0) {
|
||||
: DefinitionData(D), NumCaptures(0), NumExplicitCaptures(0),
|
||||
HasArrayIndexVars(false), Extra(0) {
|
||||
IsLambda = true;
|
||||
}
|
||||
|
||||
@ -569,15 +570,22 @@ class CXXRecordDecl : public RecordDecl {
|
||||
unsigned NumCaptures : 16;
|
||||
|
||||
/// \brief The number of explicit captures in this lambda.
|
||||
unsigned NumExplicitCaptures : 16;
|
||||
unsigned NumExplicitCaptures : 15;
|
||||
|
||||
/// \brief Whether This lambda has any by-copy array captures, and therefore
|
||||
/// has array index variables.
|
||||
unsigned HasArrayIndexVars : 1;
|
||||
|
||||
/// \brief The "extra" data associated with the lambda, including
|
||||
/// captures, capture initializers, and the body of the lambda.
|
||||
/// captures, capture initializers, the body of the lambda, and the
|
||||
/// array-index variables for array captures.
|
||||
void *Extra;
|
||||
|
||||
/// \brief Allocate the "extra" data associated with a lambda definition.
|
||||
void allocateExtra(ArrayRef<Capture> Captures,
|
||||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayIndexVars,
|
||||
ArrayRef<unsigned> ArrayIndexStarts,
|
||||
Stmt *Body);
|
||||
|
||||
/// \brief Retrieve the set of captures.
|
||||
@ -588,6 +596,18 @@ class CXXRecordDecl : public RecordDecl {
|
||||
Stmt **getStoredStmts() const {
|
||||
return reinterpret_cast<Stmt **>(getCaptures() + NumCaptures);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the mapping from captures to the first array index
|
||||
/// variable.
|
||||
unsigned *getArrayIndexStarts() const {
|
||||
return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the complete set of array-index variables.
|
||||
VarDecl **getArrayIndexVars() const {
|
||||
return reinterpret_cast<VarDecl **>(
|
||||
getArrayIndexStarts() + NumCaptures + 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct DefinitionData &data() {
|
||||
|
@ -1066,22 +1066,16 @@ class LambdaExpr : public Expr {
|
||||
/// module file just to determine the source range.
|
||||
SourceLocation ClosingBrace;
|
||||
|
||||
// Note: The Create method allocates storage after the LambdaExpr
|
||||
// object, which contains the captures, followed by the capture
|
||||
// initializers, and finally the body of the lambda. The capture
|
||||
// initializers and lambda body are placed next to each other so
|
||||
// that the children() function can visit all of them easily.
|
||||
|
||||
public:
|
||||
/// \brief Describes the capture of either a variable or 'this'.
|
||||
class Capture {
|
||||
llvm::PointerIntPair<VarDecl *, 2> VarAndBits;
|
||||
SourceLocation Loc;
|
||||
SourceLocation EllipsisLoc;
|
||||
|
||||
|
||||
friend class ASTStmtReader;
|
||||
friend class ASTStmtWriter;
|
||||
|
||||
|
||||
public:
|
||||
/// \brief Create a new capture.
|
||||
///
|
||||
@ -1155,6 +1149,8 @@ private:
|
||||
ArrayRef<Capture> Captures,
|
||||
bool ExplicitParams,
|
||||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayIndexVars,
|
||||
ArrayRef<unsigned> ArrayIndexStarts,
|
||||
SourceLocation ClosingBrace);
|
||||
|
||||
public:
|
||||
@ -1166,6 +1162,8 @@ public:
|
||||
ArrayRef<Capture> Captures,
|
||||
bool ExplicitParams,
|
||||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayIndexVars,
|
||||
ArrayRef<unsigned> ArrayIndexStarts,
|
||||
SourceLocation ClosingBrace);
|
||||
|
||||
/// \brief Determine the default capture kind for this lambda.
|
||||
@ -1212,6 +1210,13 @@ public:
|
||||
/// initialization argument for this lambda expression.
|
||||
capture_init_iterator capture_init_end() const;
|
||||
|
||||
/// \brief Retrieve the set of index variables used in the capture
|
||||
/// initializer of an array captured by copy.
|
||||
///
|
||||
/// \param Iter The iterator that points at the capture initializer for
|
||||
/// which we are extracting the corresponding index variables.
|
||||
ArrayRef<VarDecl *> getCaptureInitIndexVars(capture_init_iterator Iter) const;
|
||||
|
||||
/// \brief Retrieve the source range covering the lambda introducer,
|
||||
/// which contains the explicit capture list surrounded by square
|
||||
/// brackets ([...]).
|
||||
|
@ -301,6 +301,13 @@ public:
|
||||
/// \brief Whether any of the capture expressions requires cleanups.
|
||||
bool ExprNeedsCleanups;
|
||||
|
||||
/// \brief Variables used to index into by-copy array captures.
|
||||
llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
|
||||
|
||||
/// \brief Offsets into the ArrayIndexVars array at which each capture starts
|
||||
/// its list of array index variables.
|
||||
llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
|
||||
|
||||
LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
|
||||
CXXMethodDecl *CallOperator)
|
||||
: CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
|
||||
|
@ -38,13 +38,23 @@ AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
||||
void CXXRecordDecl::LambdaDefinitionData::allocateExtra(
|
||||
ArrayRef<LambdaExpr::Capture> Captures,
|
||||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayIndexVars,
|
||||
ArrayRef<unsigned> ArrayIndexStarts,
|
||||
Stmt *Body) {
|
||||
NumCaptures = Captures.size();
|
||||
NumExplicitCaptures = 0;
|
||||
|
||||
ASTContext &Context = Definition->getASTContext();
|
||||
unsigned ArrayIndexSize = 0;
|
||||
if (ArrayIndexVars.size() > 0) {
|
||||
HasArrayIndexVars = true;
|
||||
ArrayIndexSize = sizeof(unsigned) * (Captures.size() + 1)
|
||||
+ sizeof(VarDecl *) * ArrayIndexVars.size();
|
||||
}
|
||||
|
||||
this->Extra = Context.Allocate(sizeof(Capture) * Captures.size() +
|
||||
sizeof(Stmt*) * (Captures.size() + 1));
|
||||
sizeof(Stmt*) * (Captures.size() + 1) +
|
||||
ArrayIndexSize);
|
||||
|
||||
// Copy captures.
|
||||
Capture *ToCapture = getCaptures();
|
||||
@ -62,6 +72,15 @@ void CXXRecordDecl::LambdaDefinitionData::allocateExtra(
|
||||
|
||||
// Copy the body of the lambda.
|
||||
*Stored++ = Body;
|
||||
|
||||
if (ArrayIndexVars.size() > 0) {
|
||||
assert(ArrayIndexStarts.size() == Captures.size());
|
||||
memcpy(getArrayIndexVars(), ArrayIndexVars.data(),
|
||||
sizeof(VarDecl *) * ArrayIndexVars.size());
|
||||
memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(),
|
||||
sizeof(unsigned) * Captures.size());
|
||||
getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -753,6 +753,8 @@ LambdaExpr::LambdaExpr(QualType T,
|
||||
ArrayRef<Capture> Captures,
|
||||
bool ExplicitParams,
|
||||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayElementVars,
|
||||
ArrayRef<unsigned> ArrayElementStarts,
|
||||
SourceLocation ClosingBrace)
|
||||
: Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
|
||||
T->isDependentType(), T->isDependentType(), T->isDependentType(),
|
||||
@ -765,7 +767,8 @@ LambdaExpr::LambdaExpr(QualType T,
|
||||
assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
|
||||
CXXRecordDecl *Class = getLambdaClass();
|
||||
CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData();
|
||||
Data.allocateExtra(Captures, CaptureInits, getCallOperator()->getBody());
|
||||
Data.allocateExtra(Captures, CaptureInits, ArrayElementVars,
|
||||
ArrayElementStarts, getCallOperator()->getBody());
|
||||
|
||||
// FIXME: Propagate "has unexpanded parameter pack" bit.
|
||||
}
|
||||
@ -777,6 +780,8 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
|
||||
ArrayRef<Capture> Captures,
|
||||
bool ExplicitParams,
|
||||
ArrayRef<Expr *> CaptureInits,
|
||||
ArrayRef<VarDecl *> ArrayElementVars,
|
||||
ArrayRef<unsigned> ArrayElementStarts,
|
||||
SourceLocation ClosingBrace) {
|
||||
// Determine the type of the expression (i.e., the type of the
|
||||
// function object we're creating).
|
||||
@ -784,6 +789,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context,
|
||||
|
||||
return new (Context) LambdaExpr(T, IntroducerRange, CaptureDefault,
|
||||
Captures, ExplicitParams, CaptureInits,
|
||||
ArrayElementVars, ArrayElementStarts,
|
||||
ClosingBrace);
|
||||
}
|
||||
|
||||
@ -826,6 +832,19 @@ LambdaExpr::capture_init_iterator LambdaExpr::capture_init_end() const {
|
||||
return reinterpret_cast<Expr **>(Data.getStoredStmts() + Data.NumCaptures);
|
||||
}
|
||||
|
||||
ArrayRef<VarDecl *>
|
||||
LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const {
|
||||
CXXRecordDecl::LambdaDefinitionData &Data = getLambdaClass()->getLambdaData();
|
||||
assert(Data.HasArrayIndexVars && "No array index-var data?");
|
||||
|
||||
unsigned Index = Iter - capture_init_begin();
|
||||
assert(Index < Data.NumCaptures && "Capture index out-of-range");
|
||||
VarDecl **IndexVars = Data.getArrayIndexVars();
|
||||
unsigned *IndexStarts = Data.getArrayIndexStarts();
|
||||
return ArrayRef<VarDecl *>(IndexVars + IndexStarts[Index],
|
||||
IndexVars + IndexStarts[Index + 1]);
|
||||
}
|
||||
|
||||
CXXRecordDecl *LambdaExpr::getLambdaClass() const {
|
||||
return getType()->getAsCXXRecordDecl();
|
||||
}
|
||||
|
@ -9642,6 +9642,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
|
||||
bool InitializingArray = false;
|
||||
QualType BaseType = FieldType;
|
||||
QualType SizeType = S.Context.getSizeType();
|
||||
LSI->ArrayIndexStarts.push_back(LSI->ArrayIndexVars.size());
|
||||
while (const ConstantArrayType *Array
|
||||
= S.Context.getAsConstantArrayType(BaseType)) {
|
||||
InitializingArray = true;
|
||||
@ -9660,7 +9661,8 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
|
||||
S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
|
||||
SC_None, SC_None);
|
||||
IndexVariables.push_back(IterationVar);
|
||||
|
||||
LSI->ArrayIndexVars.push_back(IterationVar);
|
||||
|
||||
// Create a reference to the iteration variable.
|
||||
ExprResult IterationVarRef
|
||||
= S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
|
||||
|
@ -306,6 +306,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
|
||||
SourceRange IntroducerRange;
|
||||
bool ExplicitParams;
|
||||
bool LambdaExprNeedsCleanups;
|
||||
llvm::SmallVector<VarDecl *, 4> ArrayIndexVars;
|
||||
llvm::SmallVector<unsigned, 4> ArrayIndexStarts;
|
||||
{
|
||||
LambdaScopeInfo *LSI = getCurLambda();
|
||||
CallOperator = LSI->CallOperator;
|
||||
@ -313,7 +315,9 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
|
||||
IntroducerRange = LSI->IntroducerRange;
|
||||
ExplicitParams = LSI->ExplicitParams;
|
||||
LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups;
|
||||
|
||||
ArrayIndexVars.swap(LSI->ArrayIndexVars);
|
||||
ArrayIndexStarts.swap(LSI->ArrayIndexStarts);
|
||||
|
||||
// Translate captures.
|
||||
for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
|
||||
LambdaScopeInfo::Capture From = LSI->Captures[I];
|
||||
@ -467,6 +471,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
|
||||
LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange,
|
||||
CaptureDefault, Captures,
|
||||
ExplicitParams, CaptureInits,
|
||||
ArrayIndexVars, ArrayIndexStarts,
|
||||
Body->getLocEnd());
|
||||
|
||||
// C++11 [expr.prim.lambda]p2:
|
||||
|
Loading…
x
Reference in New Issue
Block a user