//===-- 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/ADT/DenseMap.h" #include "llvm/ADT/StringRef.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/MC/MCContext.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include #include #include #include #include using namespace llvm; using namespace llvm::dwarf; static cl::opt DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden, cl::desc("Disable debug info printing")); // Out of line virtual method. MachineModuleInfoImpl::~MachineModuleInfoImpl() = default; void MachineModuleInfo::initialize() { ObjFileMMI = nullptr; CurCallSite = 0; NextFnNum = 0; UsesMSVCFloatingPoint = false; DbgInfoAvailable = false; } 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(MMI.TM.getTargetTriple(), MMI.TM.getMCAsmInfo(), MMI.TM.getMCRegisterInfo(), MMI.TM.getMCSubtargetInfo(), nullptr, &MMI.TM.Options.MCOptions, false), MachineFunctions(std::move(MMI.MachineFunctions)) { Context.setObjectFileInfo(MMI.TM.getObjFileLowering()); ObjFileMMI = MMI.ObjFileMMI; CurCallSite = MMI.CurCallSite; ExternalContext = MMI.ExternalContext; TheModule = MMI.TheModule; } MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM) : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(), TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(), nullptr, &TM->Options.MCOptions, false) { Context.setObjectFileInfo(TM->getObjFileLowering()); initialize(); } MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM, MCContext *ExtContext) : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(), TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(), nullptr, &TM->Options.MCOptions, 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 *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, NextFnNum++, *this); MF->initTargetMachineFunctionInfo(STI); // 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 &&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(); AU.addPreserved(); } bool runOnFunction(Function &F) override { MachineModuleInfo &MMI = getAnalysis().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 LLVMTargetMachine *TM) : ImmutablePass(ID), MMI(TM) { initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); } MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( const LLVMTargetMachine *TM, MCContext *ExtContext) : ImmutablePass(ID), MMI(TM, ExtContext) { initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); } // Handle the Pass registration stuff necessary to use DataLayout's. INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo", "Machine Module Information", false, false) char MachineModuleInfoWrapperPass::ID = 0; static unsigned getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr, std::vector &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. unsigned 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(LocInfo->getOperand(ErrorLine))) LocCookie = CI->getZExtValue(); } return LocCookie; } bool MachineModuleInfoWrapperPass::doInitialization(Module &M) { MMI.initialize(); MMI.TheModule = &M; // FIXME: Do this for new pass manager. LLVMContext &Ctx = M.getContext(); MMI.getContext().setDiagnosticHandler( [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm, const SourceMgr &SrcMgr, std::vector &LocInfos) { unsigned LocCookie = 0; if (IsInlineAsm) LocCookie = getLocCookie(SMD, SrcMgr, LocInfos); Ctx.diagnose( DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); }); MMI.DbgInfoAvailable = !DisableDebugInfoPrinting && !M.debug_compile_units().empty(); return false; } bool MachineModuleInfoWrapperPass::doFinalization(Module &M) { MMI.finalize(); return false; } AnalysisKey MachineModuleAnalysis::Key; MachineModuleInfo MachineModuleAnalysis::run(Module &M, ModuleAnalysisManager &) { MachineModuleInfo MMI(TM); MMI.TheModule = &M; MMI.DbgInfoAvailable = !DisableDebugInfoPrinting && !M.debug_compile_units().empty(); return MMI; }