| //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/CodeGen/MachineModuleInfo.h" | |
| #include "llvm/CodeGen/MachineFunction.h" | |
| #include "llvm/CodeGen/Passes.h" | |
| #include "llvm/IR/Constants.h" | |
| #include "llvm/IR/DiagnosticInfo.h" | |
| #include "llvm/IR/LLVMContext.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/InitializePasses.h" | |
| #include "llvm/Target/TargetLoweringObjectFile.h" | |
| #include "llvm/Target/TargetMachine.h" | |
| #include <cassert> | |
| using namespace llvm; | |
| using namespace llvm::dwarf; | |
| // Out of line virtual method. | |
| MachineModuleInfoImpl::~MachineModuleInfoImpl() = default; | |
| void MachineModuleInfo::initialize() { | |
| ObjFileMMI = nullptr; | |
| NextFnNum = 0; | |
| } | |
| void MachineModuleInfo::finalize() { | |
| Context.reset(); | |
| // We don't clear the ExternalContext. | |
| delete ObjFileMMI; | |
| ObjFileMMI = nullptr; | |
| } | |
| MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI) | |
| : TM(std::move(MMI.TM)), | |
| Context(TM.getTargetTriple(), TM.getMCAsmInfo(), TM.getMCRegisterInfo(), | |
| TM.getMCSubtargetInfo(), nullptr, false), | |
| MachineFunctions(std::move(MMI.MachineFunctions)) { | |
| Context.setObjectFileInfo(TM.getObjFileLowering()); | |
| ObjFileMMI = MMI.ObjFileMMI; | |
| ExternalContext = MMI.ExternalContext; | |
| TheModule = MMI.TheModule; | |
| } | |
| MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM) | |
| : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(), | |
| TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(), | |
| nullptr, false) { | |
| Context.setObjectFileInfo(TM->getObjFileLowering()); | |
| initialize(); | |
| } | |
| MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM, | |
| MCContext *ExtContext) | |
| : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(), | |
| TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(), | |
| nullptr, false), | |
| ExternalContext(ExtContext) { | |
| Context.setObjectFileInfo(TM->getObjFileLowering()); | |
| initialize(); | |
| } | |
| MachineModuleInfo::~MachineModuleInfo() { finalize(); } | |
| MachineFunction * | |
| MachineModuleInfo::getMachineFunction(const Function &F) const { | |
| auto I = MachineFunctions.find(&F); | |
| return I != MachineFunctions.end() ? I->second.get() : nullptr; | |
| } | |
| MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) { | |
| // Shortcut for the common case where a sequence of MachineFunctionPasses | |
| // all query for the same Function. | |
| if (LastRequest == &F) | |
| return *LastResult; | |
| auto I = MachineFunctions.insert( | |
| std::make_pair(&F, std::unique_ptr<MachineFunction>())); | |
| MachineFunction *MF; | |
| if (I.second) { | |
| // No pre-existing machine function, create a new one. | |
| const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F); | |
| MF = new MachineFunction(F, TM, STI, getContext(), NextFnNum++); | |
| MF->initTargetMachineFunctionInfo(STI); | |
| // MRI callback for target specific initializations. | |
| TM.registerMachineRegisterInfoCallback(*MF); | |
| // Update the set entry. | |
| I.first->second.reset(MF); | |
| } else { | |
| MF = I.first->second.get(); | |
| } | |
| LastRequest = &F; | |
| LastResult = MF; | |
| return *MF; | |
| } | |
| void MachineModuleInfo::deleteMachineFunctionFor(Function &F) { | |
| MachineFunctions.erase(&F); | |
| LastRequest = nullptr; | |
| LastResult = nullptr; | |
| } | |
| void MachineModuleInfo::insertFunction(const Function &F, | |
| std::unique_ptr<MachineFunction> &&MF) { | |
| auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF))); | |
| assert(I.second && "machine function already mapped"); | |
| (void)I; | |
| } | |
| namespace { | |
| /// This pass frees the MachineFunction object associated with a Function. | |
| class FreeMachineFunction : public FunctionPass { | |
| public: | |
| static char ID; | |
| FreeMachineFunction() : FunctionPass(ID) {} | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| AU.addRequired<MachineModuleInfoWrapperPass>(); | |
| AU.addPreserved<MachineModuleInfoWrapperPass>(); | |
| } | |
| bool runOnFunction(Function &F) override { | |
| MachineModuleInfo &MMI = | |
| getAnalysis<MachineModuleInfoWrapperPass>().getMMI(); | |
| MMI.deleteMachineFunctionFor(F); | |
| return true; | |
| } | |
| StringRef getPassName() const override { | |
| return "Free MachineFunction"; | |
| } | |
| }; | |
| } // end anonymous namespace | |
| char FreeMachineFunction::ID; | |
| FunctionPass *llvm::createFreeMachineFunctionPass() { | |
| return new FreeMachineFunction(); | |
| } | |
| MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( | |
| const TargetMachine *TM) | |
| : ImmutablePass(ID), MMI(TM) {} | |
| MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( | |
| const TargetMachine *TM, MCContext *ExtContext) | |
| : ImmutablePass(ID), MMI(TM, ExtContext) {} | |
| // Handle the Pass registration stuff necessary to use DataLayout's. | |
| INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo", | |
| "Machine Module Information", false, false) | |
| char MachineModuleInfoWrapperPass::ID = 0; | |
| static uint64_t getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr, | |
| std::vector<const MDNode *> &LocInfos) { | |
| // Look up a LocInfo for the buffer this diagnostic is coming from. | |
| unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc()); | |
| const MDNode *LocInfo = nullptr; | |
| if (BufNum > 0 && BufNum <= LocInfos.size()) | |
| LocInfo = LocInfos[BufNum - 1]; | |
| // If the inline asm had metadata associated with it, pull out a location | |
| // cookie corresponding to which line the error occurred on. | |
| uint64_t LocCookie = 0; | |
| if (LocInfo) { | |
| unsigned ErrorLine = SMD.getLineNo() - 1; | |
| if (ErrorLine >= LocInfo->getNumOperands()) | |
| ErrorLine = 0; | |
| if (LocInfo->getNumOperands() != 0) | |
| if (const ConstantInt *CI = | |
| mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine))) | |
| LocCookie = CI->getZExtValue(); | |
| } | |
| return LocCookie; | |
| } | |
| bool MachineModuleInfoWrapperPass::doInitialization(Module &M) { | |
| MMI.initialize(); | |
| MMI.TheModule = &M; | |
| LLVMContext &Ctx = M.getContext(); | |
| MMI.getContext().setDiagnosticHandler( | |
| [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm, | |
| const SourceMgr &SrcMgr, | |
| std::vector<const MDNode *> &LocInfos) { | |
| uint64_t LocCookie = 0; | |
| if (IsInlineAsm) | |
| LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); | |
| Ctx.diagnose( | |
| DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); | |
| }); | |
| return false; | |
| } | |
| bool MachineModuleInfoWrapperPass::doFinalization(Module &M) { | |
| MMI.finalize(); | |
| return false; | |
| } | |
| AnalysisKey MachineModuleAnalysis::Key; | |
| MachineModuleAnalysis::Result | |
| MachineModuleAnalysis::run(Module &M, ModuleAnalysisManager &) { | |
| MMI.TheModule = &M; | |
| LLVMContext &Ctx = M.getContext(); | |
| MMI.getContext().setDiagnosticHandler( | |
| [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm, | |
| const SourceMgr &SrcMgr, | |
| std::vector<const MDNode *> &LocInfos) { | |
| unsigned LocCookie = 0; | |
| if (IsInlineAsm) | |
| LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); | |
| Ctx.diagnose( | |
| DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); | |
| }); | |
| return Result(MMI); | |
| } |