2006-08-17 14:28:25 +08:00
|
|
|
//===--- ASTStreamer.cpp - Provide streaming interface to ASTs ------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by Chris Lattner and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the ASTStreamer interface.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-05-22 01:38:36 +08:00
|
|
|
#include "clang/Sema/ASTStreamer.h"
|
2007-03-01 03:32:13 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2007-09-16 06:56:56 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2006-11-10 12:58:55 +08:00
|
|
|
#include "Sema.h"
|
2006-08-17 14:28:25 +08:00
|
|
|
#include "clang/Parse/Action.h"
|
|
|
|
#include "clang/Parse/Parser.h"
|
|
|
|
using namespace clang;
|
|
|
|
|
2007-09-16 06:56:56 +08:00
|
|
|
ASTConsumer::~ASTConsumer() {}
|
|
|
|
|
2006-08-17 14:28:25 +08:00
|
|
|
namespace {
|
|
|
|
class ASTStreamer {
|
|
|
|
Parser P;
|
2006-10-16 08:33:54 +08:00
|
|
|
std::vector<Decl*> LastInGroupList;
|
2006-08-17 14:28:25 +08:00
|
|
|
public:
|
2007-03-01 03:32:13 +08:00
|
|
|
ASTStreamer(Preprocessor &pp, ASTContext &ctxt, unsigned MainFileID)
|
|
|
|
: P(pp, *new Sema(pp, ctxt, LastInGroupList)) {
|
2007-10-10 06:10:18 +08:00
|
|
|
pp.EnterMainSourceFile(MainFileID);
|
2006-08-17 14:28:25 +08:00
|
|
|
|
2006-08-17 15:04:37 +08:00
|
|
|
// Initialize the parser.
|
|
|
|
P.Initialize();
|
2006-08-17 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ReadTopLevelDecl - Parse and return the next top-level declaration.
|
2007-01-26 09:27:23 +08:00
|
|
|
Decl *ReadTopLevelDecl();
|
2006-08-17 15:04:37 +08:00
|
|
|
|
2007-01-26 09:27:23 +08:00
|
|
|
void PrintStats() const;
|
|
|
|
|
2006-08-17 15:04:37 +08:00
|
|
|
~ASTStreamer() {
|
|
|
|
P.Finalize();
|
2006-08-18 13:17:52 +08:00
|
|
|
delete &P.getActions();
|
2006-08-17 14:28:25 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2007-01-26 09:27:23 +08:00
|
|
|
/// ReadTopLevelDecl - Parse and return the next top-level declaration.
|
|
|
|
///
|
|
|
|
Decl *ASTStreamer::ReadTopLevelDecl() {
|
|
|
|
Parser::DeclTy *Result;
|
|
|
|
|
|
|
|
/// If the previous time through we read something like 'int X, Y', return
|
|
|
|
/// the next declarator.
|
|
|
|
if (!LastInGroupList.empty()) {
|
|
|
|
Result = LastInGroupList.back();
|
|
|
|
LastInGroupList.pop_back();
|
|
|
|
return static_cast<Decl*>(Result);
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (P.ParseTopLevelDecl(Result))
|
|
|
|
return 0; // End of file.
|
|
|
|
|
|
|
|
// If we got a null return and something *was* parsed, try again. This
|
|
|
|
// is due to a top-level semicolon, an action override, or a parse error
|
|
|
|
// skipping something.
|
|
|
|
} while (Result == 0);
|
|
|
|
|
|
|
|
// If we parsed a declspec with multiple declarators, reverse the list and
|
|
|
|
// return the first one.
|
|
|
|
if (!LastInGroupList.empty()) {
|
|
|
|
LastInGroupList.push_back((Decl*)Result);
|
|
|
|
std::reverse(LastInGroupList.begin(), LastInGroupList.end());
|
|
|
|
Result = LastInGroupList.back();
|
|
|
|
LastInGroupList.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
return static_cast<Decl*>(Result);
|
|
|
|
}
|
2006-08-17 14:28:25 +08:00
|
|
|
|
2007-01-26 09:27:23 +08:00
|
|
|
void ASTStreamer::PrintStats() const {
|
2007-10-14 08:58:41 +08:00
|
|
|
P.getActions().PrintStats();
|
2007-01-26 09:27:23 +08:00
|
|
|
}
|
2006-08-17 14:28:25 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Public interface to the file
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-09-16 06:56:56 +08:00
|
|
|
/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
|
|
|
|
/// the file is parsed.
|
|
|
|
void clang::ParseAST(Preprocessor &PP, unsigned MainFileID,
|
|
|
|
ASTConsumer &Consumer, bool PrintStats) {
|
|
|
|
// Collect global stats on Decls/Stmts (until we have a module streamer).
|
|
|
|
if (PrintStats) {
|
|
|
|
Decl::CollectingStats(true);
|
|
|
|
Stmt::CollectingStats(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
llvm-svn: 42395
2007-09-27 22:38:14 +08:00
|
|
|
PP.getIdentifierTable(), PP.getSelectorTable());
|
2007-09-16 06:56:56 +08:00
|
|
|
|
|
|
|
ASTStreamer Streamer(PP, Context, MainFileID);
|
|
|
|
|
|
|
|
Consumer.Initialize(Context, MainFileID);
|
|
|
|
|
|
|
|
while (Decl *D = Streamer.ReadTopLevelDecl())
|
|
|
|
Consumer.HandleTopLevelDecl(D);
|
2007-10-27 03:46:17 +08:00
|
|
|
|
|
|
|
Consumer.HandleObjcMetaDataEmission();
|
2007-09-16 06:56:56 +08:00
|
|
|
|
|
|
|
if (PrintStats) {
|
|
|
|
fprintf(stderr, "\nSTATISTICS:\n");
|
|
|
|
Streamer.PrintStats();
|
|
|
|
Context.PrintStats();
|
|
|
|
Decl::PrintStats();
|
|
|
|
Stmt::PrintStats();
|
|
|
|
Consumer.PrintStats();
|
|
|
|
|
|
|
|
Decl::CollectingStats(false);
|
|
|
|
Stmt::CollectingStats(false);
|
|
|
|
}
|
|
|
|
}
|