[cfe-commits] r82107 - in /cfe/trunk: include/clang/Basic/DiagnosticFrontendKinds.td test/Frontend/ast-codegen.c tools/clang-cc/clang-cc.cpp

Daniel Dunbar daniel at zuster.org
Wed Sep 16 17:48:13 PDT 2009


Author: ddunbar
Date: Wed Sep 16 19:48:13 2009
New Revision: 82107

URL: http://llvm.org/viewvc/llvm-project?rev=82107&view=rev
Log:
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.

Added:
    cfe/trunk/test/Frontend/ast-codegen.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
    cfe/trunk/tools/clang-cc/clang-cc.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=82107&r1=82106&r2=82107&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Wed Sep 16 19:48:13 2009
@@ -15,6 +15,8 @@
 def err_fe_error_reading : Error<"error reading '%0'">;
 def err_fe_error_reading_stdin : Error<"error reading stdin">;
 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_in_macro : Note<

Added: cfe/trunk/test/Frontend/ast-codegen.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/ast-codegen.c?rev=82107&view=auto

==============================================================================
--- cfe/trunk/test/Frontend/ast-codegen.c (added)
+++ cfe/trunk/test/Frontend/ast-codegen.c Wed Sep 16 19:48:13 2009
@@ -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");

Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=82107&r1=82106&r2=82107&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Wed Sep 16 19:48:13 2009
@@ -24,6 +24,7 @@
 
 #include "clang/Frontend/AnalysisConsumer.h"
 #include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompileOptions.h"
 #include "clang/Frontend/FixItRewriter.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
@@ -318,7 +319,8 @@
   langkind_objc_cpp,
   langkind_objcxx,
   langkind_objcxx_cpp,
-  langkind_ocl
+  langkind_ocl,
+  langkind_ast
 };
 
 static llvm::cl::opt<LangKind>
@@ -347,6 +349,8 @@
                                "C++ header"),
                     clEnumValN(langkind_objcxx, "objective-c++-header",
                                "Objective-C++ header"),
+                    clEnumValN(langkind_ast, "ast",
+                               "Clang AST"),
                     clEnumValEnd));
 
 static llvm::cl::opt<bool>
@@ -402,7 +406,9 @@
     return BaseLang;
 
   llvm::StringRef Ext = Filename.rsplit('.').second;
-  if (Ext == "c")
+  if (Ext == "ast")
+    return langkind_ast;
+  else if (Ext == "c")
     return langkind_c;
   else if (Ext == "S" || Ext == "s")
     return langkind_asm_cpp;
@@ -687,6 +693,7 @@
   if (LangStd == lang_unspecified) {
     // Based on the base language, pick one.
     switch (LK) {
+    case langkind_ast: assert(0 && "Invalid call for AST inputs");
     case lang_unspecified: assert(0 && "Unknown base language");
     case langkind_ocl:
       LangStd = lang_c99;
@@ -2116,6 +2123,65 @@
   }
 }
 
+/// 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>
 InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
 
@@ -2258,6 +2324,14 @@
   for (unsigned i = 0, e = InputFilenames.size(); i != e; ++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
     /// buffers allocated to a translation unit.
     if (!SourceMgr)
@@ -2269,7 +2343,6 @@
     LangOptions LangInfo;
     DiagClient->setLangOptions(&LangInfo);
 
-    LangKind LK = GetLanguage(InFile);
     InitializeLangOptions(LangInfo, LK);
     InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
 





More information about the cfe-commits mailing list