[AST] Store the expressions in ParenListExpr in a trailing array

Use the newly available space in the bit-fields of Stmt
and store the expressions in a trailing array. This saves
2 pointer per ParenListExpr.

Differential Revision: https://reviews.llvm.org/D54675

Reviewed By: rjmccall

llvm-svn: 347320
This commit is contained in:
Bruno Ricci 2018-11-20 16:20:40 +00:00
parent 855dfee2c2
commit f49e1ca04d
9 changed files with 97 additions and 53 deletions

View File

@ -4844,31 +4844,46 @@ public:
}
};
class ParenListExpr : public Expr {
Stmt **Exprs;
unsigned NumExprs;
class ParenListExpr final
: public Expr,
private llvm::TrailingObjects<ParenListExpr, Stmt *> {
friend class ASTStmtReader;
friend TrailingObjects;
/// The location of the left and right parentheses.
SourceLocation LParenLoc, RParenLoc;
public:
ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
ArrayRef<Expr*> exprs, SourceLocation rparenloc);
/// Build a paren list.
ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs,
SourceLocation RParenLoc);
/// Build an empty paren list.
explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
ParenListExpr(EmptyShell Empty, unsigned NumExprs);
unsigned getNumExprs() const { return NumExprs; }
public:
/// Create a paren list.
static ParenListExpr *Create(const ASTContext &Ctx, SourceLocation LParenLoc,
ArrayRef<Expr *> Exprs,
SourceLocation RParenLoc);
const Expr* getExpr(unsigned Init) const {
/// Create an empty paren list.
static ParenListExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs);
/// Return the number of expressions in this paren list.
unsigned getNumExprs() const { return ParenListExprBits.NumExprs; }
Expr *getExpr(unsigned Init) {
assert(Init < getNumExprs() && "Initializer access out of range!");
return cast_or_null<Expr>(Exprs[Init]);
return getExprs()[Init];
}
Expr* getExpr(unsigned Init) {
assert(Init < getNumExprs() && "Initializer access out of range!");
return cast_or_null<Expr>(Exprs[Init]);
const Expr *getExpr(unsigned Init) const {
return const_cast<ParenListExpr *>(this)->getExpr(Init);
}
Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); }
Expr **getExprs() {
return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>());
}
ArrayRef<Expr *> exprs() {
return llvm::makeArrayRef(getExprs(), getNumExprs());
@ -4876,9 +4891,8 @@ public:
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }
SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
SourceLocation getBeginLoc() const { return getLParenLoc(); }
SourceLocation getEndLoc() const { return getRParenLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ParenListExprClass;
@ -4886,14 +4900,13 @@ public:
// Iterators
child_range children() {
return child_range(&Exprs[0], &Exprs[0]+NumExprs);
return child_range(getTrailingObjects<Stmt *>(),
getTrailingObjects<Stmt *>() + getNumExprs());
}
const_child_range children() const {
return const_child_range(&Exprs[0], &Exprs[0] + NumExprs);
return const_child_range(getTrailingObjects<Stmt *>(),
getTrailingObjects<Stmt *>() + getNumExprs());
}
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
/// Represents a C11 generic selection.

View File

@ -496,6 +496,16 @@ protected:
unsigned HadArrayRangeDesignator : 1;
};
class ParenListExprBitfields {
friend class ASTStmtReader;
friend class ParenListExpr;
unsigned : NumExprBits;
/// The number of expressions in the paren list.
unsigned NumExprs;
};
class PseudoObjectExprBitfields {
friend class ASTStmtReader; // deserialization
friend class PseudoObjectExpr;
@ -672,6 +682,7 @@ protected:
CastExprBitfields CastExprBits;
BinaryOperatorBitfields BinaryOperatorBits;
InitListExprBitfields InitListExprBits;
ParenListExprBitfields ParenListExprBits;
PseudoObjectExprBitfields PseudoObjectExprBits;
// C++ Expressions

View File

@ -6409,8 +6409,8 @@ ExpectedStmt ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
if (!ToRParenLocOrErr)
return ToRParenLocOrErr.takeError();
return new (Importer.getToContext()) ParenListExpr(
Importer.getToContext(), *ToLParenLocOrErr, ToExprs, *ToRParenLocOrErr);
return ParenListExpr::Create(Importer.getToContext(), *ToLParenLocOrErr,
ToExprs, *ToRParenLocOrErr);
}
ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {

View File

@ -4004,27 +4004,48 @@ SourceLocation DesignatedInitUpdateExpr::getEndLoc() const {
return getBase()->getEndLoc();
}
ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
ArrayRef<Expr*> exprs,
SourceLocation rparenloc)
: Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary,
false, false, false, false),
NumExprs(exprs.size()), LParenLoc(lparenloc), RParenLoc(rparenloc) {
Exprs = new (C) Stmt*[exprs.size()];
for (unsigned i = 0; i != exprs.size(); ++i) {
if (exprs[i]->isTypeDependent())
ParenListExpr::ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs,
SourceLocation RParenLoc)
: Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
false, false),
LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
ParenListExprBits.NumExprs = Exprs.size();
for (unsigned I = 0, N = Exprs.size(); I != N; ++I) {
if (Exprs[I]->isTypeDependent())
ExprBits.TypeDependent = true;
if (exprs[i]->isValueDependent())
if (Exprs[I]->isValueDependent())
ExprBits.ValueDependent = true;
if (exprs[i]->isInstantiationDependent())
if (Exprs[I]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (exprs[i]->containsUnexpandedParameterPack())
if (Exprs[I]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
Exprs[i] = exprs[i];
getTrailingObjects<Stmt *>()[I] = Exprs[I];
}
}
ParenListExpr::ParenListExpr(EmptyShell Empty, unsigned NumExprs)
: Expr(ParenListExprClass, Empty) {
ParenListExprBits.NumExprs = NumExprs;
}
ParenListExpr *ParenListExpr::Create(const ASTContext &Ctx,
SourceLocation LParenLoc,
ArrayRef<Expr *> Exprs,
SourceLocation RParenLoc) {
void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(Exprs.size()),
alignof(ParenListExpr));
return new (Mem) ParenListExpr(LParenLoc, Exprs, RParenLoc);
}
ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx,
unsigned NumExprs) {
void *Mem =
Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumExprs), alignof(ParenListExpr));
return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
}
const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e))
e = ewc->getSubExpr();

