diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-04-17 00:04:06 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-04-17 00:04:06 +0000 |
commit | 025452fa0eda63e150cfaeebe64f0a19c96b3a06 (patch) | |
tree | 187c0527f4fdd7743381dc30f67fc6bfa7852c07 /lib/Frontend | |
parent | 363c184139e26ea38223b477ad64ee67b22bb9a7 (diff) |
PCH support for the first batch of statements, including null,
compound, case, default, if, switch, and break statements.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69329 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 135 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 95 |
2 files changed, 227 insertions, 3 deletions
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 0f208fb7ac..e39f3e580b 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -139,7 +139,8 @@ void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { VisitValueDecl(FD); - // FIXME: function body + if (Record[Idx++]) + FD->setBody(cast<CompoundStmt>(Reader.ReadStmt())); FD->setPreviousDeclaration( cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); @@ -229,15 +230,28 @@ namespace { unsigned &Idx, llvm::SmallVectorImpl<Stmt *> &StmtStack) : Reader(Reader), Record(Record), Idx(Idx), StmtStack(StmtStack) { } + /// \brief The number of record fields required for the Stmt class + /// itself. + static const unsigned NumStmtFields = 0; + /// \brief The number of record fields required for the Expr class /// itself. - static const unsigned NumExprFields = 3; + static const unsigned NumExprFields = NumStmtFields + 3; // Each of the Visit* functions reads in part of the expression // from the given record and the current expression stack, then // return the total number of operands that it read from the // expression stack. + unsigned VisitStmt(Stmt *S); + unsigned VisitNullStmt(NullStmt *S); + unsigned VisitCompoundStmt(CompoundStmt *S); + unsigned VisitSwitchCase(SwitchCase *S); + unsigned VisitCaseStmt(CaseStmt *S); + unsigned VisitDefaultStmt(DefaultStmt *S); + unsigned VisitIfStmt(IfStmt *S); + unsigned VisitSwitchStmt(SwitchStmt *S); + unsigned VisitBreakStmt(BreakStmt *S); unsigned VisitExpr(Expr *E); unsigned VisitPredefinedExpr(PredefinedExpr *E); unsigned VisitDeclRefExpr(DeclRefExpr *E); @@ -273,7 +287,83 @@ namespace { }; } +unsigned PCHStmtReader::VisitStmt(Stmt *S) { + assert(Idx == NumStmtFields && "Incorrect statement field count"); + return 0; +} + +unsigned PCHStmtReader::VisitNullStmt(NullStmt *S) { + VisitStmt(S); + S->setSemiLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + return 0; +} + +unsigned PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) { + VisitStmt(S); + unsigned NumStmts = Record[Idx++]; + S->setStmts(Reader.getContext(), + &StmtStack[StmtStack.size() - NumStmts], NumStmts); + S->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + return NumStmts; +} + +unsigned PCHStmtReader::VisitSwitchCase(SwitchCase *S) { + VisitStmt(S); + Reader.RecordSwitchCaseID(S, Record[Idx++]); + return 0; +} + +unsigned PCHStmtReader::VisitCaseStmt(CaseStmt *S) { + VisitSwitchCase(S); + S->setLHS(cast<Expr>(StmtStack[StmtStack.size() - 3])); + S->setRHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2])); + S->setSubStmt(StmtStack.back()); + S->setCaseLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + return 3; +} + +unsigned PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) { + VisitSwitchCase(S); + S->setSubStmt(StmtStack.back()); + S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + return 1; +} + +unsigned PCHStmtReader::VisitIfStmt(IfStmt *S) { + VisitStmt(S); + S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3])); + S->setThen(StmtStack[StmtStack.size() - 2]); + S->setElse(StmtStack[StmtStack.size() - 1]); + S->setIfLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + return 3; +} + +unsigned PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) { + VisitStmt(S); + S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 2])); + S->setBody(StmtStack.back()); + S->setSwitchLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + SwitchCase *PrevSC = 0; + for (unsigned N = Record.size(); Idx != N; ++Idx) { + SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]); + if (PrevSC) + PrevSC->setNextSwitchCase(SC); + else + S->setSwitchCaseList(SC); + PrevSC = SC; + } + return 2; +} + +unsigned PCHStmtReader::VisitBreakStmt(BreakStmt *S) { + VisitStmt(S); + S->setBreakLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + return 0; +} + unsigned PCHStmtReader::VisitExpr(Expr *E) { + VisitStmt(E); E->setType(Reader.GetType(Record[Idx++])); E->setTypeDependent(Record[Idx++]); E->setValueDependent(Record[Idx++]); @@ -2002,6 +2092,34 @@ Stmt *PCHReader::ReadStmt() { S = 0; break; + case pch::STMT_NULL: + S = new (Context) NullStmt(Empty); + break; + + case pch::STMT_COMPOUND: + S = new (Context) CompoundStmt(Empty); + break; + + case pch::STMT_CASE: + S = new (Context) CaseStmt(Empty); + break; + + case pch::STMT_DEFAULT: + S = new (Context) DefaultStmt(Empty); + break; + + case pch::STMT_IF: + S = new (Context) IfStmt(Empty); + break; + + case pch::STMT_SWITCH: + S = new (Context) SwitchStmt(Empty); + break; + + case pch::STMT_BREAK: + S = new (Context) BreakStmt(Empty); + break; + case pch::EXPR_PREDEFINED: // FIXME: untested (until we can serialize function bodies). S = new (Context) PredefinedExpr(Empty); @@ -2157,3 +2275,16 @@ DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) { Context.getSourceManager()), DiagID); } + +/// \brief Record that the given ID maps to the given switch-case +/// statement. +void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { + assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID"); + SwitchCaseStmts[ID] = SC; +} + +/// \brief Retrieve the switch-case statement with the given ID. +SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) { + assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID"); + return SwitchCaseStmts[ID]; +} diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 056aeec2d7..8f09030ac8 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -338,7 +338,9 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { VisitValueDecl(D); - // FIXME: function body + Record.push_back(D->isThisDeclarationADefinition()); + if (D->isThisDeclarationADefinition()) + Writer.AddStmt(D->getBody()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->isInline()); @@ -443,6 +445,15 @@ namespace { PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) : Writer(Writer), Record(Record) { } + void VisitStmt(Stmt *S); + void VisitNullStmt(NullStmt *S); + void VisitCompoundStmt(CompoundStmt *S); + void VisitSwitchCase(SwitchCase *S); + void VisitCaseStmt(CaseStmt *S); + void VisitDefaultStmt(DefaultStmt *S); + void VisitIfStmt(IfStmt *S); + void VisitSwitchStmt(SwitchStmt *S); + void VisitBreakStmt(BreakStmt *S); void VisitExpr(Expr *E); void VisitPredefinedExpr(PredefinedExpr *E); void VisitDeclRefExpr(DeclRefExpr *E); @@ -478,7 +489,75 @@ namespace { }; } +void PCHStmtWriter::VisitStmt(Stmt *S) { +} + +void PCHStmtWriter::VisitNullStmt(NullStmt *S) { + VisitStmt(S); + Writer.AddSourceLocation(S->getSemiLoc(), Record); + Code = pch::STMT_NULL; +} + +void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) { + VisitStmt(S); + Record.push_back(S->size()); + for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end(); + CS != CSEnd; ++CS) + Writer.WriteSubStmt(*CS); + Writer.AddSourceLocation(S->getLBracLoc(), Record); + Writer.AddSourceLocation(S->getRBracLoc(), Record); + Code = pch::STMT_COMPOUND; +} + +void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) { + VisitStmt(S); + Record.push_back(Writer.RecordSwitchCaseID(S)); +} + +void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) { + VisitSwitchCase(S); + Writer.WriteSubStmt(S->getLHS()); + Writer.WriteSubStmt(S->getRHS()); + Writer.WriteSubStmt(S->getSubStmt()); + Writer.AddSourceLocation(S->getCaseLoc(), Record); + Code = pch::STMT_CASE; +} + +void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) { + VisitSwitchCase(S); + Writer.WriteSubStmt(S->getSubStmt()); + Writer.AddSourceLocation(S->getDefaultLoc(), Record); + Code = pch::STMT_DEFAULT; +} + +void PCHStmtWriter::VisitIfStmt(IfStmt *S) { + VisitStmt(S); + Writer.WriteSubStmt(S->getCond()); + Writer.WriteSubStmt(S->getThen()); + Writer.WriteSubStmt(S->getElse()); + Writer.AddSourceLocation(S->getIfLoc(), Record); + Code = pch::STMT_IF; +} + +void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) { + VisitStmt(S); + Writer.WriteSubStmt(S->getCond()); + Writer.WriteSubStmt(S->getBody()); + Writer.AddSourceLocation(S->getSwitchLoc(), Record); + for (SwitchCase *SC = S->getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) + Record.push_back(Writer.getSwitchCaseID(SC)); + Code = pch::STMT_SWITCH; +} + +void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) { + VisitStmt(S); + Writer.AddSourceLocation(S->getBreakLoc(), Record); + Code = pch::STMT_BREAK; +} + void PCHStmtWriter::VisitExpr(Expr *E) { + VisitStmt(E); Writer.AddTypeRef(E->getType(), Record); Record.push_back(E->isTypeDependent()); Record.push_back(E->isValueDependent()); @@ -1708,3 +1787,17 @@ void PCHWriter::FlushStmts() { StmtsToEmit.clear(); } + +unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) { + assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && + "SwitchCase recorded twice"); + unsigned NextID = SwitchCaseIDs.size(); + SwitchCaseIDs[S] = NextID; + return NextID; +} + +unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) { + assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && + "SwitchCase hasn't been seen yet"); + return SwitchCaseIDs[S]; +} |