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