1*0b57cec5SDimitry Andric //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 10*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 11*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 12*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 13*0b57cec5SDimitry 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" 17*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 18480093f4SDimitry Andric #include "llvm/InitializePasses.h" 19*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 20*0b57cec5SDimitry Andric #include "llvm/Pass.h" 2181ad6265SDimitry Andric #include "llvm/Support/CommandLine.h" 22*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 23*0b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 24*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 25*0b57cec5SDimitry Andric #include <algorithm> 26*0b57cec5SDimitry Andric #include <cassert> 27*0b57cec5SDimitry Andric #include <memory> 28*0b57cec5SDimitry Andric #include <utility> 29*0b57cec5SDimitry Andric #include <vector> 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric using namespace llvm; 32*0b57cec5SDimitry Andric using namespace llvm::dwarf; 33*0b57cec5SDimitry 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 38*0b57cec5SDimitry Andric // Out of line virtual method. 39*0b57cec5SDimitry Andric MachineModuleInfoImpl::~MachineModuleInfoImpl() = default; 40*0b57cec5SDimitry Andric 418bcb0991SDimitry Andric void MachineModuleInfo::initialize() { 42*0b57cec5SDimitry Andric ObjFileMMI = nullptr; 43*0b57cec5SDimitry Andric CurCallSite = 0; 44fe6060f1SDimitry Andric NextFnNum = 0; 4581ad6265SDimitry Andric UsesMSVCFloatingPoint = false; 4681ad6265SDimitry Andric DbgInfoAvailable = false; 47*0b57cec5SDimitry Andric } 48*0b57cec5SDimitry Andric 498bcb0991SDimitry Andric void MachineModuleInfo::finalize() { 50*0b57cec5SDimitry Andric Personalities.clear(); 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric Context.reset(); 53e8d8bef9SDimitry Andric // We don't clear the ExternalContext. 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric delete ObjFileMMI; 56*0b57cec5SDimitry Andric ObjFileMMI = nullptr; 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 598bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI) 608bcb0991SDimitry Andric : TM(std::move(MMI.TM)), 61fe6060f1SDimitry Andric Context(MMI.TM.getTargetTriple(), MMI.TM.getMCAsmInfo(), 62fe6060f1SDimitry Andric MMI.TM.getMCRegisterInfo(), MMI.TM.getMCSubtargetInfo(), nullptr, 6381ad6265SDimitry Andric &MMI.TM.Options.MCOptions, false), 64e8d8bef9SDimitry Andric MachineFunctions(std::move(MMI.MachineFunctions)) { 65fe6060f1SDimitry Andric Context.setObjectFileInfo(MMI.TM.getObjFileLowering()); 668bcb0991SDimitry Andric ObjFileMMI = MMI.ObjFileMMI; 678bcb0991SDimitry Andric CurCallSite = MMI.CurCallSite; 68e8d8bef9SDimitry Andric ExternalContext = MMI.ExternalContext; 698bcb0991SDimitry Andric TheModule = MMI.TheModule; 708bcb0991SDimitry Andric } 718bcb0991SDimitry Andric 728bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM) 73fe6060f1SDimitry Andric : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(), 74fe6060f1SDimitry Andric TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(), 7581ad6265SDimitry Andric nullptr, &TM->Options.MCOptions, false) { 76fe6060f1SDimitry Andric Context.setObjectFileInfo(TM->getObjFileLowering()); 778bcb0991SDimitry Andric initialize(); 788bcb0991SDimitry Andric } 798bcb0991SDimitry Andric 80e8d8bef9SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM, 81e8d8bef9SDimitry Andric MCContext *ExtContext) 82fe6060f1SDimitry Andric : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(), 83fe6060f1SDimitry Andric TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(), 8481ad6265SDimitry Andric nullptr, &TM->Options.MCOptions, false), 85e8d8bef9SDimitry Andric ExternalContext(ExtContext) { 86fe6060f1SDimitry Andric Context.setObjectFileInfo(TM->getObjFileLowering()); 87e8d8bef9SDimitry Andric initialize(); 88e8d8bef9SDimitry Andric } 89e8d8bef9SDimitry Andric 908bcb0991SDimitry Andric MachineModuleInfo::~MachineModuleInfo() { finalize(); } 918bcb0991SDimitry Andric 92*0b57cec5SDimitry Andric /// \name Exception Handling 93*0b57cec5SDimitry Andric /// \{ 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric void MachineModuleInfo::addPersonality(const Function *Personality) { 96fe6060f1SDimitry Andric if (!llvm::is_contained(Personalities, Personality)) 97*0b57cec5SDimitry Andric Personalities.push_back(Personality); 98*0b57cec5SDimitry Andric } 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric /// \} 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric MachineFunction * 103*0b57cec5SDimitry Andric MachineModuleInfo::getMachineFunction(const Function &F) const { 104*0b57cec5SDimitry Andric auto I = MachineFunctions.find(&F); 105*0b57cec5SDimitry Andric return I != MachineFunctions.end() ? I->second.get() : nullptr; 106*0b57cec5SDimitry Andric } 107*0b57cec5SDimitry Andric 1085ffd83dbSDimitry Andric MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) { 109*0b57cec5SDimitry Andric // Shortcut for the common case where a sequence of MachineFunctionPasses 110*0b57cec5SDimitry Andric // all query for the same Function. 111*0b57cec5SDimitry Andric if (LastRequest == &F) 112*0b57cec5SDimitry Andric return *LastResult; 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric auto I = MachineFunctions.insert( 115*0b57cec5SDimitry Andric std::make_pair(&F, std::unique_ptr<MachineFunction>())); 116*0b57cec5SDimitry Andric MachineFunction *MF; 117*0b57cec5SDimitry Andric if (I.second) { 118*0b57cec5SDimitry Andric // No pre-existing machine function, create a new one. 119*0b57cec5SDimitry Andric const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F); 120*0b57cec5SDimitry Andric MF = new MachineFunction(F, TM, STI, NextFnNum++, *this); 121*0b57cec5SDimitry Andric // Update the set entry. 122*0b57cec5SDimitry Andric I.first->second.reset(MF); 123*0b57cec5SDimitry Andric } else { 124*0b57cec5SDimitry Andric MF = I.first->second.get(); 125*0b57cec5SDimitry Andric } 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric LastRequest = &F; 128*0b57cec5SDimitry Andric LastResult = MF; 129*0b57cec5SDimitry Andric return *MF; 130*0b57cec5SDimitry Andric } 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric void MachineModuleInfo::deleteMachineFunctionFor(Function &F) { 133*0b57cec5SDimitry Andric MachineFunctions.erase(&F); 134*0b57cec5SDimitry Andric LastRequest = nullptr; 135*0b57cec5SDimitry Andric LastResult = nullptr; 136*0b57cec5SDimitry Andric } 137*0b57cec5SDimitry Andric 13881ad6265SDimitry Andric void MachineModuleInfo::insertFunction(const Function &F, 13981ad6265SDimitry Andric std::unique_ptr<MachineFunction> &&MF) { 14081ad6265SDimitry Andric auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF))); 14181ad6265SDimitry Andric assert(I.second && "machine function already mapped"); 14281ad6265SDimitry Andric (void)I; 14381ad6265SDimitry Andric } 14481ad6265SDimitry Andric 145*0b57cec5SDimitry Andric namespace { 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric /// This pass frees the MachineFunction object associated with a Function. 148*0b57cec5SDimitry Andric class FreeMachineFunction : public FunctionPass { 149*0b57cec5SDimitry Andric public: 150*0b57cec5SDimitry Andric static char ID; 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric FreeMachineFunction() : FunctionPass(ID) {} 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 1558bcb0991SDimitry Andric AU.addRequired<MachineModuleInfoWrapperPass>(); 1568bcb0991SDimitry Andric AU.addPreserved<MachineModuleInfoWrapperPass>(); 157*0b57cec5SDimitry Andric } 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric bool runOnFunction(Function &F) override { 1608bcb0991SDimitry Andric MachineModuleInfo &MMI = 1618bcb0991SDimitry Andric getAnalysis<MachineModuleInfoWrapperPass>().getMMI(); 162*0b57cec5SDimitry Andric MMI.deleteMachineFunctionFor(F); 163*0b57cec5SDimitry Andric return true; 164*0b57cec5SDimitry Andric } 165*0b57cec5SDimitry Andric 166*0b57cec5SDimitry Andric StringRef getPassName() const override { 167*0b57cec5SDimitry Andric return "Free MachineFunction"; 168*0b57cec5SDimitry Andric } 169*0b57cec5SDimitry Andric }; 170*0b57cec5SDimitry Andric 171*0b57cec5SDimitry Andric } // end anonymous namespace 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric char FreeMachineFunction::ID; 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric FunctionPass *llvm::createFreeMachineFunctionPass() { 176*0b57cec5SDimitry Andric return new FreeMachineFunction(); 177*0b57cec5SDimitry Andric } 1788bcb0991SDimitry Andric 1798bcb0991SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( 1808bcb0991SDimitry Andric const LLVMTargetMachine *TM) 1818bcb0991SDimitry Andric : ImmutablePass(ID), MMI(TM) { 1828bcb0991SDimitry Andric initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 1838bcb0991SDimitry Andric } 1848bcb0991SDimitry Andric 185e8d8bef9SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( 186e8d8bef9SDimitry Andric const LLVMTargetMachine *TM, MCContext *ExtContext) 187e8d8bef9SDimitry Andric : ImmutablePass(ID), MMI(TM, ExtContext) { 188e8d8bef9SDimitry Andric initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 189e8d8bef9SDimitry Andric } 190e8d8bef9SDimitry Andric 1918bcb0991SDimitry Andric // Handle the Pass registration stuff necessary to use DataLayout's. 1928bcb0991SDimitry Andric INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo", 1938bcb0991SDimitry Andric "Machine Module Information", false, false) 1948bcb0991SDimitry Andric char MachineModuleInfoWrapperPass::ID = 0; 1958bcb0991SDimitry Andric 196fe6060f1SDimitry Andric static unsigned getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr, 197fe6060f1SDimitry Andric std::vector<const MDNode *> &LocInfos) { 198fe6060f1SDimitry Andric // Look up a LocInfo for the buffer this diagnostic is coming from. 199fe6060f1SDimitry Andric unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc()); 200fe6060f1SDimitry Andric const MDNode *LocInfo = nullptr; 201fe6060f1SDimitry Andric if (BufNum > 0 && BufNum <= LocInfos.size()) 202fe6060f1SDimitry Andric LocInfo = LocInfos[BufNum - 1]; 203fe6060f1SDimitry Andric 204fe6060f1SDimitry Andric // If the inline asm had metadata associated with it, pull out a location 205fe6060f1SDimitry Andric // cookie corresponding to which line the error occurred on. 206fe6060f1SDimitry Andric unsigned LocCookie = 0; 207fe6060f1SDimitry Andric if (LocInfo) { 208fe6060f1SDimitry Andric unsigned ErrorLine = SMD.getLineNo() - 1; 209fe6060f1SDimitry Andric if (ErrorLine >= LocInfo->getNumOperands()) 210fe6060f1SDimitry Andric ErrorLine = 0; 211fe6060f1SDimitry Andric 212fe6060f1SDimitry Andric if (LocInfo->getNumOperands() != 0) 213fe6060f1SDimitry Andric if (const ConstantInt *CI = 214fe6060f1SDimitry Andric mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine))) 215fe6060f1SDimitry Andric LocCookie = CI->getZExtValue(); 216fe6060f1SDimitry Andric } 217fe6060f1SDimitry Andric 218fe6060f1SDimitry Andric return LocCookie; 219fe6060f1SDimitry Andric } 220fe6060f1SDimitry Andric 2218bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doInitialization(Module &M) { 2228bcb0991SDimitry Andric MMI.initialize(); 2238bcb0991SDimitry Andric MMI.TheModule = &M; 224fe6060f1SDimitry Andric // FIXME: Do this for new pass manager. 225fe6060f1SDimitry Andric LLVMContext &Ctx = M.getContext(); 226fe6060f1SDimitry Andric MMI.getContext().setDiagnosticHandler( 2271fd87a68SDimitry Andric [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm, 2281fd87a68SDimitry Andric const SourceMgr &SrcMgr, 229fe6060f1SDimitry Andric std::vector<const MDNode *> &LocInfos) { 230fe6060f1SDimitry Andric unsigned LocCookie = 0; 231fe6060f1SDimitry Andric if (IsInlineAsm) 232fe6060f1SDimitry Andric LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); 2331fd87a68SDimitry Andric Ctx.diagnose( 2341fd87a68SDimitry Andric DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); 235fe6060f1SDimitry Andric }); 23681ad6265SDimitry Andric MMI.DbgInfoAvailable = !DisableDebugInfoPrinting && 23781ad6265SDimitry Andric !M.debug_compile_units().empty(); 2388bcb0991SDimitry Andric return false; 2398bcb0991SDimitry Andric } 2408bcb0991SDimitry Andric 2418bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doFinalization(Module &M) { 2428bcb0991SDimitry Andric MMI.finalize(); 2438bcb0991SDimitry Andric return false; 2448bcb0991SDimitry Andric } 2458bcb0991SDimitry Andric 2468bcb0991SDimitry Andric AnalysisKey MachineModuleAnalysis::Key; 2478bcb0991SDimitry Andric 2488bcb0991SDimitry Andric MachineModuleInfo MachineModuleAnalysis::run(Module &M, 2498bcb0991SDimitry Andric ModuleAnalysisManager &) { 2508bcb0991SDimitry Andric MachineModuleInfo MMI(TM); 2518bcb0991SDimitry Andric MMI.TheModule = &M; 25281ad6265SDimitry Andric MMI.DbgInfoAvailable = !DisableDebugInfoPrinting && 25381ad6265SDimitry Andric !M.debug_compile_units().empty(); 2548bcb0991SDimitry Andric return MMI; 2558bcb0991SDimitry Andric } 256