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