xref: /src/contrib/llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1009b1c42SEd Schouten //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten 
97ab83427SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
10f382538dSDimitry Andric #include "llvm/ADT/DenseMap.h"
11f382538dSDimitry Andric #include "llvm/ADT/StringRef.h"
12009b1c42SEd Schouten #include "llvm/CodeGen/MachineFunction.h"
13009b1c42SEd Schouten #include "llvm/CodeGen/Passes.h"
14145449b1SDimitry Andric #include "llvm/IR/Constants.h"
15344a3780SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
16344a3780SDimitry Andric #include "llvm/IR/LLVMContext.h"
174a16efa3SDimitry Andric #include "llvm/IR/Module.h"
18706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
19f382538dSDimitry Andric #include "llvm/MC/MCContext.h"
20f382538dSDimitry Andric #include "llvm/Pass.h"
21145449b1SDimitry Andric #include "llvm/Support/CommandLine.h"
2259850d08SRoman Divacky #include "llvm/Support/ErrorHandling.h"
23eb11fae6SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
24b915e9e0SDimitry Andric #include "llvm/Target/TargetMachine.h"
25f382538dSDimitry Andric #include <algorithm>
26f382538dSDimitry Andric #include <cassert>
27f382538dSDimitry Andric #include <memory>
28f382538dSDimitry Andric #include <utility>
29f382538dSDimitry Andric #include <vector>
30f382538dSDimitry Andric 
31009b1c42SEd Schouten using namespace llvm;
32009b1c42SEd Schouten using namespace llvm::dwarf;
33009b1c42SEd Schouten 
34145449b1SDimitry Andric static cl::opt<bool>
35145449b1SDimitry Andric     DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
36145449b1SDimitry Andric                              cl::desc("Disable debug info printing"));
37145449b1SDimitry Andric 
3859850d08SRoman Divacky // Out of line virtual method.
39f382538dSDimitry Andric MachineModuleInfoImpl::~MachineModuleInfoImpl() = default;
4059850d08SRoman Divacky 
initialize()411d5ae102SDimitry Andric void MachineModuleInfo::initialize() {
425ca98fd9SDimitry Andric   ObjFileMMI = nullptr;
434a16efa3SDimitry Andric   CurCallSite = 0;
44344a3780SDimitry Andric   NextFnNum = 0;
45145449b1SDimitry Andric   UsesMSVCFloatingPoint = false;
46145449b1SDimitry Andric   DbgInfoAvailable = false;
47009b1c42SEd Schouten }
48009b1c42SEd Schouten 
finalize()491d5ae102SDimitry Andric void MachineModuleInfo::finalize() {
504a16efa3SDimitry Andric   Context.reset();
51b60736ecSDimitry Andric   // We don't clear the ExternalContext.
524a16efa3SDimitry Andric 
534a16efa3SDimitry Andric   delete ObjFileMMI;
545ca98fd9SDimitry Andric   ObjFileMMI = nullptr;
55009b1c42SEd Schouten }
56009b1c42SEd Schouten 
MachineModuleInfo(MachineModuleInfo && MMI)571d5ae102SDimitry Andric MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
581d5ae102SDimitry Andric     : TM(std::move(MMI.TM)),
597fa27ce4SDimitry Andric       Context(TM.getTargetTriple(), TM.getMCAsmInfo(), TM.getMCRegisterInfo(),
607fa27ce4SDimitry Andric               TM.getMCSubtargetInfo(), nullptr, &TM.Options.MCOptions, false),
61b60736ecSDimitry Andric       MachineFunctions(std::move(MMI.MachineFunctions)) {
627fa27ce4SDimitry Andric   Context.setObjectFileInfo(TM.getObjFileLowering());
631d5ae102SDimitry Andric   ObjFileMMI = MMI.ObjFileMMI;
641d5ae102SDimitry Andric   CurCallSite = MMI.CurCallSite;
65b60736ecSDimitry Andric   ExternalContext = MMI.ExternalContext;
661d5ae102SDimitry Andric   TheModule = MMI.TheModule;
671d5ae102SDimitry Andric }
681d5ae102SDimitry Andric 
MachineModuleInfo(const LLVMTargetMachine * TM)691d5ae102SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM)
70344a3780SDimitry Andric     : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
71344a3780SDimitry Andric                        TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
72145449b1SDimitry Andric                        nullptr, &TM->Options.MCOptions, false) {
73344a3780SDimitry Andric   Context.setObjectFileInfo(TM->getObjFileLowering());
741d5ae102SDimitry Andric   initialize();
751d5ae102SDimitry Andric }
761d5ae102SDimitry Andric 
MachineModuleInfo(const LLVMTargetMachine * TM,MCContext * ExtContext)77b60736ecSDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM,
78b60736ecSDimitry Andric                                      MCContext *ExtContext)
79344a3780SDimitry Andric     : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
80344a3780SDimitry Andric                        TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
81145449b1SDimitry Andric                        nullptr, &TM->Options.MCOptions, false),
82b60736ecSDimitry Andric       ExternalContext(ExtContext) {
83344a3780SDimitry Andric   Context.setObjectFileInfo(TM->getObjFileLowering());
84b60736ecSDimitry Andric   initialize();
85b60736ecSDimitry Andric }
86b60736ecSDimitry Andric 
~MachineModuleInfo()871d5ae102SDimitry Andric MachineModuleInfo::~MachineModuleInfo() { finalize(); }
881d5ae102SDimitry Andric 
897ab83427SDimitry Andric MachineFunction *
getMachineFunction(const Function & F) const907ab83427SDimitry Andric MachineModuleInfo::getMachineFunction(const Function &F) const {
917ab83427SDimitry Andric   auto I = MachineFunctions.find(&F);
927ab83427SDimitry Andric   return I != MachineFunctions.end() ? I->second.get() : nullptr;
937ab83427SDimitry Andric }
947ab83427SDimitry Andric 
getOrCreateMachineFunction(Function & F)95cfca06d7SDimitry Andric MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) {
96b915e9e0SDimitry Andric   // Shortcut for the common case where a sequence of MachineFunctionPasses
97b915e9e0SDimitry Andric   // all query for the same Function.
98b915e9e0SDimitry Andric   if (LastRequest == &F)
99b915e9e0SDimitry Andric     return *LastResult;
100b915e9e0SDimitry Andric 
101b915e9e0SDimitry Andric   auto I = MachineFunctions.insert(
102b915e9e0SDimitry Andric       std::make_pair(&F, std::unique_ptr<MachineFunction>()));
103b915e9e0SDimitry Andric   MachineFunction *MF;
104b915e9e0SDimitry Andric   if (I.second) {
105b915e9e0SDimitry Andric     // No pre-existing machine function, create a new one.
106044eb2f6SDimitry Andric     const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F);
107044eb2f6SDimitry Andric     MF = new MachineFunction(F, TM, STI, NextFnNum++, *this);
108e3b55780SDimitry Andric     MF->initTargetMachineFunctionInfo(STI);
1097fa27ce4SDimitry Andric 
1107fa27ce4SDimitry Andric     // MRI callback for target specific initializations.
1117fa27ce4SDimitry Andric     TM.registerMachineRegisterInfoCallback(*MF);
1127fa27ce4SDimitry Andric 
113b915e9e0SDimitry Andric     // Update the set entry.
114b915e9e0SDimitry Andric     I.first->second.reset(MF);
115b915e9e0SDimitry Andric   } else {
116b915e9e0SDimitry Andric     MF = I.first->second.get();
117009b1c42SEd Schouten   }
118009b1c42SEd Schouten 
119b915e9e0SDimitry Andric   LastRequest = &F;
120b915e9e0SDimitry Andric   LastResult = MF;
121b915e9e0SDimitry Andric   return *MF;
122009b1c42SEd Schouten }
123009b1c42SEd Schouten 
deleteMachineFunctionFor(Function & F)124b915e9e0SDimitry Andric void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
125b915e9e0SDimitry Andric   MachineFunctions.erase(&F);
126b915e9e0SDimitry Andric   LastRequest = nullptr;
127b915e9e0SDimitry Andric   LastResult = nullptr;
128009b1c42SEd Schouten }
129009b1c42SEd Schouten 
insertFunction(const Function & F,std::unique_ptr<MachineFunction> && MF)130145449b1SDimitry Andric void MachineModuleInfo::insertFunction(const Function &F,
131145449b1SDimitry Andric                                        std::unique_ptr<MachineFunction> &&MF) {
132145449b1SDimitry Andric   auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF)));
133145449b1SDimitry Andric   assert(I.second && "machine function already mapped");
134145449b1SDimitry Andric   (void)I;
135145449b1SDimitry Andric }
136145449b1SDimitry Andric 
137b915e9e0SDimitry Andric namespace {
138f382538dSDimitry Andric 
139b915e9e0SDimitry Andric /// This pass frees the MachineFunction object associated with a Function.
140b915e9e0SDimitry Andric class FreeMachineFunction : public FunctionPass {
141b915e9e0SDimitry Andric public:
142b915e9e0SDimitry Andric   static char ID;
143f382538dSDimitry Andric 
FreeMachineFunction()144b915e9e0SDimitry Andric   FreeMachineFunction() : FunctionPass(ID) {}
145b915e9e0SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const146b915e9e0SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
1471d5ae102SDimitry Andric     AU.addRequired<MachineModuleInfoWrapperPass>();
1481d5ae102SDimitry Andric     AU.addPreserved<MachineModuleInfoWrapperPass>();
1495a5ac124SDimitry Andric   }
1505a5ac124SDimitry Andric 
runOnFunction(Function & F)151b915e9e0SDimitry Andric   bool runOnFunction(Function &F) override {
1521d5ae102SDimitry Andric     MachineModuleInfo &MMI =
1531d5ae102SDimitry Andric         getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
154b915e9e0SDimitry Andric     MMI.deleteMachineFunctionFor(F);
155b915e9e0SDimitry Andric     return true;
1565a5ac124SDimitry Andric   }
15771d5a254SDimitry Andric 
getPassName() const15871d5a254SDimitry Andric   StringRef getPassName() const override {
15971d5a254SDimitry Andric     return "Free MachineFunction";
16071d5a254SDimitry Andric   }
161b915e9e0SDimitry Andric };
162f382538dSDimitry Andric 
163b915e9e0SDimitry Andric } // end anonymous namespace
1645a5ac124SDimitry Andric 
165f382538dSDimitry Andric char FreeMachineFunction::ID;
166f382538dSDimitry Andric 
createFreeMachineFunctionPass()167f382538dSDimitry Andric FunctionPass *llvm::createFreeMachineFunctionPass() {
168b915e9e0SDimitry Andric   return new FreeMachineFunction();
169009b1c42SEd Schouten }
1701d5ae102SDimitry Andric 
MachineModuleInfoWrapperPass(const LLVMTargetMachine * TM)1711d5ae102SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
1721d5ae102SDimitry Andric     const LLVMTargetMachine *TM)
1731d5ae102SDimitry Andric     : ImmutablePass(ID), MMI(TM) {
1741d5ae102SDimitry Andric   initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
1751d5ae102SDimitry Andric }
1761d5ae102SDimitry Andric 
MachineModuleInfoWrapperPass(const LLVMTargetMachine * TM,MCContext * ExtContext)177b60736ecSDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
178b60736ecSDimitry Andric     const LLVMTargetMachine *TM, MCContext *ExtContext)
179b60736ecSDimitry Andric     : ImmutablePass(ID), MMI(TM, ExtContext) {
180b60736ecSDimitry Andric   initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
181b60736ecSDimitry Andric }
182b60736ecSDimitry Andric 
1831d5ae102SDimitry Andric // Handle the Pass registration stuff necessary to use DataLayout's.
1841d5ae102SDimitry Andric INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo",
1851d5ae102SDimitry Andric                 "Machine Module Information", false, false)
1861d5ae102SDimitry Andric char MachineModuleInfoWrapperPass::ID = 0;
1871d5ae102SDimitry Andric 
getLocCookie(const SMDiagnostic & SMD,const SourceMgr & SrcMgr,std::vector<const MDNode * > & LocInfos)188ac9a064cSDimitry Andric static uint64_t getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr,
189344a3780SDimitry Andric                              std::vector<const MDNode *> &LocInfos) {
190344a3780SDimitry Andric   // Look up a LocInfo for the buffer this diagnostic is coming from.
191344a3780SDimitry Andric   unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc());
192344a3780SDimitry Andric   const MDNode *LocInfo = nullptr;
193344a3780SDimitry Andric   if (BufNum > 0 && BufNum <= LocInfos.size())
194344a3780SDimitry Andric     LocInfo = LocInfos[BufNum - 1];
195344a3780SDimitry Andric 
196344a3780SDimitry Andric   // If the inline asm had metadata associated with it, pull out a location
197344a3780SDimitry Andric   // cookie corresponding to which line the error occurred on.
198ac9a064cSDimitry Andric   uint64_t LocCookie = 0;
199344a3780SDimitry Andric   if (LocInfo) {
200344a3780SDimitry Andric     unsigned ErrorLine = SMD.getLineNo() - 1;
201344a3780SDimitry Andric     if (ErrorLine >= LocInfo->getNumOperands())
202344a3780SDimitry Andric       ErrorLine = 0;
203344a3780SDimitry Andric 
204344a3780SDimitry Andric     if (LocInfo->getNumOperands() != 0)
205344a3780SDimitry Andric       if (const ConstantInt *CI =
206344a3780SDimitry Andric               mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
207344a3780SDimitry Andric         LocCookie = CI->getZExtValue();
208344a3780SDimitry Andric   }
209344a3780SDimitry Andric 
210344a3780SDimitry Andric   return LocCookie;
211344a3780SDimitry Andric }
212344a3780SDimitry Andric 
doInitialization(Module & M)2131d5ae102SDimitry Andric bool MachineModuleInfoWrapperPass::doInitialization(Module &M) {
2141d5ae102SDimitry Andric   MMI.initialize();
2151d5ae102SDimitry Andric   MMI.TheModule = &M;
216344a3780SDimitry Andric   LLVMContext &Ctx = M.getContext();
217344a3780SDimitry Andric   MMI.getContext().setDiagnosticHandler(
218ecbca9f5SDimitry Andric       [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
219ecbca9f5SDimitry Andric                  const SourceMgr &SrcMgr,
220344a3780SDimitry Andric                  std::vector<const MDNode *> &LocInfos) {
221ac9a064cSDimitry Andric         uint64_t LocCookie = 0;
222344a3780SDimitry Andric         if (IsInlineAsm)
223344a3780SDimitry Andric           LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
224ecbca9f5SDimitry Andric         Ctx.diagnose(
225ecbca9f5SDimitry Andric             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
226344a3780SDimitry Andric       });
227145449b1SDimitry Andric   MMI.DbgInfoAvailable = !DisableDebugInfoPrinting &&
228145449b1SDimitry Andric                          !M.debug_compile_units().empty();
2291d5ae102SDimitry Andric   return false;
2301d5ae102SDimitry Andric }
2311d5ae102SDimitry Andric 
doFinalization(Module & M)2321d5ae102SDimitry Andric bool MachineModuleInfoWrapperPass::doFinalization(Module &M) {
2331d5ae102SDimitry Andric   MMI.finalize();
2341d5ae102SDimitry Andric   return false;
2351d5ae102SDimitry Andric }
2361d5ae102SDimitry Andric 
2371d5ae102SDimitry Andric AnalysisKey MachineModuleAnalysis::Key;
2381d5ae102SDimitry Andric 
239ac9a064cSDimitry Andric MachineModuleAnalysis::Result
run(Module & M,ModuleAnalysisManager &)240ac9a064cSDimitry Andric MachineModuleAnalysis::run(Module &M, ModuleAnalysisManager &) {
2411d5ae102SDimitry Andric   MMI.TheModule = &M;
242ac9a064cSDimitry Andric   LLVMContext &Ctx = M.getContext();
243ac9a064cSDimitry Andric   MMI.getContext().setDiagnosticHandler(
244ac9a064cSDimitry Andric       [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
245ac9a064cSDimitry Andric                  const SourceMgr &SrcMgr,
246ac9a064cSDimitry Andric                  std::vector<const MDNode *> &LocInfos) {
247ac9a064cSDimitry Andric         unsigned LocCookie = 0;
248ac9a064cSDimitry Andric         if (IsInlineAsm)
249ac9a064cSDimitry Andric           LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
250ac9a064cSDimitry Andric         Ctx.diagnose(
251ac9a064cSDimitry Andric             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
252ac9a064cSDimitry Andric       });
253ac9a064cSDimitry Andric   MMI.DbgInfoAvailable =
254ac9a064cSDimitry Andric       !DisableDebugInfoPrinting && !M.debug_compile_units().empty();
255ac9a064cSDimitry Andric   return Result(MMI);
2561d5ae102SDimitry Andric }
257