View File

@ -565,8 +565,8 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
// Create an initialization sequence for the promise type using the
// constructor arguments, wrapped in a parenthesized list expression.
Expr *PLE = new (Context) ParenListExpr(Context, FD->getLocation(),
CtorArgExprs, FD->getLocation());
Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(),
CtorArgExprs, FD->getLocation());
InitializedEntity Entity = InitializedEntity::InitializeVariable(VD);
InitializationKind Kind = InitializationKind::CreateForInit(
VD->getLocation(), /*DirectInit=*/true, PLE);

View File

@ -3731,8 +3731,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,
ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
Expr *List = new (Context) ParenListExpr(Context, LParenLoc,
Args, RParenLoc);
Expr *List = ParenListExpr::Create(Context, LParenLoc, Args, RParenLoc);
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
DS, IdLoc, List, EllipsisLoc);
}

View File

@ -6410,8 +6410,7 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
ExprResult Sema::ActOnParenListExpr(SourceLocation L,
SourceLocation R,
MultiExprArg Val) {
Expr *expr = new (Context) ParenListExpr(Context, L, Val, R);
return expr;
return ParenListExpr::Create(Context, L, Val, R);
}
/// Emit a specialized diagnostic when one expression is a null pointer

View File

@ -643,10 +643,9 @@ void ASTStmtReader::VisitParenExpr(ParenExpr *E) {
void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) {
VisitExpr(E);
unsigned NumExprs = Record.readInt();
E->Exprs = new (Record.getContext()) Stmt*[NumExprs];
for (unsigned i = 0; i != NumExprs; ++i)
E->Exprs[i] = Record.readSubStmt();
E->NumExprs = NumExprs;
assert((NumExprs == E->getNumExprs()) && "Wrong NumExprs!");
for (unsigned I = 0; I != NumExprs; ++I)
E->getTrailingObjects<Stmt *>()[I] = Record.readSubStmt();
E->LParenLoc = ReadSourceLocation();
E->RParenLoc = ReadSourceLocation();
}
@ -2452,7 +2451,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_PAREN_LIST:
S = new (Context) ParenListExpr(Empty);
S = ParenListExpr::CreateEmpty(
Context,
/* NumExprs=*/Record[ASTStmtReader::NumExprFields + 0]);
break;
case EXPR_UNARY_OPERATOR:

View File

@ -559,11 +559,11 @@ void ASTStmtWriter::VisitParenExpr(ParenExpr *E) {
void ASTStmtWriter::VisitParenListExpr(ParenListExpr *E) {
VisitExpr(E);
Record.push_back(E->NumExprs);
for (unsigned i=0; i != E->NumExprs; ++i)
Record.AddStmt(E->Exprs[i]);
Record.AddSourceLocation(E->LParenLoc);
Record.AddSourceLocation(E->RParenLoc);
Record.push_back(E->getNumExprs());
for (auto *SubStmt : E->exprs())
Record.AddStmt(SubStmt);
Record.AddSourceLocation(E->getLParenLoc());
Record.AddSourceLocation(E->getRParenLoc());
Code = serialization::EXPR_PAREN_LIST;
}