зеркало из https://github.com/microsoft/clang-1.git
Implemented -serialize-ast option for the driver. This is not really tested
and is a work in progress. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44967 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
4319b8437d
Коммит
a1fa3a19bf
|
@ -12,6 +12,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "ASTConsumers.h"
|
#include "ASTConsumers.h"
|
||||||
|
#include "TranslationUnit.h"
|
||||||
#include "clang/AST/AST.h"
|
#include "clang/AST/AST.h"
|
||||||
#include "clang/AST/ASTConsumer.h"
|
#include "clang/AST/ASTConsumer.h"
|
||||||
#include "clang/AST/CFG.h"
|
#include "clang/AST/CFG.h"
|
||||||
|
@ -604,3 +605,40 @@ ASTConsumer *clang::CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Feat
|
||||||
return new LLVMEmitter(Diags, Features);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
|
namespace llvm { namespace sys { class Path; }}
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
class ASTConsumer;
|
class ASTConsumer;
|
||||||
|
@ -35,6 +37,9 @@ ASTConsumer *CreateCodeRewriterTest(Diagnostic &Diags);
|
||||||
ASTConsumer *CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr,
|
ASTConsumer *CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr,
|
||||||
const LangOptions &LOpts);
|
const LangOptions &LOpts);
|
||||||
|
|
||||||
|
ASTConsumer *CreateASTSerializer(const llvm::sys::Path& FName,
|
||||||
|
Diagnostic &Diags, const LangOptions &LOpts);
|
||||||
|
|
||||||
} // end clang namespace
|
} // end clang namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace {
|
||||||
|
|
||||||
using namespace clang;
|
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.
|
// Reserve 256K for bitstream buffer.
|
||||||
std::vector<unsigned char> Buffer;
|
std::vector<unsigned char> Buffer;
|
||||||
|
@ -122,8 +122,9 @@ void TranslationUnit::Emit(llvm::Serializer& Sezr) const {
|
||||||
Sezr.ExitBlock(); // exit "ASTContextBlock"
|
Sezr.ExitBlock(); // exit "ASTContextBlock"
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationUnit* TranslationUnit::ReadBitcodeFile(llvm::sys::Path& Filename,
|
TranslationUnit*
|
||||||
FileManager& FMgr) {
|
TranslationUnit::ReadBitcodeFile(const llvm::sys::Path& Filename,
|
||||||
|
FileManager& FMgr) {
|
||||||
|
|
||||||
// Create the memory buffer that contains the contents of the file.
|
// Create the memory buffer that contains the contents of the file.
|
||||||
llvm::scoped_ptr<llvm::MemoryBuffer>
|
llvm::scoped_ptr<llvm::MemoryBuffer>
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
const LangOptions& getLangOpts() const { return LangOpts; }
|
const LangOptions& getLangOpts() const { return LangOpts; }
|
||||||
|
|
||||||
/// EmitBitcodeFile - Emit the translation unit to a bitcode file.
|
/// 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.
|
/// Emit - Emit the translation unit to an arbitray bitcode stream.
|
||||||
void Emit(llvm::Serializer& S) const;
|
void Emit(llvm::Serializer& S) const;
|
||||||
|
@ -56,7 +56,7 @@ public:
|
||||||
static TranslationUnit* Create(llvm::Deserializer& D, FileManager& FMgr);
|
static TranslationUnit* Create(llvm::Deserializer& D, FileManager& FMgr);
|
||||||
|
|
||||||
/// ReadBitcodeFile - Reconsitute a translation unit from a bitcode file.
|
/// 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);
|
FileManager& FMgr);
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
|
|
|
@ -53,6 +53,7 @@ Stats("stats", llvm::cl::desc("Print performance metrics and statistics"));
|
||||||
enum ProgActions {
|
enum ProgActions {
|
||||||
RewriteTest, // Rewriter testing stuff.
|
RewriteTest, // Rewriter testing stuff.
|
||||||
EmitLLVM, // Emit a .ll file.
|
EmitLLVM, // Emit a .ll file.
|
||||||
|
SerializeAST, // Emit a .ast file.
|
||||||
ASTPrint, // Parse ASTs and print them.
|
ASTPrint, // Parse ASTs and print them.
|
||||||
ASTDump, // Parse ASTs and dump them.
|
ASTDump, // Parse ASTs and dump them.
|
||||||
ASTView, // Parse ASTs and view them in Graphviz.
|
ASTView, // Parse ASTs and view them in Graphviz.
|
||||||
|
@ -107,6 +108,8 @@ ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
|
||||||
"Run prototype serializtion code."),
|
"Run prototype serializtion code."),
|
||||||
clEnumValN(EmitLLVM, "emit-llvm",
|
clEnumValN(EmitLLVM, "emit-llvm",
|
||||||
"Build ASTs then convert to LLVM, emit .ll file"),
|
"Build ASTs then convert to LLVM, emit .ll file"),
|
||||||
|
clEnumValN(SerializeAST, "serialize-ast",
|
||||||
|
"Build ASTs and emit .ast file"),
|
||||||
clEnumValN(RewriteTest, "rewrite-test",
|
clEnumValN(RewriteTest, "rewrite-test",
|
||||||
"Playground for the code rewriter"),
|
"Playground for the code rewriter"),
|
||||||
clEnumValEnd));
|
clEnumValEnd));
|
||||||
|
@ -816,7 +819,8 @@ static void ParseFile(Preprocessor &PP, MinimalAction *PA, unsigned MainFileID){
|
||||||
/// CreateASTConsumer - Create the ASTConsumer for the corresponding program
|
/// CreateASTConsumer - Create the ASTConsumer for the corresponding program
|
||||||
/// action. These consumers can operate on both ASTs that are freshly
|
/// action. These consumers can operate on both ASTs that are freshly
|
||||||
/// parsed from source files as well as those deserialized from Bitcode.
|
/// 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) {
|
const LangOptions& LangOpts) {
|
||||||
switch (ProgAction) {
|
switch (ProgAction) {
|
||||||
default:
|
default:
|
||||||
|
@ -850,6 +854,21 @@ static ASTConsumer* CreateASTConsumer(Diagnostic& Diag, FileManager& FileMgr,
|
||||||
case EmitLLVM:
|
case EmitLLVM:
|
||||||
return CreateLLVMEmitter(Diag, LangOpts);
|
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:
|
case RewriteTest:
|
||||||
return CreateCodeRewriterTest(Diag);
|
return CreateCodeRewriterTest(Diag);
|
||||||
}
|
}
|
||||||
|
@ -869,7 +888,8 @@ static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID,
|
||||||
|
|
||||||
switch (ProgAction) {
|
switch (ProgAction) {
|
||||||
default:
|
default:
|
||||||
Consumer = CreateASTConsumer(PP.getDiagnostics(), HeaderInfo.getFileMgr(),
|
Consumer = CreateASTConsumer(InFile, PP.getDiagnostics(),
|
||||||
|
HeaderInfo.getFileMgr(),
|
||||||
PP.getLangOptions());
|
PP.getLangOptions());
|
||||||
|
|
||||||
if (!Consumer) {
|
if (!Consumer) {
|
||||||
|
@ -964,7 +984,8 @@ static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag,
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationUnit* TU = TranslationUnit::ReadBitcodeFile(Filename,FileMgr);
|
TranslationUnit* TU = TranslationUnit::ReadBitcodeFile(Filename,FileMgr);
|
||||||
ASTConsumer* Consumer = CreateASTConsumer(Diag,FileMgr,TU->getLangOpts());
|
ASTConsumer* Consumer = CreateASTConsumer(InFile,Diag,
|
||||||
|
FileMgr,TU->getLangOpts());
|
||||||
|
|
||||||
if (!Consumer) {
|
if (!Consumer) {
|
||||||
fprintf(stderr, "Unsupported program action with serialized ASTs!\n");
|
fprintf(stderr, "Unsupported program action with serialized ASTs!\n");
|
||||||
|
|
Загрузка…
Ссылка в новой задаче