1 //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/CodeGen/MachineModuleInfo.h" 10 #include "llvm/CodeGen/MachineFunction.h" 11 #include "llvm/CodeGen/Passes.h" 12 #include "llvm/IR/Constants.h" 13 #include "llvm/IR/DiagnosticInfo.h" 14 #include "llvm/IR/LLVMContext.h" 15 #include "llvm/IR/Module.h" 16 #include "llvm/InitializePasses.h" 17 #include "llvm/Target/TargetLoweringObjectFile.h" 18 #include "llvm/Target/TargetMachine.h" 19 #include <cassert> 20 21 using namespace llvm; 22 using namespace llvm::dwarf; 23 24 // Out of line virtual method. 25 MachineModuleInfoImpl::~MachineModuleInfoImpl() = default; 26 27 void MachineModuleInfo::initialize() { 28 ObjFileMMI = nullptr; 29 CurCallSite = 0; 30 NextFnNum = 0; 31 DbgInfoAvailable = false; 32 } 33 34 void MachineModuleInfo::finalize() { 35 Context.reset(); 36 // We don't clear the ExternalContext. 37 38 delete ObjFileMMI; 39 ObjFileMMI = nullptr; 40 } 41 42 MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI) 43 : TM(std::move(MMI.TM)), 44 Context(TM.getTargetTriple(), TM.getMCAsmInfo(), TM.getMCRegisterInfo(), 45 TM.getMCSubtargetInfo(), nullptr, &TM.Options.MCOptions, false), 46 MachineFunctions(std::move(MMI.MachineFunctions)) { 47 Context.setObjectFileInfo(TM.getObjFileLowering()); 48 ObjFileMMI = MMI.ObjFileMMI; 49 CurCallSite = MMI.CurCallSite; 50 ExternalContext = MMI.ExternalContext; 51 TheModule = MMI.TheModule; 52 } 53 54 MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM) 55 : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(), 56 TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(), 57 nullptr, &TM->Options.MCOptions, false) { 58 Context.setObjectFileInfo(TM->getObjFileLowering()); 59 initialize(); 60 } 61 62 MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM, 63 MCContext *ExtContext) 64 : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(), 65 TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(), 66 nullptr, &TM->Options.MCOptions, false), 67 ExternalContext(ExtContext) { 68 Context.setObjectFileInfo(TM->getObjFileLowering()); 69 initialize(); 70 } 71 72 MachineModuleInfo::~MachineModuleInfo() { finalize(); } 73 74 MachineFunction * 75 MachineModuleInfo::getMachineFunction(const Function &F) const { 76 auto I = MachineFunctions.find(&F); 77 return I != MachineFunctions.end() ? I->second.get() : nullptr; 78 } 79 80 MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) { 81 // Shortcut for the common case where a sequence of MachineFunctionPasses 82 // all query for the same Function. 83 if (LastRequest == &F) 84 return *LastResult; 85 86 auto I = MachineFunctions.insert( 87 std::make_pair(&F, std::unique_ptr<MachineFunction>())); 88 MachineFunction *MF; 89 if (I.second) { 90 // No pre-existing machine function, create a new one. 91 const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F); 92 MF = new MachineFunction(F, TM, STI, NextFnNum++, *this); 93 MF->initTargetMachineFunctionInfo(STI); 94 95 // MRI callback for target specific initializations. 96 TM.registerMachineRegisterInfoCallback(*MF); 97 98 // Update the set entry. 99 I.first->second.reset(MF); 100 } else { 101 MF = I.first->second.get(); 102 } 103 104 LastRequest = &F; 105 LastResult = MF; 106 return *MF; 107 } 108 109 void MachineModuleInfo::deleteMachineFunctionFor(Function &F) { 110 MachineFunctions.erase(&F); 111 LastRequest = nullptr; 112 LastResult = nullptr; 113 } 114 115 void MachineModuleInfo::insertFunction(const Function &F, 116 std::unique_ptr<MachineFunction> &&MF) { 117 auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF))); 118 assert(I.second && "machine function already mapped"); 119 (void)I; 120 } 121 122 namespace { 123 124 /// This pass frees the MachineFunction object associated with a Function. 125 class FreeMachineFunction : public FunctionPass { 126 public: 127 static char ID; 128 129 FreeMachineFunction() : FunctionPass(ID) {} 130 131 void getAnalysisUsage(AnalysisUsage &AU) const override { 132 AU.addRequired<MachineModuleInfoWrapperPass>(); 133 AU.addPreserved<MachineModuleInfoWrapperPass>(); 134 } 135 136 bool runOnFunction(Function &F) override { 137 MachineModuleInfo &MMI = 138 getAnalysis<MachineModuleInfoWrapperPass>().getMMI(); 139 MMI.deleteMachineFunctionFor(F); 140 return true; 141 } 142 143 StringRef getPassName() const override { 144 return "Free MachineFunction"; 145 } 146 }; 147 148 } // end anonymous namespace 149 150 char FreeMachineFunction::ID; 151 152 FunctionPass *llvm::createFreeMachineFunctionPass() { 153 return new FreeMachineFunction(); 154 } 155 156 MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( 157 const LLVMTargetMachine *TM) 158 : ImmutablePass(ID), MMI(TM) { 159 initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 160 } 161 162 MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( 163 const LLVMTargetMachine *TM, MCContext *ExtContext) 164 : ImmutablePass(ID), MMI(TM, ExtContext) { 165 initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 166 } 167 168 // Handle the Pass registration stuff necessary to use DataLayout's. 169 INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo", 170 "Machine Module Information", false, false) 171 char MachineModuleInfoWrapperPass::ID = 0; 172 173 static uint64_t getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr, 174 std::vector<const MDNode *> &LocInfos) { 175 // Look up a LocInfo for the buffer this diagnostic is coming from. 176 unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc()); 177 const MDNode *LocInfo = nullptr; 178 if (BufNum > 0 && BufNum <= LocInfos.size()) 179 LocInfo = LocInfos[BufNum - 1]; 180 181 // If the inline asm had metadata associated with it, pull out a location 182 // cookie corresponding to which line the error occurred on. 183 uint64_t LocCookie = 0; 184 if (LocInfo) { 185 unsigned ErrorLine = SMD.getLineNo() - 1; 186 if (ErrorLine >= LocInfo->getNumOperands()) 187 ErrorLine = 0; 188 189 if (LocInfo->getNumOperands() != 0) 190 if (const ConstantInt *CI = 191 mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine))) 192 LocCookie = CI->getZExtValue(); 193 } 194 195 return LocCookie; 196 } 197 198 bool MachineModuleInfoWrapperPass::doInitialization(Module &M) { 199 MMI.initialize(); 200 MMI.TheModule = &M; 201 LLVMContext &Ctx = M.getContext(); 202 MMI.getContext().setDiagnosticHandler( 203 [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm, 204 const SourceMgr &SrcMgr, 205 std::vector<const MDNode *> &LocInfos) { 206 uint64_t LocCookie = 0; 207 if (IsInlineAsm) 208 LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); 209 Ctx.diagnose( 210 DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); 211 }); 212 MMI.DbgInfoAvailable = !M.debug_compile_units().empty(); 213 return false; 214 } 215 216 bool MachineModuleInfoWrapperPass::doFinalization(Module &M) { 217 MMI.finalize(); 218 return false; 219 } 220 221 AnalysisKey MachineModuleAnalysis::Key; 222 223 MachineModuleAnalysis::Result 224 MachineModuleAnalysis::run(Module &M, ModuleAnalysisManager &) { 225 MMI.TheModule = &M; 226 LLVMContext &Ctx = M.getContext(); 227 MMI.getContext().setDiagnosticHandler( 228 [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm, 229 const SourceMgr &SrcMgr, 230 std::vector<const MDNode *> &LocInfos) { 231 unsigned LocCookie = 0; 232 if (IsInlineAsm) 233 LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); 234 Ctx.diagnose( 235 DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); 236 }); 237 MMI.DbgInfoAvailable = !M.debug_compile_units().empty(); 238 return Result(MMI); 239 } 240