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(Val: &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 | KV: std::make_pair(x: &F, y: 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&: *MF); |
94 | |
95 | // Update the set entry. |
96 | I.first->second.reset(p: 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(Val: &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(KV: std::make_pair(x: &F, y: 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(Loc: 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>(MD: LocInfo->getOperand(I: 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 | DI: 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 | DI: DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie)); |
232 | }); |
233 | return Result(MMI); |
234 | } |
235 | |