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