//===----------------------------------------------------------------------===//
#include "ASTConsumers.h"
+#include "TranslationUnit.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/CFG.h"
return new LLVMEmitter(Diags, Features);
}
+//===----------------------------------------------------------------------===//
+// AST Serializer
+
+namespace {
+ class ASTSerializer : public ASTConsumer {
+ Diagnostic &Diags;
+ TranslationUnit TU;
+ const llvm::sys::Path FName;
+ public:
+ ASTSerializer(const llvm::sys::Path& F, Diagnostic &diags,
+ const LangOptions &LO)
+ : Diags(diags), TU(LO), FName(F) {}
+
+
+ virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
+ TU.setContext(&Context);
+ }
+
+ virtual void HandleTopLevelDecl(Decl *D) {
+ // If an error occurred, stop code generation, but continue parsing and
+ // semantic analysis (to ensure all warnings and errors are emitted).
+ if (Diags.hasErrorOccurred())
+ return;
+
+ TU.AddTopLevelDecl(D);
+ }
+
+ ~ASTSerializer() { TU.EmitBitcodeFile(FName); }
+ };
+} // end anonymous namespace
+
+
+ASTConsumer *clang::CreateASTSerializer(const llvm::sys::Path& FName,
+ Diagnostic &Diags,
+ const LangOptions &Features) {
+ return new ASTSerializer(FName, Diags, Features);
+}
#include <iosfwd>
+namespace llvm { namespace sys { class Path; }}
+
namespace clang {
class ASTConsumer;
ASTConsumer *CreateCodeRewriterTest(Diagnostic &Diags);
ASTConsumer *CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr,
const LangOptions &LOpts);
+
+ASTConsumer *CreateASTSerializer(const llvm::sys::Path& FName,
+ Diagnostic &Diags, const LangOptions &LOpts);
} // end clang namespace
using namespace clang;
-bool TranslationUnit::EmitBitcodeFile(llvm::sys::Path& Filename) const {
+bool TranslationUnit::EmitBitcodeFile(const llvm::sys::Path& Filename) const {
// Reserve 256K for bitstream buffer.
std::vector<unsigned char> Buffer;
Sezr.ExitBlock(); // exit "ASTContextBlock"
}
-TranslationUnit* TranslationUnit::ReadBitcodeFile(llvm::sys::Path& Filename,
- FileManager& FMgr) {
+TranslationUnit*
+TranslationUnit::ReadBitcodeFile(const llvm::sys::Path& Filename,
+ FileManager& FMgr) {
// Create the memory buffer that contains the contents of the file.
llvm::scoped_ptr<llvm::MemoryBuffer>
const LangOptions& getLangOpts() const { return LangOpts; }
/// EmitBitcodeFile - Emit the translation unit to a bitcode file.
- bool EmitBitcodeFile(llvm::sys::Path& Filename) const;
+ bool EmitBitcodeFile(const llvm::sys::Path& Filename) const;
/// Emit - Emit the translation unit to an arbitray bitcode stream.
void Emit(llvm::Serializer& S) const;
static TranslationUnit* Create(llvm::Deserializer& D, FileManager& FMgr);
/// ReadBitcodeFile - Reconsitute a translation unit from a bitcode file.
- static TranslationUnit* ReadBitcodeFile(llvm::sys::Path& Filename,
+ static TranslationUnit* ReadBitcodeFile(const llvm::sys::Path& Filename,
FileManager& FMgr);
// Accessors
enum ProgActions {
RewriteTest, // Rewriter testing stuff.
EmitLLVM, // Emit a .ll file.
+ SerializeAST, // Emit a .ast file.
ASTPrint, // Parse ASTs and print them.
ASTDump, // Parse ASTs and dump them.
ASTView, // Parse ASTs and view them in Graphviz.
"Run prototype serializtion code."),
clEnumValN(EmitLLVM, "emit-llvm",
"Build ASTs then convert to LLVM, emit .ll file"),
+ clEnumValN(SerializeAST, "serialize-ast",
+ "Build ASTs and emit .ast file"),
clEnumValN(RewriteTest, "rewrite-test",
"Playground for the code rewriter"),
clEnumValEnd));
/// CreateASTConsumer - Create the ASTConsumer for the corresponding program
/// action. These consumers can operate on both ASTs that are freshly
/// parsed from source files as well as those deserialized from Bitcode.
-static ASTConsumer* CreateASTConsumer(Diagnostic& Diag, FileManager& FileMgr,
+static ASTConsumer* CreateASTConsumer(const std::string& InFile,
+ Diagnostic& Diag, FileManager& FileMgr,
const LangOptions& LangOpts) {
switch (ProgAction) {
default:
case EmitLLVM:
return CreateLLVMEmitter(Diag, LangOpts);
+ case SerializeAST: {
+ // FIXME: Allow user to tailor where the file is written.
+ llvm::sys::Path FName = llvm::sys::Path::GetTemporaryDirectory(NULL);
+ FName.appendComponent((InFile + ".ast").c_str());
+
+ if (FName.makeUnique(true,NULL)) {
+ fprintf (stderr, "error: cannot create serialized file: '%s'\n",
+ FName.c_str());
+
+ return NULL;
+ }
+
+ return CreateASTSerializer(FName, Diag, LangOpts);
+ }
+
case RewriteTest:
return CreateCodeRewriterTest(Diag);
}
switch (ProgAction) {
default:
- Consumer = CreateASTConsumer(PP.getDiagnostics(), HeaderInfo.getFileMgr(),
+ Consumer = CreateASTConsumer(InFile, PP.getDiagnostics(),
+ HeaderInfo.getFileMgr(),
PP.getLangOptions());
if (!Consumer) {
}
TranslationUnit* TU = TranslationUnit::ReadBitcodeFile(Filename,FileMgr);
- ASTConsumer* Consumer = CreateASTConsumer(Diag,FileMgr,TU->getLangOpts());
+ ASTConsumer* Consumer = CreateASTConsumer(InFile,Diag,
+ FileMgr,TU->getLangOpts());
if (!Consumer) {
fprintf(stderr, "Unsupported program action with serialized ASTs!\n");