AsmPrinter needs to hold state between doInitialization, runOnMachineFunction, and doFinalization, which are all separate passes in the NewPM. Storing this state externally somewhere like MachineModuleInfo or a new analysis is possible, but a bit messy given some state, particularly EHHandler objects, has backreferences into the AsmPrinter and assumes there is a single AsmPrinter throughout the entire compilation. So instead, store AsmPrinter in an analysis that stays constant throughout compilation which solves all these problems. This also means we can also just let AsmPrinter continue to own the MCStreamer, which means object file emission should work after this as well. This does require passing the ModuleAnalysisManager into buildCodeGenPipeline to register the AsmPrinterAnalysis, but that seems pretty reasonable to do. Reviewers: paperchalice, RKSimon, arsenm Pull Request: https://github.com/llvm/llvm-project/pull/191535
211 lines
7.0 KiB
C++
211 lines
7.0 KiB
C++
//===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file
|
|
///
|
|
/// This file is just a split of the code that logically belongs in llc.cpp but
|
|
/// that includes the new pass manager headers.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "NewPMDriver.h"
|
|
#include "llvm/Analysis/CGSCCPassManager.h"
|
|
#include "llvm/Analysis/RuntimeLibcallInfo.h"
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
#include "llvm/CodeGen/CommandFlags.h"
|
|
#include "llvm/CodeGen/LibcallLoweringInfo.h"
|
|
#include "llvm/CodeGen/MIRParser/MIRParser.h"
|
|
#include "llvm/CodeGen/MIRPrinter.h"
|
|
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/CodeGen/MachinePassManager.h"
|
|
#include "llvm/CodeGen/MachineVerifier.h"
|
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
|
#include "llvm/IR/DiagnosticPrinter.h"
|
|
#include "llvm/IR/IRPrintingPasses.h"
|
|
#include "llvm/IR/LLVMContext.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
#include "llvm/IR/Verifier.h"
|
|
#include "llvm/IRReader/IRReader.h"
|
|
#include "llvm/Passes/PassBuilder.h"
|
|
#include "llvm/Passes/StandardInstrumentations.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/FormattedStream.h"
|
|
#include "llvm/Support/ToolOutputFile.h"
|
|
#include "llvm/Support/WithColor.h"
|
|
#include "llvm/Target/CGPassBuilderOption.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
|
#include "llvm/Transforms/Utils/Cloning.h"
|
|
|
|
using namespace llvm;
|
|
|
|
static cl::opt<RegAllocType, false, RegAllocTypeParser>
|
|
RegAlloc("regalloc-npm",
|
|
cl::desc("Register allocator to use for new pass manager"),
|
|
cl::Hidden, cl::init(RegAllocType::Unset));
|
|
|
|
static cl::opt<bool>
|
|
DebugPM("debug-pass-manager", cl::Hidden,
|
|
cl::desc("Print pass management debugging information"));
|
|
|
|
bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
|
|
DiagnosticHandler::handleDiagnostics(DI);
|
|
if (DI.getKind() == llvm::DK_SrcMgr) {
|
|
const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
|
|
const SMDiagnostic &SMD = DISM.getSMDiag();
|
|
|
|
SMD.print(nullptr, errs());
|
|
|
|
// For testing purposes, we print the LocCookie here.
|
|
if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
|
|
WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
|
|
|
|
return true;
|
|
}
|
|
|
|
if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
|
|
if (!Remark->isEnabled())
|
|
return true;
|
|
|
|
DiagnosticPrinterRawOStream DP(errs());
|
|
errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
|
|
DI.print(DP);
|
|
errs() << "\n";
|
|
return true;
|
|
}
|
|
|
|
static llvm::ExitOnError ExitOnErr;
|
|
|
|
int llvm::compileModuleWithNewPM(
|
|
StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
|
|
std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
|
|
std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context,
|
|
const TargetLibraryInfoImpl &TLII, VerifierKind VK, StringRef PassPipeline,
|
|
CodeGenFileType FileType) {
|
|
|
|
if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) {
|
|
WithColor::error(errs(), Arg0)
|
|
<< "--passes cannot be used with "
|
|
<< TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n";
|
|
return 1;
|
|
}
|
|
|
|
raw_pwrite_stream *OS = &Out->os();
|
|
|
|
std::unique_ptr<buffer_ostream> BOS;
|
|
if (codegen::getFileType() != CodeGenFileType::AssemblyFile &&
|
|
!Out->os().supportsSeeking()) {
|
|
BOS = std::make_unique<buffer_ostream>(Out->os());
|
|
OS = BOS.get();
|
|
}
|
|
|
|
// Fetch options from TargetPassConfig
|
|
CGPassBuilderOption Opt = getCGPassBuilderOption();
|
|
Opt.DisableVerify = VK != VerifierKind::InputOutput;
|
|
Opt.DebugPM = DebugPM;
|
|
Opt.RegAlloc = RegAlloc;
|
|
|
|
MachineModuleInfo MMI(Target.get());
|
|
|
|
PassInstrumentationCallbacks PIC;
|
|
StandardInstrumentations SI(Context, Opt.DebugPM,
|
|
VK == VerifierKind::EachPass);
|
|
registerCodeGenCallback(PIC, *Target);
|
|
|
|
MachineFunctionAnalysisManager MFAM;
|
|
LoopAnalysisManager LAM;
|
|
FunctionAnalysisManager FAM;
|
|
CGSCCAnalysisManager CGAM;
|
|
ModuleAnalysisManager MAM;
|
|
PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
|
|
PB.registerModuleAnalyses(MAM);
|
|
PB.registerCGSCCAnalyses(CGAM);
|
|
PB.registerFunctionAnalyses(FAM);
|
|
PB.registerLoopAnalyses(LAM);
|
|
PB.registerMachineFunctionAnalyses(MFAM);
|
|
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM);
|
|
SI.registerCallbacks(PIC, &MAM);
|
|
|
|
FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
|
|
|
|
MAM.registerPass([&] {
|
|
const TargetOptions &Options = Target->Options;
|
|
return RuntimeLibraryAnalysis(
|
|
M->getTargetTriple(), Target->Options.ExceptionModel,
|
|
Target->Options.FloatABIType, Target->Options.EABIVersion,
|
|
Options.MCOptions.ABIName, Target->Options.VecLib);
|
|
});
|
|
MAM.registerPass([&] { return LibcallLoweringModuleAnalysis(); });
|
|
|
|
MAM.registerPass([&] { return MachineModuleAnalysis(MMI); });
|
|
|
|
ModulePassManager MPM;
|
|
FunctionPassManager FPM;
|
|
|
|
if (!PassPipeline.empty()) {
|
|
// Construct a custom pass pipeline that starts after instruction
|
|
// selection.
|
|
|
|
if (!MIR) {
|
|
WithColor::error(errs(), Arg0) << "-passes is for .mir file only.\n";
|
|
return 1;
|
|
}
|
|
|
|
// FIXME: verify that there are no IR passes.
|
|
ExitOnErr(PB.parsePassPipeline(MPM, PassPipeline));
|
|
MPM.addPass(PrintMIRPreparePass(*OS));
|
|
MachineFunctionPassManager MFPM;
|
|
if (VK == VerifierKind::InputOutput)
|
|
MFPM.addPass(MachineVerifierPass());
|
|
MFPM.addPass(PrintMIRPass(*OS));
|
|
FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
|
|
|
} else {
|
|
ExitOnErr(Target->buildCodeGenPipeline(
|
|
MPM, MAM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt,
|
|
MMI.getContext(), &PIC));
|
|
}
|
|
|
|
// If user only wants to print the pipeline, print it before parsing the MIR.
|
|
if (PrintPipelinePasses) {
|
|
std::string PipelineStr;
|
|
raw_string_ostream OS(PipelineStr);
|
|
MPM.printPipeline(OS, [&PIC](StringRef ClassName) {
|
|
auto PassName = PIC.getPassNameForClassName(ClassName);
|
|
return PassName.empty() ? ClassName : PassName;
|
|
});
|
|
outs() << PipelineStr << '\n';
|
|
return 0;
|
|
}
|
|
|
|
if (MIR && MIR->parseMachineFunctions(*M, MAM))
|
|
return 1;
|
|
|
|
// Before executing passes, print the final values of the LLVM options.
|
|
cl::PrintOptionValues();
|
|
|
|
MPM.run(*M, MAM);
|
|
|
|
if (Context.getDiagHandlerPtr()->HasErrors)
|
|
return 1;
|
|
|
|
// Declare success.
|
|
Out->keep();
|
|
if (DwoOut)
|
|
DwoOut->keep();
|
|
|
|
return 0;
|
|
}
|