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 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 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 578bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI) 588bcb0991SDimitry Andric : TM(std::move(MMI.TM)), 5906c3fb27SDimitry Andric Context(TM.getTargetTriple(), TM.getMCAsmInfo(), TM.getMCRegisterInfo(), 6006c3fb27SDimitry Andric TM.getMCSubtargetInfo(), nullptr, &TM.Options.MCOptions, false), 61e8d8bef9SDimitry Andric MachineFunctions(std::move(MMI.MachineFunctions)) { 6206c3fb27SDimitry 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 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 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 878bcb0991SDimitry Andric MachineModuleInfo::~MachineModuleInfo() { finalize(); } 888bcb0991SDimitry Andric 890b57cec5SDimitry Andric MachineFunction * 900b57cec5SDimitry 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 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); 10906c3fb27SDimitry Andric 11006c3fb27SDimitry Andric // MRI callback for target specific initializations. 11106c3fb27SDimitry Andric TM.registerMachineRegisterInfoCallback(*MF); 11206c3fb27SDimitry 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 1240b57cec5SDimitry Andric void MachineModuleInfo::deleteMachineFunctionFor(Function &F) { 1250b57cec5SDimitry Andric MachineFunctions.erase(&F); 1260b57cec5SDimitry Andric LastRequest = nullptr; 1270b57cec5SDimitry Andric LastResult = nullptr; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 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 1440b57cec5SDimitry Andric FreeMachineFunction() : FunctionPass(ID) {} 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 1478bcb0991SDimitry Andric AU.addRequired<MachineModuleInfoWrapperPass>(); 1488bcb0991SDimitry Andric AU.addPreserved<MachineModuleInfoWrapperPass>(); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 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 1580b57cec5SDimitry 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 1670b57cec5SDimitry Andric FunctionPass *llvm::createFreeMachineFunctionPass() { 1680b57cec5SDimitry Andric return new FreeMachineFunction(); 1690b57cec5SDimitry Andric } 1708bcb0991SDimitry Andric 1718bcb0991SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( 1728bcb0991SDimitry Andric const LLVMTargetMachine *TM) 1738bcb0991SDimitry Andric : ImmutablePass(ID), MMI(TM) { 1748bcb0991SDimitry Andric initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 1758bcb0991SDimitry Andric } 1768bcb0991SDimitry Andric 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 188*0fca6ea1SDimitry Andric static uint64_t 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. 198*0fca6ea1SDimitry Andric uint64_t 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 2138bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doInitialization(Module &M) { 2148bcb0991SDimitry Andric MMI.initialize(); 2158bcb0991SDimitry Andric MMI.TheModule = &M; 216fe6060f1SDimitry Andric LLVMContext &Ctx = M.getContext(); 217fe6060f1SDimitry Andric MMI.getContext().setDiagnosticHandler( 2181fd87a68SDimitry Andric [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm, 2191fd87a68SDimitry Andric const SourceMgr &SrcMgr, 220fe6060f1SDimitry Andric std::vector<const MDNode *> &LocInfos) { 221*0fca6ea1SDimitry Andric uint64_t LocCookie = 0; 222fe6060f1SDimitry Andric if (IsInlineAsm) 223fe6060f1SDimitry Andric LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); 2241fd87a68SDimitry Andric Ctx.diagnose( 2251fd87a68SDimitry Andric DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); 226fe6060f1SDimitry Andric }); 22781ad6265SDimitry Andric MMI.DbgInfoAvailable = !DisableDebugInfoPrinting && 22881ad6265SDimitry Andric !M.debug_compile_units().empty(); 2298bcb0991SDimitry Andric return false; 2308bcb0991SDimitry Andric } 2318bcb0991SDimitry Andric 2328bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doFinalization(Module &M) { 2338bcb0991SDimitry Andric MMI.finalize(); 2348bcb0991SDimitry Andric return false; 2358bcb0991SDimitry Andric } 2368bcb0991SDimitry Andric 2378bcb0991SDimitry Andric AnalysisKey MachineModuleAnalysis::Key; 2388bcb0991SDimitry Andric 239*0fca6ea1SDimitry Andric MachineModuleAnalysis::Result 240*0fca6ea1SDimitry Andric MachineModuleAnalysis::run(Module &M, ModuleAnalysisManager &) { 2418bcb0991SDimitry Andric MMI.TheModule = &M; 242*0fca6ea1SDimitry Andric LLVMContext &Ctx = M.getContext(); 243*0fca6ea1SDimitry Andric MMI.getContext().setDiagnosticHandler( 244*0fca6ea1SDimitry Andric [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm, 245*0fca6ea1SDimitry Andric const SourceMgr &SrcMgr, 246*0fca6ea1SDimitry Andric std::vector<const MDNode *> &LocInfos) { 247*0fca6ea1SDimitry Andric unsigned LocCookie = 0; 248*0fca6ea1SDimitry Andric if (IsInlineAsm) 249*0fca6ea1SDimitry Andric LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); 250*0fca6ea1SDimitry Andric Ctx.diagnose( 251*0fca6ea1SDimitry Andric DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); 252*0fca6ea1SDimitry Andric }); 253*0fca6ea1SDimitry Andric MMI.DbgInfoAvailable = 254*0fca6ea1SDimitry Andric !DisableDebugInfoPrinting && !M.debug_compile_units().empty(); 255*0fca6ea1SDimitry Andric return Result(MMI); 2568bcb0991SDimitry Andric } 257