Inline storage of attributes in AttributedStmt.

llvm-svn: 159925
This commit is contained in:
Alexander Kornienko 2012-07-09 10:04:07 +00:00
parent 75b9cfd1f0
commit 20f6fc6220
13 changed files with 85 additions and 45 deletions

View File

@ -149,8 +149,10 @@ typedef SmallVector<const Attr*, 2> ConstAttrVec;
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
/// providing attributes that are of a specifc type.
template <typename SpecificAttr>
template <typename SpecificAttr, typename Container = AttrVec>
class specific_attr_iterator {
typedef typename Container::const_iterator Iterator;
/// Current - The current, underlying iterator.
/// In order to ensure we don't dereference an invalid iterator unless
/// specifically requested, we don't necessarily advance this all the
@ -158,14 +160,14 @@ class specific_attr_iterator {
/// operation is acting on what should be a past-the-end iterator,
/// then we offer no guarantees, but this way we do not dererence a
/// past-the-end iterator when we move to a past-the-end position.
mutable AttrVec::const_iterator Current;
mutable Iterator Current;
void AdvanceToNext() const {
while (!isa<SpecificAttr>(*Current))
++Current;
}
void AdvanceToNext(AttrVec::const_iterator I) const {
void AdvanceToNext(Iterator I) const {
while (Current != I && !isa<SpecificAttr>(*Current))
++Current;
}
@ -178,7 +180,7 @@ public:
typedef std::ptrdiff_t difference_type;
specific_attr_iterator() : Current() { }
explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
explicit specific_attr_iterator(Iterator i) : Current(i) { }
reference operator*() const {
AdvanceToNext();
@ -213,23 +215,27 @@ public:
}
};
template <typename T>
inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
return specific_attr_iterator<T>(vec.begin());
template <typename SpecificAttr, typename Container>
inline specific_attr_iterator<SpecificAttr, Container>
specific_attr_begin(const Container& container) {
return specific_attr_iterator<SpecificAttr, Container>(container.begin());
}
template <typename T>
inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
return specific_attr_iterator<T>(vec.end());
template <typename SpecificAttr, typename Container>
inline specific_attr_iterator<SpecificAttr, Container>
specific_attr_end(const Container& container) {
return specific_attr_iterator<SpecificAttr, Container>(container.end());
}
template <typename T>
inline bool hasSpecificAttr(const AttrVec& vec) {
return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
template <typename SpecificAttr, typename Container>
inline bool hasSpecificAttr(const Container& container) {
return specific_attr_begin<SpecificAttr>(container) !=
specific_attr_end<SpecificAttr>(container);
}
template <typename T>
inline T *getSpecificAttr(const AttrVec& vec) {
specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
if (i != specific_attr_end<T>(vec))
template <typename SpecificAttr, typename Container>
inline SpecificAttr *getSpecificAttr(const Container& container) {
specific_attr_iterator<SpecificAttr, Container> i =
specific_attr_begin<SpecificAttr>(container);
if (i != specific_attr_end<SpecificAttr>(container))
return *i;
else
return 0;

View File

@ -797,24 +797,32 @@ public:
class AttributedStmt : public Stmt {
Stmt *SubStmt;
SourceLocation AttrLoc;
AttrVec Attrs;
// TODO: It can be done as Attr *Attrs[1]; and variable size array as in
// StringLiteral
unsigned NumAttrs;
const Attr *Attrs[1];
friend class ASTStmtReader;
public:
AttributedStmt(SourceLocation loc, const AttrVec &attrs, Stmt *substmt)
: Stmt(AttributedStmtClass), SubStmt(substmt), AttrLoc(loc), Attrs(attrs) {
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
: Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
NumAttrs(Attrs.size()) {
memcpy(this->Attrs, Attrs.data(), Attrs.size() * sizeof(Attr*));
}
// \brief Build an empty attributed statement.
explicit AttributedStmt(EmptyShell Empty)
: Stmt(AttributedStmtClass, Empty) {
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
: Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
memset(Attrs, 0, NumAttrs * sizeof(Attr*));
}
public:
static AttributedStmt *Create(ASTContext &C, SourceLocation Loc,
ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
// \brief Build an empty attributed statement.
static AttributedStmt *CreateEmpty(ASTContext &C, unsigned NumAttrs);
SourceLocation getAttrLoc() const { return AttrLoc; }
const AttrVec &getAttrs() const { return Attrs; }
ArrayRef<const Attr*> getAttrs() const {
return ArrayRef<const Attr*>(Attrs, NumAttrs);
}
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }

View File

@ -2467,7 +2467,8 @@ public:
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
SourceLocation ColonLoc, Stmt *SubStmt);
StmtResult ActOnAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
StmtResult ActOnAttributedStmt(SourceLocation AttrLoc,
ArrayRef<const Attr*> Attrs,
Stmt *SubStmt);
StmtResult ActOnIfStmt(SourceLocation IfLoc,

View File

@ -427,7 +427,7 @@ private:
void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
bool IsModule);
void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record);
void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record);
void ResolveDeclUpdatesBlocks();
void WriteDeclUpdatesBlocks();
void WriteDeclReplacementsBlock();

View File

@ -273,6 +273,23 @@ const char *LabelStmt::getName() const {
return getDecl()->getIdentifier()->getNameStart();
}
AttributedStmt *AttributedStmt::Create(ASTContext &C, SourceLocation Loc,
ArrayRef<const Attr*> Attrs,
Stmt *SubStmt) {
void *Mem = C.Allocate(sizeof(AttributedStmt) +
sizeof(Attr*) * (Attrs.size() - 1),
llvm::alignOf<AttributedStmt>());
return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
}
AttributedStmt *AttributedStmt::CreateEmpty(ASTContext &C, unsigned NumAttrs) {
assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
void *Mem = C.Allocate(sizeof(AttributedStmt) +
sizeof(Attr*) * (NumAttrs - 1),
llvm::alignOf<AttributedStmt>());
return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
}
// This is defined here to avoid polluting Stmt.h with importing Expr.h
SourceRange ReturnStmt::getSourceRange() const {
if (RetExpr)

View File

@ -173,9 +173,9 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
OS << "[[";
bool first = true;
for (AttrVec::const_iterator it = Node->getAttrs().begin(),
end = Node->getAttrs().end();
it != end; ++it) {
for (ArrayRef<const Attr*>::iterator it = Node->getAttrs().begin(),
end = Node->getAttrs().end();
it != end; ++it) {
if (!first) {
OS << ", ";
first = false;

View File

@ -370,12 +370,10 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
}
StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
const AttrVec &Attrs,
ArrayRef<const Attr*> Attrs,
Stmt *SubStmt) {
// Fill in the declaration and return it. Variable length will require to
// change this to AttributedStmt::Create(Context, ....);
// and probably using ArrayRef
AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt);
// Fill in the declaration and return it.
AttributedStmt *LS = AttributedStmt::Create(Context, AttrLoc, Attrs, SubStmt);
return Owned(LS);
}

View File

@ -61,7 +61,7 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
SourceRange Range) {
AttrVec Attrs;
SmallVector<const Attr*, 8> Attrs;
for (const AttributeList* l = AttrList; l; l = l->getNext()) {
if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
Attrs.push_back(a);

View File

@ -1050,7 +1050,8 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
StmtResult RebuildAttributedStmt(SourceLocation AttrLoc,
ArrayRef<const Attr*> Attrs,
Stmt *SubStmt) {
return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
}

View File

@ -162,9 +162,12 @@ void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {
VisitStmt(S);
uint64_t NumAttrs = Record[Idx++];
AttrVec Attrs;
Reader.ReadAttributes(F, Attrs, Record, Idx);
S->Attrs = Attrs;
assert(NumAttrs == S->NumAttrs);
assert(NumAttrs == Attrs.size());
std::copy(Attrs.begin(), Attrs.end(), S->Attrs);
S->SubStmt = Reader.ReadSubStmt();
S->AttrLoc = ReadSourceLocation(Record, Idx);
}
@ -1648,7 +1651,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_ATTRIBUTED:
S = new (Context) AttributedStmt(Empty);
S = AttributedStmt::CreateEmpty(
Context,
/*NumAttrs*/Record[ASTStmtReader::NumStmtFields]);
break;
case STMT_IF:

View File

@ -3086,10 +3086,12 @@ void ASTWriter::WriteMergedDecls() {
//===----------------------------------------------------------------------===//
/// \brief Write a record containing the given attributes.
void ASTWriter::WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record) {
void ASTWriter::WriteAttributes(ArrayRef<const Attr*> Attrs,
RecordDataImpl &Record) {
Record.push_back(Attrs.size());
for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){
const Attr * A = *i;
for (ArrayRef<const Attr *>::iterator i = Attrs.begin(),
e = Attrs.end(); i != e; ++i){
const Attr *A = *i;
Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
AddSourceRange(A->getRange(), Record);

View File

@ -151,7 +151,8 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
Record.push_back(D->isInvalidDecl());
Record.push_back(D->hasAttrs());
if (D->hasAttrs())
Writer.WriteAttributes(D->getAttrs(), Record);
Writer.WriteAttributes(ArrayRef<const Attr*>(D->getAttrs().begin(),
D->getAttrs().size()), Record);
Record.push_back(D->isImplicit());
Record.push_back(D->isUsed(false));
Record.push_back(D->isReferenced());

View File

@ -109,6 +109,7 @@ void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
void ASTStmtWriter::VisitAttributedStmt(AttributedStmt *S) {
VisitStmt(S);
Record.push_back(S->getAttrs().size());
Writer.WriteAttributes(S->getAttrs(), Record);
Writer.AddStmt(S->getSubStmt());
Writer.AddSourceLocation(S->getAttrLoc(), Record);