10b57cec5SDimitry Andric //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
100b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
110b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
120b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
1481ad6265SDimitry Andric #include "llvm/IR/Constants.h"
15fe6060f1SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
16fe6060f1SDimitry Andric #include "llvm/IR/LLVMContext.h"
170b57cec5SDimitry Andric #include "llvm/IR/Module.h"
18480093f4SDimitry Andric #include "llvm/InitializePasses.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
200b57cec5SDimitry Andric #include "llvm/Pass.h"
2181ad6265SDimitry Andric #include "llvm/Support/CommandLine.h"
220b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
230b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
240b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
250b57cec5SDimitry Andric #include <algorithm>
260b57cec5SDimitry Andric #include <cassert>
270b57cec5SDimitry Andric #include <memory>
280b57cec5SDimitry Andric #include <utility>
290b57cec5SDimitry Andric #include <vector>
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric using namespace llvm::dwarf;
330b57cec5SDimitry Andric
3481ad6265SDimitry Andric static cl::opt<bool>
3581ad6265SDimitry Andric DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
3681ad6265SDimitry Andric cl::desc("Disable debug info printing"));
3781ad6265SDimitry Andric
380b57cec5SDimitry Andric // Out of line virtual method.
390b57cec5SDimitry Andric MachineModuleInfoImpl::~MachineModuleInfoImpl() = default;
400b57cec5SDimitry Andric
initialize()418bcb0991SDimitry Andric void MachineModuleInfo::initialize() {
420b57cec5SDimitry Andric ObjFileMMI = nullptr;
430b57cec5SDimitry Andric CurCallSite = 0;
44fe6060f1SDimitry Andric NextFnNum = 0;
4581ad6265SDimitry Andric UsesMSVCFloatingPoint = false;
4681ad6265SDimitry Andric DbgInfoAvailable = false;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric
finalize()498bcb0991SDimitry Andric void MachineModuleInfo::finalize() {
500b57cec5SDimitry Andric Context.reset();
51e8d8bef9SDimitry Andric // We don't clear the ExternalContext.
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric delete ObjFileMMI;
540b57cec5SDimitry Andric ObjFileMMI = nullptr;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric
MachineModuleInfo(MachineModuleInfo && MMI)578bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
588bcb0991SDimitry Andric : TM(std::move(MMI.TM)),
59*fe013be4SDimitry Andric Context(TM.getTargetTriple(), TM.getMCAsmInfo(), TM.getMCRegisterInfo(),
60*fe013be4SDimitry Andric TM.getMCSubtargetInfo(), nullptr, &TM.Options.MCOptions, false),
61e8d8bef9SDimitry Andric MachineFunctions(std::move(MMI.MachineFunctions)) {
62*fe013be4SDimitry Andric Context.setObjectFileInfo(TM.getObjFileLowering());
638bcb0991SDimitry Andric ObjFileMMI = MMI.ObjFileMMI;
648bcb0991SDimitry Andric CurCallSite = MMI.CurCallSite;
65e8d8bef9SDimitry Andric ExternalContext = MMI.ExternalContext;
668bcb0991SDimitry Andric TheModule = MMI.TheModule;
678bcb0991SDimitry Andric }
688bcb0991SDimitry Andric
MachineModuleInfo(const LLVMTargetMachine * TM)698bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM)
70fe6060f1SDimitry Andric : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
71fe6060f1SDimitry Andric TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
7281ad6265SDimitry Andric nullptr, &TM->Options.MCOptions, false) {
73fe6060f1SDimitry Andric Context.setObjectFileInfo(TM->getObjFileLowering());
748bcb0991SDimitry Andric initialize();
758bcb0991SDimitry Andric }
768bcb0991SDimitry Andric
MachineModuleInfo(const LLVMTargetMachine * TM,MCContext * ExtContext)77e8d8bef9SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM,
78e8d8bef9SDimitry Andric MCContext *ExtContext)
79fe6060f1SDimitry Andric : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
80fe6060f1SDimitry Andric TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
8181ad6265SDimitry Andric nullptr, &TM->Options.MCOptions, false),
82e8d8bef9SDimitry Andric ExternalContext(ExtContext) {
83fe6060f1SDimitry Andric Context.setObjectFileInfo(TM->getObjFileLowering());
84e8d8bef9SDimitry Andric initialize();
85e8d8bef9SDimitry Andric }
86e8d8bef9SDimitry Andric
~MachineModuleInfo()878bcb0991SDimitry Andric MachineModuleInfo::~MachineModuleInfo() { finalize(); }
888bcb0991SDimitry Andric
890b57cec5SDimitry Andric MachineFunction *
getMachineFunction(const Function & F) const900b57cec5SDimitry Andric MachineModuleInfo::getMachineFunction(const Function &F) const {
910b57cec5SDimitry Andric auto I = MachineFunctions.find(&F);
920b57cec5SDimitry Andric return I != MachineFunctions.end() ? I->second.get() : nullptr;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric
getOrCreateMachineFunction(Function & F)955ffd83dbSDimitry Andric MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) {
960b57cec5SDimitry Andric // Shortcut for the common case where a sequence of MachineFunctionPasses
970b57cec5SDimitry Andric // all query for the same Function.
980b57cec5SDimitry Andric if (LastRequest == &F)
990b57cec5SDimitry Andric return *LastResult;
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric auto I = MachineFunctions.insert(
1020b57cec5SDimitry Andric std::make_pair(&F, std::unique_ptr<MachineFunction>()));
1030b57cec5SDimitry Andric MachineFunction *MF;
1040b57cec5SDimitry Andric if (I.second) {
1050b57cec5SDimitry Andric // No pre-existing machine function, create a new one.
1060b57cec5SDimitry Andric const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F);
1070b57cec5SDimitry Andric MF = new MachineFunction(F, TM, STI, NextFnNum++, *this);
108bdd1243dSDimitry Andric MF->initTargetMachineFunctionInfo(STI);
109*fe013be4SDimitry Andric
110*fe013be4SDimitry Andric // MRI callback for target specific initializations.
111*fe013be4SDimitry Andric TM.registerMachineRegisterInfoCallback(*MF);
112*fe013be4SDimitry Andric
1130b57cec5SDimitry Andric // Update the set entry.
1140b57cec5SDimitry Andric I.first->second.reset(MF);
1150b57cec5SDimitry Andric } else {
1160b57cec5SDimitry Andric MF = I.first->second.get();
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric LastRequest = &F;
1200b57cec5SDimitry Andric LastResult = MF;
1210b57cec5SDimitry Andric return *MF;
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric
deleteMachineFunctionFor(Function & F)1240b57cec5SDimitry Andric void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
1250b57cec5SDimitry Andric MachineFunctions.erase(&F);
1260b57cec5SDimitry Andric LastRequest = nullptr;
1270b57cec5SDimitry Andric LastResult = nullptr;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric
insertFunction(const Function & F,std::unique_ptr<MachineFunction> && MF)13081ad6265SDimitry Andric void MachineModuleInfo::insertFunction(const Function &F,
13181ad6265SDimitry Andric std::unique_ptr<MachineFunction> &&MF) {
13281ad6265SDimitry Andric auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF)));
13381ad6265SDimitry Andric assert(I.second && "machine function already mapped");
13481ad6265SDimitry Andric (void)I;
13581ad6265SDimitry Andric }
13681ad6265SDimitry Andric
1370b57cec5SDimitry Andric namespace {
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric /// This pass frees the MachineFunction object associated with a Function.
1400b57cec5SDimitry Andric class FreeMachineFunction : public FunctionPass {
1410b57cec5SDimitry Andric public:
1420b57cec5SDimitry Andric static char ID;
1430b57cec5SDimitry Andric
FreeMachineFunction()1440b57cec5SDimitry Andric FreeMachineFunction() : FunctionPass(ID) {}
1450b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const1460b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
1478bcb0991SDimitry Andric AU.addRequired<MachineModuleInfoWrapperPass>();
1488bcb0991SDimitry Andric AU.addPreserved<MachineModuleInfoWrapperPass>();
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric
runOnFunction(Function & F)1510b57cec5SDimitry Andric bool runOnFunction(Function &F) override {
1528bcb0991SDimitry Andric MachineModuleInfo &MMI =
1538bcb0991SDimitry Andric getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1540b57cec5SDimitry Andric MMI.deleteMachineFunctionFor(F);
1550b57cec5SDimitry Andric return true;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric
getPassName() const1580b57cec5SDimitry Andric StringRef getPassName() const override {
1590b57cec5SDimitry Andric return "Free MachineFunction";
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric };
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric } // end anonymous namespace
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric char FreeMachineFunction::ID;
1660b57cec5SDimitry Andric
createFreeMachineFunctionPass()1670b57cec5SDimitry Andric FunctionPass *llvm::createFreeMachineFunctionPass() {
1680b57cec5SDimitry Andric return new FreeMachineFunction();
1690b57cec5SDimitry Andric }
1708bcb0991SDimitry Andric
MachineModuleInfoWrapperPass(const LLVMTargetMachine * TM)1718bcb0991SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
1728bcb0991SDimitry Andric const LLVMTargetMachine *TM)
1738bcb0991SDimitry Andric : ImmutablePass(ID), MMI(TM) {
1748bcb0991SDimitry Andric initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
1758bcb0991SDimitry Andric }
1768bcb0991SDimitry Andric
MachineModuleInfoWrapperPass(const LLVMTargetMachine * TM,MCContext * ExtContext)177e8d8bef9SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
178e8d8bef9SDimitry Andric const LLVMTargetMachine *TM, MCContext *ExtContext)
179e8d8bef9SDimitry Andric : ImmutablePass(ID), MMI(TM, ExtContext) {
180e8d8bef9SDimitry Andric initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
181e8d8bef9SDimitry Andric }
182e8d8bef9SDimitry Andric
1838bcb0991SDimitry Andric // Handle the Pass registration stuff necessary to use DataLayout's.
1848bcb0991SDimitry Andric INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo",
1858bcb0991SDimitry Andric "Machine Module Information", false, false)
1868bcb0991SDimitry Andric char MachineModuleInfoWrapperPass::ID = 0;
1878bcb0991SDimitry Andric
getLocCookie(const SMDiagnostic & SMD,const SourceMgr & SrcMgr,std::vector<const MDNode * > & LocInfos)188fe6060f1SDimitry Andric static unsigned getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr,
189fe6060f1SDimitry Andric std::vector<const MDNode *> &LocInfos) {
190fe6060f1SDimitry Andric // Look up a LocInfo for the buffer this diagnostic is coming from.
191fe6060f1SDimitry Andric unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc());
192fe6060f1SDimitry Andric const MDNode *LocInfo = nullptr;
193fe6060f1SDimitry Andric if (BufNum > 0 && BufNum <= LocInfos.size())
194fe6060f1SDimitry Andric LocInfo = LocInfos[BufNum - 1];
195fe6060f1SDimitry Andric
196fe6060f1SDimitry Andric // If the inline asm had metadata associated with it, pull out a location
197fe6060f1SDimitry Andric // cookie corresponding to which line the error occurred on.
198fe6060f1SDimitry Andric unsigned LocCookie = 0;
199fe6060f1SDimitry Andric if (LocInfo) {
200fe6060f1SDimitry Andric unsigned ErrorLine = SMD.getLineNo() - 1;
201fe6060f1SDimitry Andric if (ErrorLine >= LocInfo->getNumOperands())
202fe6060f1SDimitry Andric ErrorLine = 0;
203fe6060f1SDimitry Andric
204fe6060f1SDimitry Andric if (LocInfo->getNumOperands() != 0)
205fe6060f1SDimitry Andric if (const ConstantInt *CI =
206fe6060f1SDimitry Andric mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
207fe6060f1SDimitry Andric LocCookie = CI->getZExtValue();
208fe6060f1SDimitry Andric }
209fe6060f1SDimitry Andric
210fe6060f1SDimitry Andric return LocCookie;
211fe6060f1SDimitry Andric }
212fe6060f1SDimitry Andric
doInitialization(Module & M)2138bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doInitialization(Module &M) {
2148bcb0991SDimitry Andric MMI.initialize();
2158bcb0991SDimitry Andric MMI.TheModule = &M;
216fe6060f1SDimitry Andric // FIXME: Do this for new pass manager.
217fe6060f1SDimitry Andric LLVMContext &Ctx = M.getContext();
218fe6060f1SDimitry Andric MMI.getContext().setDiagnosticHandler(
2191fd87a68SDimitry Andric [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
2201fd87a68SDimitry Andric const SourceMgr &SrcMgr,
221fe6060f1SDimitry Andric std::vector<const MDNode *> &LocInfos) {
222fe6060f1SDimitry Andric unsigned LocCookie = 0;
223fe6060f1SDimitry Andric if (IsInlineAsm)
224fe6060f1SDimitry Andric LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
2251fd87a68SDimitry Andric Ctx.diagnose(
2261fd87a68SDimitry Andric DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
227fe6060f1SDimitry Andric });
22881ad6265SDimitry Andric MMI.DbgInfoAvailable = !DisableDebugInfoPrinting &&
22981ad6265SDimitry Andric !M.debug_compile_units().empty();
2308bcb0991SDimitry Andric return false;
2318bcb0991SDimitry Andric }
2328bcb0991SDimitry Andric
doFinalization(Module & M)2338bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doFinalization(Module &M) {
2348bcb0991SDimitry Andric MMI.finalize();
2358bcb0991SDimitry Andric return false;
2368bcb0991SDimitry Andric }
2378bcb0991SDimitry Andric
2388bcb0991SDimitry Andric AnalysisKey MachineModuleAnalysis::Key;
2398bcb0991SDimitry Andric
run(Module & M,ModuleAnalysisManager &)2408bcb0991SDimitry Andric MachineModuleInfo MachineModuleAnalysis::run(Module &M,
2418bcb0991SDimitry Andric ModuleAnalysisManager &) {
2428bcb0991SDimitry Andric MachineModuleInfo MMI(TM);
2438bcb0991SDimitry Andric MMI.TheModule = &M;
24481ad6265SDimitry Andric MMI.DbgInfoAvailable = !DisableDebugInfoPrinting &&
24581ad6265SDimitry Andric !M.debug_compile_units().empty();
2468bcb0991SDimitry Andric return MMI;
2478bcb0991SDimitry Andric }
248