Initial support for code generation from .ast files.
- Doesn't actually work yet because only module level asm's get correctly marked as externally visible in the PCH. - Other things like 'clang-cc foo.ast -ast-dump' now work, as well. llvm-svn: 82107
This commit is contained in:
parent
691b9337a6
commit
e9fee8a361
|
@ -15,6 +15,8 @@ def err_fe_unknown_target_abi : Error<"unknown target ABI '%0'">;
|
||||||
def err_fe_error_reading : Error<"error reading '%0'">;
|
def err_fe_error_reading : Error<"error reading '%0'">;
|
||||||
def err_fe_error_reading_stdin : Error<"error reading stdin">;
|
def err_fe_error_reading_stdin : Error<"error reading stdin">;
|
||||||
def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
|
def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
|
||||||
|
def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal;
|
||||||
|
def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal;
|
||||||
|
|
||||||
def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
|
def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
|
||||||
def note_fixit_in_macro : Note<
|
def note_fixit_in_macro : Note<
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
// RUN: clang -emit-ast -o %t.ast %s &&
|
||||||
|
// RUN: clang -emit-llvm -S -o - %t.ast | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK: module asm "foo"
|
||||||
|
__asm__("foo");
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "clang/Frontend/AnalysisConsumer.h"
|
#include "clang/Frontend/AnalysisConsumer.h"
|
||||||
#include "clang/Frontend/ASTConsumers.h"
|
#include "clang/Frontend/ASTConsumers.h"
|
||||||
|
#include "clang/Frontend/ASTUnit.h"
|
||||||
#include "clang/Frontend/CompileOptions.h"
|
#include "clang/Frontend/CompileOptions.h"
|
||||||
#include "clang/Frontend/FixItRewriter.h"
|
#include "clang/Frontend/FixItRewriter.h"
|
||||||
#include "clang/Frontend/FrontendDiagnostic.h"
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
||||||
|
@ -318,7 +319,8 @@ enum LangKind {
|
||||||
langkind_objc_cpp,
|
langkind_objc_cpp,
|
||||||
langkind_objcxx,
|
langkind_objcxx,
|
||||||
langkind_objcxx_cpp,
|
langkind_objcxx_cpp,
|
||||||
langkind_ocl
|
langkind_ocl,
|
||||||
|
langkind_ast
|
||||||
};
|
};
|
||||||
|
|
||||||
static llvm::cl::opt<LangKind>
|
static llvm::cl::opt<LangKind>
|
||||||
|
@ -347,6 +349,8 @@ BaseLang("x", llvm::cl::desc("Base language to compile"),
|
||||||
"C++ header"),
|
"C++ header"),
|
||||||
clEnumValN(langkind_objcxx, "objective-c++-header",
|
clEnumValN(langkind_objcxx, "objective-c++-header",
|
||||||
"Objective-C++ header"),
|
"Objective-C++ header"),
|
||||||
|
clEnumValN(langkind_ast, "ast",
|
||||||
|
"Clang AST"),
|
||||||
clEnumValEnd));
|
clEnumValEnd));
|
||||||
|
|
||||||
static llvm::cl::opt<bool>
|
static llvm::cl::opt<bool>
|
||||||
|
@ -402,7 +406,9 @@ static LangKind GetLanguage(llvm::StringRef Filename) {
|
||||||
return BaseLang;
|
return BaseLang;
|
||||||
|
|
||||||
llvm::StringRef Ext = Filename.rsplit('.').second;
|
llvm::StringRef Ext = Filename.rsplit('.').second;
|
||||||
if (Ext == "c")
|
if (Ext == "ast")
|
||||||
|
return langkind_ast;
|
||||||
|
else if (Ext == "c")
|
||||||
return langkind_c;
|
return langkind_c;
|
||||||
else if (Ext == "S" || Ext == "s")
|
else if (Ext == "S" || Ext == "s")
|
||||||
return langkind_asm_cpp;
|
return langkind_asm_cpp;
|
||||||
|
@ -687,6 +693,7 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
|
||||||
if (LangStd == lang_unspecified) {
|
if (LangStd == lang_unspecified) {
|
||||||
// Based on the base language, pick one.
|
// Based on the base language, pick one.
|
||||||
switch (LK) {
|
switch (LK) {
|
||||||
|
case langkind_ast: assert(0 && "Invalid call for AST inputs");
|
||||||
case lang_unspecified: assert(0 && "Unknown base language");
|
case lang_unspecified: assert(0 && "Unknown base language");
|
||||||
case langkind_ocl:
|
case langkind_ocl:
|
||||||
LangStd = lang_c99;
|
LangStd = lang_c99;
|
||||||
|
@ -2116,6 +2123,65 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ProcessInputFile - Process a single AST input file with the specified state.
|
||||||
|
///
|
||||||
|
static void ProcessASTInputFile(const std::string &InFile, ProgActions PA,
|
||||||
|
const llvm::StringMap<bool> &Features,
|
||||||
|
Diagnostic &Diags, FileManager &FileMgr,
|
||||||
|
llvm::LLVMContext& Context) {
|
||||||
|
// FIXME: This is manufactoring its own diags and source manager, we should
|
||||||
|
// reuse ours.
|
||||||
|
std::string Error;
|
||||||
|
llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, FileMgr,
|
||||||
|
&Error));
|
||||||
|
if (!AST) {
|
||||||
|
Diags.Report(FullSourceLoc(), diag::err_fe_invalid_ast_file) << Error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Preprocessor &PP = AST->getPreprocessor();
|
||||||
|
|
||||||
|
llvm::OwningPtr<llvm::raw_ostream> OS;
|
||||||
|
llvm::sys::Path OutPath;
|
||||||
|
llvm::OwningPtr<ASTConsumer> Consumer(CreateConsumerAction(PP, InFile, PA, OS,
|
||||||
|
OutPath, Features,
|
||||||
|
Context));
|
||||||
|
|
||||||
|
if (!Consumer.get()) {
|
||||||
|
Diags.Report(FullSourceLoc(), diag::err_fe_invalid_ast_action);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stream the input AST to the consumer.
|
||||||
|
Consumer->Initialize(AST->getASTContext());
|
||||||
|
AST->getASTContext()
|
||||||
|
.getExternalSource()->StartTranslationUnit(Consumer.get());
|
||||||
|
Consumer->HandleTranslationUnit(AST->getASTContext());
|
||||||
|
|
||||||
|
// FIXME: Tentative decls and #pragma weak aren't going to get handled
|
||||||
|
// correctly here.
|
||||||
|
|
||||||
|
// Release the consumer and the AST, in that order since the consumer may
|
||||||
|
// perform actions in its destructor which require the context.
|
||||||
|
if (DisableFree) {
|
||||||
|
Consumer.take();
|
||||||
|
AST.take();
|
||||||
|
} else {
|
||||||
|
Consumer.reset();
|
||||||
|
AST.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always delete the output stream because we don't want to leak file
|
||||||
|
// handles. Also, we don't want to try to erase an open file.
|
||||||
|
OS.reset();
|
||||||
|
|
||||||
|
if ((HadErrors || (PP.getDiagnostics().getNumErrors() != 0)) &&
|
||||||
|
!OutPath.isEmpty()) {
|
||||||
|
// If we had errors, try to erase the output file.
|
||||||
|
OutPath.eraseFromDisk();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static llvm::cl::list<std::string>
|
static llvm::cl::list<std::string>
|
||||||
InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
|
InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
|
||||||
|
|
||||||
|
@ -2258,6 +2324,14 @@ int main(int argc, char **argv) {
|
||||||
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
|
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
|
||||||
const std::string &InFile = InputFilenames[i];
|
const std::string &InFile = InputFilenames[i];
|
||||||
|
|
||||||
|
LangKind LK = GetLanguage(InFile);
|
||||||
|
// AST inputs are handled specially.
|
||||||
|
if (LK == langkind_ast) {
|
||||||
|
ProcessASTInputFile(InFile, ProgAction, Features,
|
||||||
|
Diags, FileMgr, Context);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a SourceManager object. This tracks and owns all the file
|
/// Create a SourceManager object. This tracks and owns all the file
|
||||||
/// buffers allocated to a translation unit.
|
/// buffers allocated to a translation unit.
|
||||||
if (!SourceMgr)
|
if (!SourceMgr)
|
||||||
|
@ -2269,7 +2343,6 @@ int main(int argc, char **argv) {
|
||||||
LangOptions LangInfo;
|
LangOptions LangInfo;
|
||||||
DiagClient->setLangOptions(&LangInfo);
|
DiagClient->setLangOptions(&LangInfo);
|
||||||
|
|
||||||
LangKind LK = GetLanguage(InFile);
|
|
||||||
InitializeLangOptions(LangInfo, LK);
|
InitializeLangOptions(LangInfo, LK);
|
||||||
InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
|
InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue