mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-08 00:02:20 +00:00

to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
274 lines
11 KiB
C++
274 lines
11 KiB
C++
//===--- ExecuteCompilerInvocation.cpp ------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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/ARCMigrate/ARCMTActions.h"
|
|
#include "clang/CodeGen/CodeGenAction.h"
|
|
#include "clang/Config/config.h"
|
|
#include "clang/Driver/Options.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/Utils.h"
|
|
#include "clang/FrontendTool/Utils.h"
|
|
#include "clang/Rewrite/Frontend/FrontendActions.h"
|
|
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
|
|
#include "llvm/Option/OptTable.h"
|
|
#include "llvm/Option/Option.h"
|
|
#include "llvm/Support/BuryPointer.h"
|
|
#include "llvm/Support/DynamicLibrary.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
using namespace clang;
|
|
using namespace llvm::opt;
|
|
|
|
namespace clang {
|
|
|
|
static std::unique_ptr<FrontendAction>
|
|
CreateFrontendBaseAction(CompilerInstance &CI) {
|
|
using namespace clang::frontend;
|
|
StringRef Action("unknown");
|
|
(void)Action;
|
|
|
|
switch (CI.getFrontendOpts().ProgramAction) {
|
|
case ASTDeclList: return llvm::make_unique<ASTDeclListAction>();
|
|
case ASTDump: return llvm::make_unique<ASTDumpAction>();
|
|
case ASTPrint: return llvm::make_unique<ASTPrintAction>();
|
|
case ASTView: return llvm::make_unique<ASTViewAction>();
|
|
case DumpCompilerOptions:
|
|
return llvm::make_unique<DumpCompilerOptionsAction>();
|
|
case DumpRawTokens: return llvm::make_unique<DumpRawTokensAction>();
|
|
case DumpTokens: return llvm::make_unique<DumpTokensAction>();
|
|
case EmitAssembly: return llvm::make_unique<EmitAssemblyAction>();
|
|
case EmitBC: return llvm::make_unique<EmitBCAction>();
|
|
case EmitHTML: return llvm::make_unique<HTMLPrintAction>();
|
|
case EmitLLVM: return llvm::make_unique<EmitLLVMAction>();
|
|
case EmitLLVMOnly: return llvm::make_unique<EmitLLVMOnlyAction>();
|
|
case EmitCodeGenOnly: return llvm::make_unique<EmitCodeGenOnlyAction>();
|
|
case EmitObj: return llvm::make_unique<EmitObjAction>();
|
|
case FixIt: return llvm::make_unique<FixItAction>();
|
|
case GenerateModule:
|
|
return llvm::make_unique<GenerateModuleFromModuleMapAction>();
|
|
case GenerateModuleInterface:
|
|
return llvm::make_unique<GenerateModuleInterfaceAction>();
|
|
case GenerateHeaderModule:
|
|
return llvm::make_unique<GenerateHeaderModuleAction>();
|
|
case GeneratePCH: return llvm::make_unique<GeneratePCHAction>();
|
|
case InitOnly: return llvm::make_unique<InitOnlyAction>();
|
|
case ParseSyntaxOnly: return llvm::make_unique<SyntaxOnlyAction>();
|
|
case ModuleFileInfo: return llvm::make_unique<DumpModuleInfoAction>();
|
|
case VerifyPCH: return llvm::make_unique<VerifyPCHAction>();
|
|
case TemplightDump: return llvm::make_unique<TemplightDumpAction>();
|
|
|
|
case PluginAction: {
|
|
for (FrontendPluginRegistry::iterator it =
|
|
FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
|
|
it != ie; ++it) {
|
|
if (it->getName() == CI.getFrontendOpts().ActionName) {
|
|
std::unique_ptr<PluginASTAction> P(it->instantiate());
|
|
if ((P->getActionType() != PluginASTAction::ReplaceAction &&
|
|
P->getActionType() != PluginASTAction::Cmdline) ||
|
|
!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs[it->getName()]))
|
|
return nullptr;
|
|
return std::move(P);
|
|
}
|
|
}
|
|
|
|
CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
|
|
<< CI.getFrontendOpts().ActionName;
|
|
return nullptr;
|
|
}
|
|
|
|
case PrintPreamble: return llvm::make_unique<PrintPreambleAction>();
|
|
case PrintPreprocessedInput: {
|
|
if (CI.getPreprocessorOutputOpts().RewriteIncludes ||
|
|
CI.getPreprocessorOutputOpts().RewriteImports)
|
|
return llvm::make_unique<RewriteIncludesAction>();
|
|
return llvm::make_unique<PrintPreprocessedAction>();
|
|
}
|
|
|
|
case RewriteMacros: return llvm::make_unique<RewriteMacrosAction>();
|
|
case RewriteTest: return llvm::make_unique<RewriteTestAction>();
|
|
#if CLANG_ENABLE_OBJC_REWRITER
|
|
case RewriteObjC: return llvm::make_unique<RewriteObjCAction>();
|
|
#else
|
|
case RewriteObjC: Action = "RewriteObjC"; break;
|
|
#endif
|
|
#if CLANG_ENABLE_ARCMT
|
|
case MigrateSource:
|
|
return llvm::make_unique<arcmt::MigrateSourceAction>();
|
|
#else
|
|
case MigrateSource: Action = "MigrateSource"; break;
|
|
#endif
|
|
#if CLANG_ENABLE_STATIC_ANALYZER
|
|
case RunAnalysis: return llvm::make_unique<ento::AnalysisAction>();
|
|
#else
|
|
case RunAnalysis: Action = "RunAnalysis"; break;
|
|
#endif
|
|
case RunPreprocessorOnly: return llvm::make_unique<PreprocessOnlyAction>();
|
|
}
|
|
|
|
#if !CLANG_ENABLE_ARCMT || !CLANG_ENABLE_STATIC_ANALYZER \
|
|
|| !CLANG_ENABLE_OBJC_REWRITER
|
|
CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action;
|
|
return 0;
|
|
#else
|
|
llvm_unreachable("Invalid program action!");
|
|
#endif
|
|
}
|
|
|
|
std::unique_ptr<FrontendAction>
|
|
CreateFrontendAction(CompilerInstance &CI) {
|
|
// Create the underlying action.
|
|
std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI);
|
|
if (!Act)
|
|
return nullptr;
|
|
|
|
const FrontendOptions &FEOpts = CI.getFrontendOpts();
|
|
|
|
if (FEOpts.FixAndRecompile) {
|
|
Act = llvm::make_unique<FixItRecompile>(std::move(Act));
|
|
}
|
|
|
|
#if CLANG_ENABLE_ARCMT
|
|
if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource &&
|
|
CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) {
|
|
// Potentially wrap the base FE action in an ARC Migrate Tool action.
|
|
switch (FEOpts.ARCMTAction) {
|
|
case FrontendOptions::ARCMT_None:
|
|
break;
|
|
case FrontendOptions::ARCMT_Check:
|
|
Act = llvm::make_unique<arcmt::CheckAction>(std::move(Act));
|
|
break;
|
|
case FrontendOptions::ARCMT_Modify:
|
|
Act = llvm::make_unique<arcmt::ModifyAction>(std::move(Act));
|
|
break;
|
|
case FrontendOptions::ARCMT_Migrate:
|
|
Act = llvm::make_unique<arcmt::MigrateAction>(std::move(Act),
|
|
FEOpts.MTMigrateDir,
|
|
FEOpts.ARCMTMigrateReportOut,
|
|
FEOpts.ARCMTMigrateEmitARCErrors);
|
|
break;
|
|
}
|
|
|
|
if (FEOpts.ObjCMTAction != FrontendOptions::ObjCMT_None) {
|
|
Act = llvm::make_unique<arcmt::ObjCMigrateAction>(std::move(Act),
|
|
FEOpts.MTMigrateDir,
|
|
FEOpts.ObjCMTAction);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// If there are any AST files to merge, create a frontend action
|
|
// adaptor to perform the merge.
|
|
if (!FEOpts.ASTMergeFiles.empty())
|
|
Act = llvm::make_unique<ASTMergeAction>(std::move(Act),
|
|
FEOpts.ASTMergeFiles);
|
|
|
|
return Act;
|
|
}
|
|
|
|
bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
|
|
// Honor -help.
|
|
if (Clang->getFrontendOpts().ShowHelp) {
|
|
std::unique_ptr<OptTable> Opts = driver::createDriverOptTable();
|
|
Opts->PrintHelp(llvm::outs(), "clang -cc1 [options] file...",
|
|
"LLVM 'Clang' Compiler: http://clang.llvm.org",
|
|
/*Include=*/driver::options::CC1Option,
|
|
/*Exclude=*/0, /*ShowAllAliases=*/false);
|
|
return true;
|
|
}
|
|
|
|
// Honor -version.
|
|
//
|
|
// FIXME: Use a better -version message?
|
|
if (Clang->getFrontendOpts().ShowVersion) {
|
|
llvm::cl::PrintVersionMessage();
|
|
return true;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Check if any of the loaded plugins replaces the main AST action
|
|
for (FrontendPluginRegistry::iterator it = FrontendPluginRegistry::begin(),
|
|
ie = FrontendPluginRegistry::end();
|
|
it != ie; ++it) {
|
|
std::unique_ptr<PluginASTAction> P(it->instantiate());
|
|
if (P->getActionType() == PluginASTAction::ReplaceAction) {
|
|
Clang->getFrontendOpts().ProgramAction = clang::frontend::PluginAction;
|
|
Clang->getFrontendOpts().ActionName = it->getName();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Honor -mllvm.
|
|
//
|
|
// FIXME: Remove this, one day.
|
|
// This should happen AFTER plugins have been loaded!
|
|
if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
|
|
unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
|
|
auto Args = llvm::make_unique<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] = nullptr;
|
|
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
|
|
}
|
|
|
|
#if CLANG_ENABLE_STATIC_ANALYZER
|
|
// Honor -analyzer-checker-help.
|
|
// This should happen AFTER plugins have been loaded!
|
|
if (Clang->getAnalyzerOpts()->ShowCheckerHelp) {
|
|
ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins,
|
|
Clang->getDiagnostics());
|
|
return true;
|
|
}
|
|
|
|
// Honor -analyzer-list-enabled-checkers.
|
|
if (Clang->getAnalyzerOpts()->ShowEnabledCheckerList) {
|
|
ento::printEnabledCheckerList(llvm::outs(),
|
|
Clang->getFrontendOpts().Plugins,
|
|
*Clang->getAnalyzerOpts(),
|
|
Clang->getDiagnostics());
|
|
}
|
|
|
|
// Honor -analyzer-config-help.
|
|
if (Clang->getAnalyzerOpts()->ShowConfigOptionsList) {
|
|
ento::printAnalyzerConfigList(llvm::outs());
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
// If there were errors in processing arguments, don't do anything else.
|
|
if (Clang->getDiagnostics().hasErrorOccurred())
|
|
return false;
|
|
// Create and execute the frontend action.
|
|
std::unique_ptr<FrontendAction> Act(CreateFrontendAction(*Clang));
|
|
if (!Act)
|
|
return false;
|
|
bool Success = Clang->ExecuteAction(*Act);
|
|
if (Clang->getFrontendOpts().DisableFree)
|
|
llvm::BuryPointer(std::move(Act));
|
|
return Success;
|
|
}
|
|
|
|
} // namespace clang
|