bool Stopped = false;
bool AddingMachinePasses = false;
+ /// Set the StartAfter, StartBefore and StopAfter passes to allow running only
+ /// a portion of the normal code-gen pass sequence.
+ ///
+ /// If the StartAfter and StartBefore pass ID is zero, then compilation will
+ /// begin at the normal point; otherwise, clear the Started flag to indicate
+ /// that passes should not be added until the starting pass is seen. If the
+ /// Stop pass ID is zero, then compilation will continue to the end.
+ ///
+ /// This function expects that at least one of the StartAfter or the
+ /// StartBefore pass IDs is null.
+ void setStartStopPasses();
+
protected:
LLVMTargetMachine *TM;
PassConfigImpl *Impl = nullptr; // Internal data structures
CodeGenOpt::Level getOptLevel() const;
- /// Set the StartAfter, StartBefore and StopAfter passes to allow running only
- /// a portion of the normal code-gen pass sequence.
- ///
- /// If the StartAfter and StartBefore pass ID is zero, then compilation will
- /// begin at the normal point; otherwise, clear the Started flag to indicate
- /// that passes should not be added until the starting pass is seen. If the
- /// Stop pass ID is zero, then compilation will continue to the end.
- ///
- /// This function expects that at least one of the StartAfter or the
- /// StartBefore pass IDs is null.
- void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter,
- AnalysisID StopBefore, AnalysisID StopAfter) {
- assert(!(StartBefore && StartAfter) &&
- "Start after and start before passes are given");
- assert(!(StopBefore && StopAfter) &&
- "Stop after and stop before passed are given");
- this->StartBefore = StartBefore;
- this->StartAfter = StartAfter;
- this->StopBefore = StopBefore;
- this->StopAfter = StopAfter;
- Started = (StartAfter == nullptr) && (StartBefore == nullptr);
+ /// Describe the status of the codegen
+ /// pipeline set by this target pass config.
+ /// Having a limited codegen pipeline means that options
+ /// have been used to restrict what codegen is doing.
+ /// In particular, that means that codegen won't emit
+ /// assembly code.
+ bool hasLimitedCodeGenPipeline() const;
+
+ /// If hasLimitedCodeGenPipeline is true, this method
+ /// returns a string with the name of the options, separated
+ /// by \p Separator that caused this pipeline to be limited.
+ std::string
+ getLimitedCodeGenPipelineReason(const char *Separator = "/") const;
+
+ /// Check if the codegen pipeline is limited in such a way that it
+ /// won't be complete. When the codegen pipeline is not complete,
+ /// this means it may not be possible to generate assembly from it.
+ bool willCompleteCodeGenPipeline() const {
+ return !hasLimitedCodeGenPipeline() || (!StopAfter && !StopBefore);
}
void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); }
namespace llvm {
class GlobalValue;
+class MachineModuleInfo;
class Mangler;
class MCAsmInfo;
class MCContext;
/// emitted. Typically this will involve several steps of code generation.
/// This method should return true if emission of this file type is not
/// supported, or false on success.
- virtual bool addPassesToEmitFile(
- PassManagerBase &, raw_pwrite_stream &, CodeGenFileType,
- bool /*DisableVerify*/ = true, AnalysisID /*StartBefore*/ = nullptr,
- AnalysisID /*StartAfter*/ = nullptr, AnalysisID /*StopBefore*/ = nullptr,
- AnalysisID /*StopAfter*/ = nullptr) {
+ /// \p MMI is an optional parameter that, if set to non-nullptr,
+ /// will be used to set the MachineModuloInfo for this PM.
+ virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &,
+ CodeGenFileType,
+ bool /*DisableVerify*/ = true,
+ MachineModuleInfo *MMI = nullptr) {
return true;
}
CodeModel::Model CM, CodeGenOpt::Level OL);
void initAsmInfo();
+
public:
/// \brief Get a TargetIRAnalysis implementation for the target.
///
/// Add passes to the specified pass manager to get the specified file
/// emitted. Typically this will involve several steps of code generation.
- bool addPassesToEmitFile(
- PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType,
- bool DisableVerify = true, AnalysisID StartBefore = nullptr,
- AnalysisID StartAfter = nullptr, AnalysisID StopBefore = nullptr,
- AnalysisID StopAfter = nullptr) override;
+ /// \p MMI is an optional parameter that, if set to non-nullptr,
+ /// will be used to set the MachineModuloInfofor this PM.
+ bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
+ CodeGenFileType FileType, bool DisableVerify = true,
+ MachineModuleInfo *MMI = nullptr) override;
/// Add passes to the specified pass manager to get machine code emitted with
/// the MCJIT. This method returns true if machine code is not supported. It
/// addPassesToX helper drives creation and initialization of TargetPassConfig.
static MCContext *
addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM,
- bool DisableVerify, AnalysisID StartBefore,
- AnalysisID StartAfter, AnalysisID StopBefore,
- AnalysisID StopAfter) {
+ bool DisableVerify, bool &WillCompleteCodeGenPipeline,
+ raw_pwrite_stream &Out, MachineModuleInfo *MMI) {
// Targets may override createPassConfig to provide a target-specific
// subclass.
TargetPassConfig *PassConfig = TM->createPassConfig(PM);
- PassConfig->setStartStopPasses(StartBefore, StartAfter, StopBefore,
- StopAfter);
// Set PassConfig options provided by TargetMachine.
PassConfig->setDisableVerify(DisableVerify);
+ WillCompleteCodeGenPipeline = PassConfig->willCompleteCodeGenPipeline();
PM.add(PassConfig);
- MachineModuleInfo *MMI = new MachineModuleInfo(TM);
+ if (!MMI)
+ MMI = new MachineModuleInfo(TM);
PM.add(MMI);
if (PassConfig->addISelPasses())
return nullptr;
PassConfig->addMachinePasses();
PassConfig->setInitialized();
+ if (!WillCompleteCodeGenPipeline)
+ PM.add(createPrintMIRPass(Out));
return &MMI->getContext();
}
return false;
}
-bool LLVMTargetMachine::addPassesToEmitFile(
- PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType,
- bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter,
- AnalysisID StopBefore, AnalysisID StopAfter) {
+bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
+ raw_pwrite_stream &Out,
+ CodeGenFileType FileType,
+ bool DisableVerify,
+ MachineModuleInfo *MMI) {
// Add common CodeGen passes.
- MCContext *Context =
- addPassesToGenerateCode(this, PM, DisableVerify, StartBefore, StartAfter,
- StopBefore, StopAfter);
+ bool WillCompleteCodeGenPipeline = true;
+ MCContext *Context = addPassesToGenerateCode(
+ this, PM, DisableVerify, WillCompleteCodeGenPipeline, Out, MMI);
if (!Context)
return true;
- if (StopBefore || StopAfter) {
- PM.add(createPrintMIRPass(Out));
- } else {
- if (addAsmPrinter(PM, Out, FileType, *Context))
- return true;
- }
+ if (WillCompleteCodeGenPipeline && addAsmPrinter(PM, Out, FileType, *Context))
+ return true;
PM.add(createFreeMachineFunctionPass());
return false;
raw_pwrite_stream &Out,
bool DisableVerify) {
// Add common CodeGen passes.
- Ctx = addPassesToGenerateCode(this, PM, DisableVerify, nullptr, nullptr,
- nullptr, nullptr);
+ bool WillCompleteCodeGenPipeline = true;
+ Ctx = addPassesToGenerateCode(this, PM, DisableVerify,
+ WillCompleteCodeGenPipeline, Out,
+ /*MachineModuleInfo*/ nullptr);
if (!Ctx)
return true;
+ assert(WillCompleteCodeGenPipeline && "CodeGen pipeline has been altered");
if (Options.MCOptions.MCSaveTempLabels)
Ctx->setAllowTemporaryLabels(false);
clEnumValN(CFLAAType::Both, "both",
"Enable both variants of CFL-AA")));
+/// Option names for limiting the codegen pipeline.
+/// Those are used in error reporting and we didn't want
+/// to duplicate their names all over the place.
+const char *StartAfterOptName = "start-after";
+const char *StartBeforeOptName = "start-before";
+const char *StopAfterOptName = "stop-after";
+const char *StopBeforeOptName = "stop-before";
+
+static cl::opt<std::string>
+ StartAfterOpt(StringRef(StartAfterOptName),
+ cl::desc("Resume compilation after a specific pass"),
+ cl::value_desc("pass-name"), cl::init(""));
+
+static cl::opt<std::string>
+ StartBeforeOpt(StringRef(StartBeforeOptName),
+ cl::desc("Resume compilation before a specific pass"),
+ cl::value_desc("pass-name"), cl::init(""));
+
+static cl::opt<std::string>
+ StopAfterOpt(StringRef(StopAfterOptName),
+ cl::desc("Stop compilation after a specific pass"),
+ cl::value_desc("pass-name"), cl::init(""));
+
+static cl::opt<std::string>
+ StopBeforeOpt(StringRef(StopBeforeOptName),
+ cl::desc("Stop compilation before a specific pass"),
+ cl::value_desc("pass-name"), cl::init(""));
+
/// Allow standard passes to be disabled by command line options. This supports
/// simple binary flags that either suppress the pass or do nothing.
/// i.e. -disable-mypass=false has no effect.
delete Impl;
}
+static const PassInfo *getPassInfo(StringRef PassName) {
+ if (PassName.empty())
+ return nullptr;
+
+ const PassRegistry &PR = *PassRegistry::getPassRegistry();
+ const PassInfo *PI = PR.getPassInfo(PassName);
+ if (!PI)
+ report_fatal_error(Twine('\"') + Twine(PassName) +
+ Twine("\" pass is not registered."));
+ return PI;
+}
+
+static AnalysisID getPassIDFromName(StringRef PassName) {
+ const PassInfo *PI = getPassInfo(PassName);
+ return PI ? PI->getTypeInfo() : nullptr;
+}
+
+void TargetPassConfig::setStartStopPasses() {
+ StartBefore = getPassIDFromName(StartBeforeOpt);
+ StartAfter = getPassIDFromName(StartAfterOpt);
+ StopBefore = getPassIDFromName(StopBeforeOpt);
+ StopAfter = getPassIDFromName(StopAfterOpt);
+ if (StartBefore && StartAfter)
+ report_fatal_error(Twine(StartBeforeOptName) + Twine(" and ") +
+ Twine(StartAfterOptName) + Twine(" specified!"));
+ if (StopBefore && StopAfter)
+ report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") +
+ Twine(StopAfterOptName) + Twine(" specified!"));
+ Started = (StartAfter == nullptr) && (StartBefore == nullptr);
+}
+
// Out of line constructor provides default values for pass options and
// registers all common codegen passes.
TargetPassConfig::TargetPassConfig(LLVMTargetMachine &TM, PassManagerBase &pm)
if (TM.Options.EnableIPRA)
setRequiresCodeGenSCCOrder();
+
+ setStartStopPasses();
}
CodeGenOpt::Level TargetPassConfig::getOptLevel() const {
"triple set?");
}
+bool TargetPassConfig::hasLimitedCodeGenPipeline() const {
+ return StartBefore || StartAfter || StopBefore || StopAfter;
+}
+
+std::string
+TargetPassConfig::getLimitedCodeGenPipelineReason(const char *Separator) const {
+ if (!hasLimitedCodeGenPipeline())
+ return std::string();
+ std::string Res;
+ static cl::opt<std::string> *PassNames[] = {&StartAfterOpt, &StartBeforeOpt,
+ &StopAfterOpt, &StopBeforeOpt};
+ static const char *OptNames[] = {StartAfterOptName, StartBeforeOptName,
+ StopAfterOptName, StopBeforeOptName};
+ bool IsFirst = true;
+ for (int Idx = 0; Idx < 4; ++Idx)
+ if (!PassNames[Idx]->empty()) {
+ if (!IsFirst)
+ Res += Separator;
+ IsFirst = false;
+ Res += OptNames[Idx];
+ }
+ return Res;
+}
+
// Helper to verify the analysis is really immutable.
void TargetPassConfig::setOpt(bool &Opt, bool Val) {
assert(!Initialized && "PassConfig is immutable");
; RUN: not llc < %s -stop-before=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-STOP-BEFORE
; RUN: not llc < %s -start-after=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-START-AFTER
; RUN: not llc < %s -stop-after=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-STOP-AFTER
-; NONEXISTENT-START-BEFORE: start-before pass is not registered.
-; NONEXISTENT-STOP-BEFORE: stop-before pass is not registered.
-; NONEXISTENT-START-AFTER: start-after pass is not registered.
-; NONEXISTENT-STOP-AFTER: stop-after pass is not registered.
+; NONEXISTENT-START-BEFORE: "nonexistent" pass is not registered.
+; NONEXISTENT-STOP-BEFORE: "nonexistent" pass is not registered.
+; NONEXISTENT-START-AFTER: "nonexistent" pass is not registered.
+; NONEXISTENT-STOP-AFTER: "nonexistent" pass is not registered.
; RUN: not llc < %s -start-before=loop-reduce -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=DOUBLE-START
; RUN: not llc < %s -stop-before=loop-reduce -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=DOUBLE-STOP
-; DOUBLE-START: -start-before and -start-after specified!
-; DOUBLE-STOP: -stop-before and -stop-after specified!
+; DOUBLE-START: start-before and start-after specified!
+; DOUBLE-STOP: stop-before and stop-after specified!
cl::desc("Discard names from Value (other than GlobalValue)."),
cl::init(false), cl::Hidden);
-static cl::opt<std::string> StopBefore("stop-before",
- cl::desc("Stop compilation before a specific pass"),
- cl::value_desc("pass-name"), cl::init(""));
-
-static cl::opt<std::string> StopAfter("stop-after",
- cl::desc("Stop compilation after a specific pass"),
- cl::value_desc("pass-name"), cl::init(""));
-
-static cl::opt<std::string> StartBefore("start-before",
- cl::desc("Resume compilation before a specific pass"),
- cl::value_desc("pass-name"), cl::init(""));
-
-static cl::opt<std::string> StartAfter("start-after",
- cl::desc("Resume compilation after a specific pass"),
- cl::value_desc("pass-name"), cl::init(""));
-
static cl::list<std::string> IncludeDirs("I", cl::desc("include search path"));
static cl::opt<bool> PassRemarksWithHotness(
return false;
}
-static AnalysisID getPassID(const char *argv0, const char *OptionName,
- StringRef PassName) {
- if (PassName.empty())
- return nullptr;
-
- const PassRegistry &PR = *PassRegistry::getPassRegistry();
- const PassInfo *PI = PR.getPassInfo(PassName);
- if (!PI) {
- errs() << argv0 << ": " << OptionName << " pass is not registered.\n";
- exit(1);
- }
- return PI->getTypeInfo();
-}
-
static int compileModule(char **argv, LLVMContext &Context) {
// Load the module to be compiled...
SMDiagnostic Err;
}
const char *argv0 = argv[0];
- AnalysisID StartBeforeID = getPassID(argv0, "start-before", StartBefore);
- AnalysisID StartAfterID = getPassID(argv0, "start-after", StartAfter);
- AnalysisID StopAfterID = getPassID(argv0, "stop-after", StopAfter);
- AnalysisID StopBeforeID = getPassID(argv0, "stop-before", StopBefore);
- if (StartBeforeID && StartAfterID) {
- errs() << argv0 << ": -start-before and -start-after specified!\n";
- return 1;
- }
- if (StopBeforeID && StopAfterID) {
- errs() << argv0 << ": -stop-before and -stop-after specified!\n";
- return 1;
- }
-
- if (MIR) {
- // Construct a custom pass pipeline that starts after instruction
- // selection.
- LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine&>(*Target);
+ LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine&>(*Target);
+ MachineModuleInfo *MMI = new MachineModuleInfo(&LLVMTM);
+
+ // Construct a custom pass pipeline that starts after instruction
+ // selection.
+ if (!RunPassNames->empty()) {
+ if (!MIR) {
+ errs() << argv0 << ": run-pass is for .mir file only.\n";
+ return 1;
+ }
TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM);
+ if (TPC.hasLimitedCodeGenPipeline()) {
+ errs() << argv0 << ": run-pass cannot be used with "
+ << TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n";
+ return 1;
+ }
+
TPC.setDisableVerify(NoVerify);
PM.add(&TPC);
- MachineModuleInfo *MMI = new MachineModuleInfo(&LLVMTM);
- if (MIR->parseMachineFunctions(*M, *MMI))
- return 1;
PM.add(MMI);
TPC.printAndVerify("");
-
- if (!RunPassNames->empty()) {
- if (!StartAfter.empty() || !StopAfter.empty() || !StartBefore.empty() ||
- !StopBefore.empty()) {
- errs() << argv0 << ": start-after and/or stop-after passes are "
- "redundant when run-pass is specified.\n";
+ for (const std::string &RunPassName : *RunPassNames) {
+ if (addPass(PM, argv0, RunPassName, TPC))
return 1;
- }
-
- for (const std::string &RunPassName : *RunPassNames) {
- if (addPass(PM, argv0, RunPassName, TPC))
- return 1;
- }
- } else {
- TPC.setStartStopPasses(StartBeforeID, StartAfterID, StopBeforeID,
- StopAfterID);
- TPC.addISelPasses();
- TPC.addMachinePasses();
}
TPC.setInitialized();
-
- if (!StopBefore.empty() || !StopAfter.empty() || !RunPassNames->empty()) {
- PM.add(createPrintMIRPass(*OS));
- } else if (LLVMTM.addAsmPrinter(PM, *OS, FileType, MMI->getContext())) {
- errs() << argv0 << ": target does not support generation of this"
- << " file type!\n";
- return 1;
- }
+ PM.add(createPrintMIRPass(*OS));
PM.add(createFreeMachineFunctionPass());
- } else if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify,
- StartBeforeID, StartAfterID,
- StopBeforeID, StopAfterID)) {
+ } else if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, MMI)) {
errs() << argv0 << ": target does not support generation of this"
- << " file type!\n";
+ << " file type!\n";
return 1;
}
+ if (MIR) {
+ assert(MMI && "addPassesToEmitFile didn't set MMI");
+ if (MIR->parseMachineFunctions(*M, *MMI))
+ return 1;
+ }
+
// Before executing passes, print the final values of the LLVM options.
cl::PrintOptionValues();