brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.4 KiB · 05f646b Raw
317 lines · cpp
1//===--- ExecuteCompilerInvocation.cpp ------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file holds ExecuteCompilerInvocation(). It is split into its own file to10// minimize the impact of pulling in essentially everything else in Clang.11//12//===----------------------------------------------------------------------===//13 14#include "clang/Basic/DiagnosticFrontend.h"15#include "clang/CodeGen/CodeGenAction.h"16#include "clang/Config/config.h"17#include "clang/ExtractAPI/FrontendActions.h"18#include "clang/Frontend/CompilerInstance.h"19#include "clang/Frontend/CompilerInvocation.h"20#include "clang/Frontend/FrontendActions.h"21#include "clang/Frontend/FrontendPluginRegistry.h"22#include "clang/Frontend/Utils.h"23#include "clang/FrontendTool/Utils.h"24#include "clang/Options/Options.h"25#include "clang/Rewrite/Frontend/FrontendActions.h"26#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"27#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"28#include "llvm/Option/OptTable.h"29#include "llvm/Support/BuryPointer.h"30#include "llvm/Support/DynamicLibrary.h"31#include "llvm/Support/ErrorHandling.h"32 33#if CLANG_ENABLE_CIR34#include "mlir/IR/AsmState.h"35#include "mlir/IR/MLIRContext.h"36#include "mlir/Pass/PassManager.h"37#include "clang/CIR/Dialect/Passes.h"38#include "clang/CIR/FrontendAction/CIRGenAction.h"39#endif40 41using namespace clang;42using namespace llvm::opt;43 44namespace clang {45 46static std::unique_ptr<FrontendAction>47CreateFrontendBaseAction(CompilerInstance &CI) {48  using namespace clang::frontend;49  StringRef Action("unknown");50  (void)Action;51 52  unsigned UseCIR = CI.getFrontendOpts().UseClangIRPipeline;53  frontend::ActionKind Act = CI.getFrontendOpts().ProgramAction;54  bool EmitsCIR = Act == EmitCIR;55 56  if (!UseCIR && EmitsCIR)57    llvm::report_fatal_error("-emit-cir and only valid when using -fclangir");58 59  switch (CI.getFrontendOpts().ProgramAction) {60  case ASTDeclList:            return std::make_unique<ASTDeclListAction>();61  case ASTDump:                return std::make_unique<ASTDumpAction>();62  case ASTPrint:               return std::make_unique<ASTPrintAction>();63  case ASTView:                return std::make_unique<ASTViewAction>();64  case DumpCompilerOptions:65    return std::make_unique<DumpCompilerOptionsAction>();66  case DumpRawTokens:          return std::make_unique<DumpRawTokensAction>();67  case DumpTokens:             return std::make_unique<DumpTokensAction>();68  case EmitAssembly:69#if CLANG_ENABLE_CIR70    if (UseCIR)71      return std::make_unique<cir::EmitAssemblyAction>();72#endif73    return std::make_unique<EmitAssemblyAction>();74  case EmitBC:75#if CLANG_ENABLE_CIR76    if (UseCIR)77      return std::make_unique<cir::EmitBCAction>();78#endif79    return std::make_unique<EmitBCAction>();80  case EmitCIR:81#if CLANG_ENABLE_CIR82    return std::make_unique<cir::EmitCIRAction>();83#else84    CI.getDiagnostics().Report(diag::err_fe_cir_not_built);85    return nullptr;86#endif87  case EmitHTML:               return std::make_unique<HTMLPrintAction>();88  case EmitLLVM: {89#if CLANG_ENABLE_CIR90    if (UseCIR)91      return std::make_unique<cir::EmitLLVMAction>();92#endif93    return std::make_unique<EmitLLVMAction>();94  }95  case EmitLLVMOnly:           return std::make_unique<EmitLLVMOnlyAction>();96  case EmitCodeGenOnly:        return std::make_unique<EmitCodeGenOnlyAction>();97  case EmitObj:98#if CLANG_ENABLE_CIR99    if (UseCIR)100      return std::make_unique<cir::EmitObjAction>();101#endif102    return std::make_unique<EmitObjAction>();103  case ExtractAPI:104    return std::make_unique<ExtractAPIAction>();105  case FixIt:                  return std::make_unique<FixItAction>();106  case GenerateModule:107    return std::make_unique<GenerateModuleFromModuleMapAction>();108  case GenerateModuleInterface:109    return std::make_unique<GenerateModuleInterfaceAction>();110  case GenerateReducedModuleInterface:111    return std::make_unique<GenerateReducedModuleInterfaceAction>();112  case GenerateHeaderUnit:113    return std::make_unique<GenerateHeaderUnitAction>();114  case GeneratePCH:            return std::make_unique<GeneratePCHAction>();115  case GenerateInterfaceStubs:116    return std::make_unique<GenerateInterfaceStubsAction>();117  case InitOnly:               return std::make_unique<InitOnlyAction>();118  case ParseSyntaxOnly:        return std::make_unique<SyntaxOnlyAction>();119  case ModuleFileInfo:         return std::make_unique<DumpModuleInfoAction>();120  case VerifyPCH:              return std::make_unique<VerifyPCHAction>();121  case TemplightDump:          return std::make_unique<TemplightDumpAction>();122 123  case PluginAction: {124    for (const FrontendPluginRegistry::entry &Plugin :125         FrontendPluginRegistry::entries()) {126      if (Plugin.getName() == CI.getFrontendOpts().ActionName) {127        std::unique_ptr<PluginASTAction> P(Plugin.instantiate());128        if ((P->getActionType() != PluginASTAction::ReplaceAction &&129             P->getActionType() != PluginASTAction::CmdlineAfterMainAction) ||130            !P->ParseArgs(131                CI,132                CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())]))133          return nullptr;134        return std::move(P);135      }136    }137 138    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)139      << CI.getFrontendOpts().ActionName;140    return nullptr;141  }142 143  case PrintPreamble:          return std::make_unique<PrintPreambleAction>();144  case PrintPreprocessedInput: {145    if (CI.getPreprocessorOutputOpts().RewriteIncludes ||146        CI.getPreprocessorOutputOpts().RewriteImports)147      return std::make_unique<RewriteIncludesAction>();148    return std::make_unique<PrintPreprocessedAction>();149  }150 151  case RewriteMacros:          return std::make_unique<RewriteMacrosAction>();152  case RewriteTest:            return std::make_unique<RewriteTestAction>();153#if CLANG_ENABLE_OBJC_REWRITER154  case RewriteObjC:            return std::make_unique<RewriteObjCAction>();155#else156  case RewriteObjC:            Action = "RewriteObjC"; break;157#endif158#if CLANG_ENABLE_STATIC_ANALYZER159  case RunAnalysis:            return std::make_unique<ento::AnalysisAction>();160#else161  case RunAnalysis:            Action = "RunAnalysis"; break;162#endif163  case RunPreprocessorOnly:    return std::make_unique<PreprocessOnlyAction>();164  case PrintDependencyDirectivesSourceMinimizerOutput:165    return std::make_unique<PrintDependencyDirectivesSourceMinimizerAction>();166  }167 168#if !CLANG_ENABLE_STATIC_ANALYZER || !CLANG_ENABLE_OBJC_REWRITER169  CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action;170  return 0;171#else172  llvm_unreachable("Invalid program action!");173#endif174}175 176std::unique_ptr<FrontendAction>177CreateFrontendAction(CompilerInstance &CI) {178  // Create the underlying action.179  std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI);180  if (!Act)181    return nullptr;182 183  const FrontendOptions &FEOpts = CI.getFrontendOpts();184 185  if (CI.getLangOpts().HLSL)186    Act = std::make_unique<HLSLFrontendAction>(std::move(Act));187 188  if (FEOpts.FixAndRecompile) {189    Act = std::make_unique<FixItRecompile>(std::move(Act));190  }191 192  // Wrap the base FE action in an extract api action to generate193  // symbol graph as a biproduct of compilation (enabled with194  // --emit-symbol-graph option)195  if (FEOpts.EmitSymbolGraph) {196    if (FEOpts.SymbolGraphOutputDir.empty()) {197      CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir);198      CI.getFrontendOpts().SymbolGraphOutputDir = ".";199    }200    CI.getCodeGenOpts().ClearASTBeforeBackend = false;201    Act = std::make_unique<WrappingExtractAPIAction>(std::move(Act));202  }203 204  // If there are any AST files to merge, create a frontend action205  // adaptor to perform the merge.206  if (!FEOpts.ASTMergeFiles.empty())207    Act = std::make_unique<ASTMergeAction>(std::move(Act),208                                            FEOpts.ASTMergeFiles);209 210  return Act;211}212 213bool ExecuteCompilerInvocation(CompilerInstance *Clang) {214  unsigned NumErrorsBefore = Clang->getDiagnostics().getNumErrors();215 216  // Honor -help.217  if (Clang->getFrontendOpts().ShowHelp) {218    getDriverOptTable().printHelp(219        llvm::outs(), "clang -cc1 [options] file...",220        "LLVM 'Clang' Compiler: http://clang.llvm.org",221        /*ShowHidden=*/false, /*ShowAllAliases=*/false,222        llvm::opt::Visibility(options::CC1Option));223    return true;224  }225 226  // Honor -version.227  //228  // FIXME: Use a better -version message?229  if (Clang->getFrontendOpts().ShowVersion) {230    llvm::cl::PrintVersionMessage();231    return true;232  }233 234  Clang->LoadRequestedPlugins();235 236  // Honor -mllvm.237  //238  // FIXME: Remove this, one day.239  // This should happen AFTER plugins have been loaded!240  if (!Clang->getFrontendOpts().LLVMArgs.empty()) {241    unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();242    auto Args = std::make_unique<const char*[]>(NumArgs + 2);243    Args[0] = "clang (LLVM option parsing)";244    for (unsigned i = 0; i != NumArgs; ++i)245      Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();246    Args[NumArgs + 1] = nullptr;247    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get(), /*Overview=*/"",248                                      /*Errs=*/nullptr,249                                      /*VFS=*/&Clang->getVirtualFileSystem());250  }251 252#if CLANG_ENABLE_STATIC_ANALYZER253  // These should happen AFTER plugins have been loaded!254 255  AnalyzerOptions &AnOpts = Clang->getAnalyzerOpts();256 257  // Honor -analyzer-checker-help and -analyzer-checker-help-hidden.258  if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpAlpha ||259      AnOpts.ShowCheckerHelpDeveloper) {260    ento::printCheckerHelp(llvm::outs(), *Clang);261    return true;262  }263 264  // Honor -analyzer-checker-option-help.265  if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionAlphaList ||266      AnOpts.ShowCheckerOptionDeveloperList) {267    ento::printCheckerConfigList(llvm::outs(), *Clang);268    return true;269  }270 271  // Honor -analyzer-list-enabled-checkers.272  if (AnOpts.ShowEnabledCheckerList) {273    ento::printEnabledCheckerList(llvm::outs(), *Clang);274    return true;275  }276 277  // Honor -analyzer-config-help.278  if (AnOpts.ShowConfigOptionsList) {279    ento::printAnalyzerConfigList(llvm::outs());280    return true;281  }282#endif283 284#if CLANG_ENABLE_CIR285  if (!Clang->getFrontendOpts().MLIRArgs.empty()) {286    mlir::registerCIRPasses();287    mlir::registerMLIRContextCLOptions();288    mlir::registerPassManagerCLOptions();289    mlir::registerAsmPrinterCLOptions();290    unsigned NumArgs = Clang->getFrontendOpts().MLIRArgs.size();291    auto Args = std::make_unique<const char *[]>(NumArgs + 2);292    Args[0] = "clang (MLIR option parsing)";293    for (unsigned i = 0; i != NumArgs; ++i)294      Args[i + 1] = Clang->getFrontendOpts().MLIRArgs[i].c_str();295    Args[NumArgs + 1] = nullptr;296    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());297  }298#endif299 300  // If there were errors in the above, don't do anything else.301  // This intentionally ignores errors emitted before this function to302  // accommodate lenient callers that decided to make progress despite errors.303  if (Clang->getDiagnostics().getNumErrors() != NumErrorsBefore)304    return false;305 306  // Create and execute the frontend action.307  std::unique_ptr<FrontendAction> Act(CreateFrontendAction(*Clang));308  if (!Act)309    return false;310  bool Success = Clang->ExecuteAction(*Act);311  if (Clang->getFrontendOpts().DisableFree)312    llvm::BuryPointer(std::move(Act));313  return Success;314}315 316} // namespace clang317