xref: /llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
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(&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       std::make_pair(&F, 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);
94 
95     // Update the set entry.
96     I.first->second.reset(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(&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(std::make_pair(&F, 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(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>(LocInfo->getOperand(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             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             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
232       });
233   return Result(MMI);
234 }
235