From: Daniel Dunbar Date: Thu, 12 Aug 2010 02:53:12 +0000 (+0000) Subject: Frontend: Move the bulk of the cc1_main() processing into X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8eb2b0141d81d7d1026fad2d1a631f40eb3747a6;p=clang Frontend: Move the bulk of the cc1_main() processing into ExecuteCompilerInvocation in libFrontend. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110903 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index c8b1daf0b7..cd6ffb0f71 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -23,6 +23,7 @@ class Triple; namespace clang { class ASTConsumer; +class CompilerInstance; class Decl; class DependencyOutputOptions; class Diagnostic; @@ -76,6 +77,13 @@ void AttachDependencyFileGen(Preprocessor &PP, /// a seekable stream. void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS); + +/// ExecuteCompilerInvocation - Execute the given actions described by the +/// compiler invocation object in the given compiler instance. +/// +/// \return - True on success. +bool ExecuteCompilerInvocation(CompilerInstance *Clang); + } // end namespace clang #endif diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index b2e0518424..a3fd17fc8c 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_library(clangFrontend DependencyFile.cpp DiagChecker.cpp DocumentXML.cpp + ExecuteCompilerInvocation.cpp FrontendAction.cpp FrontendActions.cpp FrontendOptions.cpp diff --git a/lib/Frontend/ExecuteCompilerInvocation.cpp b/lib/Frontend/ExecuteCompilerInvocation.cpp new file mode 100644 index 0000000000..c69d844ac9 --- /dev/null +++ b/lib/Frontend/ExecuteCompilerInvocation.cpp @@ -0,0 +1,154 @@ +//===--- ExecuteCompilerInvocation.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file holds ExecuteCompilerInvocation(). It is split into its own file to +// minimize the impact of pulling in essentially everything else in Clang. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/Utils.h" +#include "clang/Checker/FrontendActions.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/Driver/CC1Options.h" +#include "clang/Driver/OptTable.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Rewrite/FrontendActions.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/System/DynamicLibrary.h" +using namespace clang; + +static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) { + using namespace clang::frontend; + + switch (CI.getFrontendOpts().ProgramAction) { + default: + llvm_unreachable("Invalid program action!"); + + case ASTDump: return new ASTDumpAction(); + case ASTPrint: return new ASTPrintAction(); + case ASTPrintXML: return new ASTPrintXMLAction(); + case ASTView: return new ASTViewAction(); + case BoostCon: return new BoostConAction(); + case DumpRawTokens: return new DumpRawTokensAction(); + case DumpTokens: return new DumpTokensAction(); + case EmitAssembly: return new EmitAssemblyAction(); + case EmitBC: return new EmitBCAction(); + case EmitHTML: return new HTMLPrintAction(); + case EmitLLVM: return new EmitLLVMAction(); + case EmitLLVMOnly: return new EmitLLVMOnlyAction(); + case EmitCodeGenOnly: return new EmitCodeGenOnlyAction(); + case EmitObj: return new EmitObjAction(); + case FixIt: return new FixItAction(); + case GeneratePCH: return new GeneratePCHAction(); + case GeneratePTH: return new GeneratePTHAction(); + case InheritanceView: return new InheritanceViewAction(); + case InitOnly: return new InitOnlyAction(); + case ParseSyntaxOnly: return new SyntaxOnlyAction(); + + case PluginAction: { + for (FrontendPluginRegistry::iterator it = + FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); + it != ie; ++it) { + if (it->getName() == CI.getFrontendOpts().ActionName) { + llvm::OwningPtr P(it->instantiate()); + if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs)) + return 0; + return P.take(); + } + } + + CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) + << CI.getFrontendOpts().ActionName; + return 0; + } + + case PrintDeclContext: return new DeclContextPrintAction(); + case PrintPreamble: return new PrintPreambleAction(); + case PrintPreprocessedInput: return new PrintPreprocessedAction(); + case RewriteMacros: return new RewriteMacrosAction(); + case RewriteObjC: return new RewriteObjCAction(); + case RewriteTest: return new RewriteTestAction(); + case RunAnalysis: return new AnalysisAction(); + case RunPreprocessorOnly: return new PreprocessOnlyAction(); + } +} + +static FrontendAction *CreateFrontendAction(CompilerInstance &CI) { + // Create the underlying action. + FrontendAction *Act = CreateFrontendBaseAction(CI); + if (!Act) + return 0; + + // If there are any AST files to merge, create a frontend action + // adaptor to perform the merge. + if (!CI.getFrontendOpts().ASTMergeFiles.empty()) + Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0], + CI.getFrontendOpts().ASTMergeFiles.size()); + + return Act; +} + +bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) { + // Honor -help. + if (Clang->getFrontendOpts().ShowHelp) { + llvm::OwningPtr Opts(driver::createCC1OptTable()); + Opts->PrintHelp(llvm::outs(), "clang -cc1", + "LLVM 'Clang' Compiler: http://clang.llvm.org"); + return 0; + } + + // Honor -version. + // + // FIXME: Use a better -version message? + if (Clang->getFrontendOpts().ShowVersion) { + llvm::cl::PrintVersionMessage(); + return 0; + } + + // Honor -mllvm. + // + // FIXME: Remove this, one day. + if (!Clang->getFrontendOpts().LLVMArgs.empty()) { + unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); + const char **Args = new const char*[NumArgs + 2]; + Args[0] = "clang (LLVM option parsing)"; + for (unsigned i = 0; i != NumArgs; ++i) + Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); + Args[NumArgs + 1] = 0; + llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast(Args)); + } + + // Load any requested plugins. + for (unsigned i = 0, + e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) { + const std::string &Path = Clang->getFrontendOpts().Plugins[i]; + std::string Error; + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) + Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin) + << Path << Error; + } + + // If there were errors in processing arguments, don't do anything else. + bool Success = false; + if (!Clang->getDiagnostics().getNumErrors()) { + // Create and execute the frontend action. + llvm::OwningPtr Act(CreateFrontendAction(*Clang)); + if (Act) { + Success = Clang->ExecuteAction(*Act); + if (Clang->getFrontendOpts().DisableFree) + Act.take(); + } + } + + return Success; +} diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index dcf7d4e5c1..2eb5fd381d 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -13,9 +13,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Basic/Diagnostic.h" -#include "clang/Checker/FrontendActions.h" -#include "clang/CodeGen/CodeGenAction.h" #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/CC1Options.h" @@ -23,20 +20,16 @@ #include "clang/Driver/OptTable.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" -#include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Rewrite/FrontendActions.h" +#include "clang/Frontend/Utils.h" #include "llvm/LLVMContext.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/DynamicLibrary.h" #include "llvm/Target/TargetSelect.h" #include using namespace clang; @@ -54,77 +47,6 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message) { exit(1); } -static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) { - using namespace clang::frontend; - - switch (CI.getFrontendOpts().ProgramAction) { - default: - llvm_unreachable("Invalid program action!"); - - case ASTDump: return new ASTDumpAction(); - case ASTPrint: return new ASTPrintAction(); - case ASTPrintXML: return new ASTPrintXMLAction(); - case ASTView: return new ASTViewAction(); - case BoostCon: return new BoostConAction(); - case DumpRawTokens: return new DumpRawTokensAction(); - case DumpTokens: return new DumpTokensAction(); - case EmitAssembly: return new EmitAssemblyAction(); - case EmitBC: return new EmitBCAction(); - case EmitHTML: return new HTMLPrintAction(); - case EmitLLVM: return new EmitLLVMAction(); - case EmitLLVMOnly: return new EmitLLVMOnlyAction(); - case EmitCodeGenOnly: return new EmitCodeGenOnlyAction(); - case EmitObj: return new EmitObjAction(); - case FixIt: return new FixItAction(); - case GeneratePCH: return new GeneratePCHAction(); - case GeneratePTH: return new GeneratePTHAction(); - case InheritanceView: return new InheritanceViewAction(); - case InitOnly: return new InitOnlyAction(); - case ParseSyntaxOnly: return new SyntaxOnlyAction(); - - case PluginAction: { - for (FrontendPluginRegistry::iterator it = - FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); - it != ie; ++it) { - if (it->getName() == CI.getFrontendOpts().ActionName) { - llvm::OwningPtr P(it->instantiate()); - if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs)) - return 0; - return P.take(); - } - } - - CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) - << CI.getFrontendOpts().ActionName; - return 0; - } - - case PrintDeclContext: return new DeclContextPrintAction(); - case PrintPreamble: return new PrintPreambleAction(); - case PrintPreprocessedInput: return new PrintPreprocessedAction(); - case RewriteMacros: return new RewriteMacrosAction(); - case RewriteObjC: return new RewriteObjCAction(); - case RewriteTest: return new RewriteTestAction(); - case RunAnalysis: return new AnalysisAction(); - case RunPreprocessorOnly: return new PreprocessOnlyAction(); - } -} - -static FrontendAction *CreateFrontendAction(CompilerInstance &CI) { - // Create the underlying action. - FrontendAction *Act = CreateFrontendBaseAction(CI); - if (!Act) - return 0; - - // If there are any AST files to merge, create a frontend action - // adaptor to perform the merge. - if (!CI.getFrontendOpts().ASTMergeFiles.empty()) - Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0], - CI.getFrontendOpts().ASTMergeFiles.size()); - - return Act; -} - // FIXME: Define the need for this testing away. static int cc1_test(Diagnostic &Diags, const char **ArgBegin, const char **ArgEnd) { @@ -234,56 +156,8 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd, DiagsBuffer.FlushDiagnostics(Clang->getDiagnostics()); - // Honor -help. - if (Clang->getFrontendOpts().ShowHelp) { - llvm::OwningPtr Opts(driver::createCC1OptTable()); - Opts->PrintHelp(llvm::outs(), "clang -cc1", - "LLVM 'Clang' Compiler: http://clang.llvm.org"); - return 0; - } - - // Honor -version. - // - // FIXME: Use a better -version message? - if (Clang->getFrontendOpts().ShowVersion) { - llvm::cl::PrintVersionMessage(); - return 0; - } - - // Honor -mllvm. - // - // FIXME: Remove this, one day. - if (!Clang->getFrontendOpts().LLVMArgs.empty()) { - unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); - const char **Args = new const char*[NumArgs + 2]; - Args[0] = "clang (LLVM option parsing)"; - for (unsigned i = 0; i != NumArgs; ++i) - Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); - Args[NumArgs + 1] = 0; - llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast(Args)); - } - - // Load any requested plugins. - for (unsigned i = 0, - e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) { - const std::string &Path = Clang->getFrontendOpts().Plugins[i]; - std::string Error; - if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) - Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin) - << Path << Error; - } - - // If there were errors in processing arguments, don't do anything else. - bool Success = false; - if (!Clang->getDiagnostics().getNumErrors()) { - // Create and execute the frontend action. - llvm::OwningPtr Act(CreateFrontendAction(*Clang)); - if (Act) { - Success = Clang->ExecuteAction(*Act); - if (Clang->getFrontendOpts().DisableFree) - Act.take(); - } - } + // Execute the frontend actions. + bool Success = ExecuteCompilerInvocation(Clang.get()); // If any timers were active but haven't been destroyed yet, print their // results now. This happens in -disable-free mode.