forked from OSchip/llvm-project
PCH support for indirect gotos and address-of-label expressions.
llvm-svn: 69369
This commit is contained in:
parent
70a42144ca
commit
779d865b48
|
@ -1601,12 +1601,22 @@ public:
|
|||
QualType t)
|
||||
: Expr(AddrLabelExprClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
|
||||
|
||||
/// \brief Build an empty address of a label expression.
|
||||
explicit AddrLabelExpr(EmptyShell Empty)
|
||||
: Expr(AddrLabelExprClass, Empty) { }
|
||||
|
||||
SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; }
|
||||
void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; }
|
||||
SourceLocation getLabelLoc() const { return LabelLoc; }
|
||||
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(AmpAmpLoc, LabelLoc);
|
||||
}
|
||||
|
||||
LabelStmt *getLabel() const { return Label; }
|
||||
|
||||
void setLabel(LabelStmt *S) { Label = S; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == AddrLabelExprClass;
|
||||
}
|
||||
|
|
|
@ -852,13 +852,18 @@ public:
|
|||
class IndirectGotoStmt : public Stmt {
|
||||
Stmt *Target;
|
||||
// FIXME: Add location information (e.g. SourceLocation objects).
|
||||
// When doing so, update the serialization routines.
|
||||
// When doing so, update the PCH serialization routines.
|
||||
public:
|
||||
IndirectGotoStmt(Expr *target) : Stmt(IndirectGotoStmtClass),
|
||||
Target((Stmt*)target){}
|
||||
|
||||
/// \brief Build an empty indirect goto statement.
|
||||
explicit IndirectGotoStmt(EmptyShell Empty)
|
||||
: Stmt(IndirectGotoStmtClass, Empty) { }
|
||||
|
||||
Expr *getTarget();
|
||||
const Expr *getTarget() const;
|
||||
void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(); }
|
||||
|
||||
|
|
|
@ -397,6 +397,8 @@ namespace clang {
|
|||
STMT_FOR,
|
||||
/// \brief A GotoStmt record.
|
||||
STMT_GOTO,
|
||||
/// \brief An IndirectGotoStmt record.
|
||||
STMT_INDIRECT_GOTO,
|
||||
/// \brief A ContinueStmt record.
|
||||
STMT_CONTINUE,
|
||||
/// \brief A BreakStmt record.
|
||||
|
@ -405,6 +407,7 @@ namespace clang {
|
|||
STMT_RETURN,
|
||||
/// \brief A DeclStmt record.
|
||||
STMT_DECL,
|
||||
/// FIXME: An AsmStmt record.
|
||||
/// \brief A PredefinedExpr record.
|
||||
EXPR_PREDEFINED,
|
||||
/// \brief A DeclRefExpr record.
|
||||
|
@ -453,7 +456,8 @@ namespace clang {
|
|||
EXPR_IMPLICIT_VALUE_INIT,
|
||||
/// \brief A VAArgExpr record.
|
||||
EXPR_VA_ARG,
|
||||
// FIXME: AddrLabelExpr
|
||||
// An AddrLabelExpr record.
|
||||
EXPR_ADDR_LABEL,
|
||||
// FIXME: StmtExpr
|
||||
/// \brief A TypesCompatibleExpr record.
|
||||
EXPR_TYPES_COMPATIBLE,
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace llvm {
|
|||
|
||||
namespace clang {
|
||||
|
||||
class AddrLabelExpr;
|
||||
class ASTContext;
|
||||
class Attr;
|
||||
class Decl;
|
||||
|
@ -143,6 +144,11 @@ private:
|
|||
/// de-serialized.
|
||||
std::multimap<unsigned, GotoStmt *> UnresolvedGotoStmts;
|
||||
|
||||
/// \brief Mapping from label IDs to the set of address label
|
||||
/// expressions that point to that label before the label itself has
|
||||
/// been de-serialized.
|
||||
std::multimap<unsigned, AddrLabelExpr *> UnresolvedAddrLabelExprs;
|
||||
|
||||
PCHReadResult ReadPCHBlock();
|
||||
bool CheckPredefinesBuffer(const char *PCHPredef,
|
||||
unsigned PCHPredefLen,
|
||||
|
@ -278,6 +284,15 @@ public:
|
|||
/// immediately (updating the statement) or it may queue the
|
||||
/// statement to be back-patched later.
|
||||
void SetLabelOf(GotoStmt *S, unsigned ID);
|
||||
|
||||
/// \brief Set the label of the given expression to the label
|
||||
/// identified by ID.
|
||||
///
|
||||
/// Depending on the order in which the label and other statements
|
||||
/// referencing that label occur, this operation may complete
|
||||
/// immediately (updating the statement) or it may queue the
|
||||
/// statement to be back-patched later.
|
||||
void SetLabelOf(AddrLabelExpr *S, unsigned ID);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -256,6 +256,7 @@ namespace {
|
|||
unsigned VisitDoStmt(DoStmt *S);
|
||||
unsigned VisitForStmt(ForStmt *S);
|
||||
unsigned VisitGotoStmt(GotoStmt *S);
|
||||
unsigned VisitIndirectGotoStmt(IndirectGotoStmt *S);
|
||||
unsigned VisitContinueStmt(ContinueStmt *S);
|
||||
unsigned VisitBreakStmt(BreakStmt *S);
|
||||
unsigned VisitReturnStmt(ReturnStmt *S);
|
||||
|
@ -287,6 +288,7 @@ namespace {
|
|||
unsigned VisitDesignatedInitExpr(DesignatedInitExpr *E);
|
||||
unsigned VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
|
||||
unsigned VisitVAArgExpr(VAArgExpr *E);
|
||||
unsigned VisitAddrLabelExpr(AddrLabelExpr *E);
|
||||
unsigned VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
|
||||
unsigned VisitChooseExpr(ChooseExpr *E);
|
||||
unsigned VisitGNUNullExpr(GNUNullExpr *E);
|
||||
|
@ -407,6 +409,12 @@ unsigned PCHStmtReader::VisitGotoStmt(GotoStmt *S) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
|
||||
VisitStmt(S);
|
||||
S->setTarget(cast_or_null<Expr>(StmtStack.back()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitContinueStmt(ContinueStmt *S) {
|
||||
VisitStmt(S);
|
||||
S->setContinueLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
|
@ -733,6 +741,14 @@ unsigned PCHStmtReader::VisitVAArgExpr(VAArgExpr *E) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
|
||||
VisitExpr(E);
|
||||
E->setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
E->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
Reader.SetLabelOf(E, Record[Idx++]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PCHStmtReader::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
|
||||
VisitExpr(E);
|
||||
E->setArgType1(Reader.GetType(Record[Idx++]));
|
||||
|
@ -2218,6 +2234,10 @@ Stmt *PCHReader::ReadStmt() {
|
|||
case pch::STMT_GOTO:
|
||||
S = new (Context) GotoStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_INDIRECT_GOTO:
|
||||
S = new (Context) IndirectGotoStmt(Empty);
|
||||
break;
|
||||
|
||||
case pch::STMT_CONTINUE:
|
||||
S = new (Context) ContinueStmt(Empty);
|
||||
|
@ -2335,6 +2355,10 @@ Stmt *PCHReader::ReadStmt() {
|
|||
S = new (Context) VAArgExpr(Empty);
|
||||
break;
|
||||
|
||||
case pch::EXPR_ADDR_LABEL:
|
||||
S = new (Context) AddrLabelExpr(Empty);
|
||||
break;
|
||||
|
||||
case pch::EXPR_TYPES_COMPATIBLE:
|
||||
S = new (Context) TypesCompatibleExpr(Empty);
|
||||
break;
|
||||
|
@ -2418,6 +2442,16 @@ void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
|
|||
for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
|
||||
Goto->second->setLabel(S);
|
||||
UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
|
||||
|
||||
// If we've already seen any address-label statements that point to
|
||||
// this label, resolve them now.
|
||||
typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
|
||||
std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
|
||||
= UnresolvedAddrLabelExprs.equal_range(ID);
|
||||
for (AddrLabelIter AddrLabel = AddrLabels.first;
|
||||
AddrLabel != AddrLabels.second; ++AddrLabel)
|
||||
AddrLabel->second->setLabel(S);
|
||||
UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
|
||||
}
|
||||
|
||||
/// \brief Set the label of the given statement to the label
|
||||
|
@ -2439,3 +2473,23 @@ void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
|
|||
UnresolvedGotoStmts.insert(std::make_pair(ID, S));
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Set the label of the given expression to the label
|
||||
/// identified by ID.
|
||||
///
|
||||
/// Depending on the order in which the label and other statements
|
||||
/// referencing that label occur, this operation may complete
|
||||
/// immediately (updating the statement) or it may queue the
|
||||
/// statement to be back-patched later.
|
||||
void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
|
||||
std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
|
||||
if (Label != LabelStmts.end()) {
|
||||
// We've already seen this label, so set the label of the
|
||||
// label-address expression and we're done.
|
||||
S->setLabel(Label->second);
|
||||
} else {
|
||||
// We haven't seen this label yet, so add this label-address
|
||||
// expression to the set of unresolved label-address expressions.
|
||||
UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -458,6 +458,7 @@ namespace {
|
|||
void VisitDoStmt(DoStmt *S);
|
||||
void VisitForStmt(ForStmt *S);
|
||||
void VisitGotoStmt(GotoStmt *S);
|
||||
void VisitIndirectGotoStmt(IndirectGotoStmt *S);
|
||||
void VisitContinueStmt(ContinueStmt *S);
|
||||
void VisitBreakStmt(BreakStmt *S);
|
||||
void VisitReturnStmt(ReturnStmt *S);
|
||||
|
@ -489,6 +490,7 @@ namespace {
|
|||
void VisitDesignatedInitExpr(DesignatedInitExpr *E);
|
||||
void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
|
||||
void VisitVAArgExpr(VAArgExpr *E);
|
||||
void VisitAddrLabelExpr(AddrLabelExpr *E);
|
||||
void VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
|
||||
void VisitChooseExpr(ChooseExpr *E);
|
||||
void VisitGNUNullExpr(GNUNullExpr *E);
|
||||
|
@ -601,6 +603,12 @@ void PCHStmtWriter::VisitGotoStmt(GotoStmt *S) {
|
|||
Code = pch::STMT_GOTO;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
|
||||
VisitStmt(S);
|
||||
Writer.WriteSubStmt(S->getTarget());
|
||||
Code = pch::STMT_INDIRECT_GOTO;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) {
|
||||
VisitStmt(S);
|
||||
Writer.AddSourceLocation(S->getContinueLoc(), Record);
|
||||
|
@ -880,6 +888,14 @@ void PCHStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
|
|||
Code = pch::EXPR_VA_ARG;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
|
||||
VisitExpr(E);
|
||||
Writer.AddSourceLocation(E->getAmpAmpLoc(), Record);
|
||||
Writer.AddSourceLocation(E->getLabelLoc(), Record);
|
||||
Record.push_back(Writer.GetLabelID(E->getLabel()));
|
||||
Code = pch::EXPR_ADDR_LABEL;
|
||||
}
|
||||
|
||||
void PCHStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
|
||||
VisitExpr(E);
|
||||
Writer.AddTypeRef(E->getArgType1(), Record);
|
||||
|
|
|
@ -8,3 +8,5 @@
|
|||
void g0(void) { f0(5); }
|
||||
int g1(int x) { return f1(x); }
|
||||
const char* query_name(void) { return what_is_my_name(); }
|
||||
|
||||
int use_computed_goto(int x) { return computed_goto(x); }
|
||||
|
|
|
@ -68,3 +68,21 @@ int f1(int x) {
|
|||
}
|
||||
|
||||
const char* what_is_my_name(void) { return __func__; }
|
||||
|
||||
int computed_goto(int x) {
|
||||
start:
|
||||
x = x << 1;
|
||||
void *location = &&start;
|
||||
|
||||
if (x > 17)
|
||||
location = &&done;
|
||||
|
||||
while (x > 12) {
|
||||
--x;
|
||||
if (x == 15)
|
||||
goto *location;
|
||||
}
|
||||
|
||||
done:
|
||||
return 5;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue