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