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
initialize()27 void MachineModuleInfo::initialize() {
28 ObjFileMMI = nullptr;
29 NextFnNum = 0;
30 }
31
finalize()32 void MachineModuleInfo::finalize() {
33 Context.reset();
34 // We don't clear the ExternalContext.
35
36 delete ObjFileMMI;
37 ObjFileMMI = nullptr;
38 }
39
MachineModuleInfo(MachineModuleInfo && MMI)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
MachineModuleInfo(const TargetMachine * TM)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
MachineModuleInfo(const TargetMachine * TM,MCContext * ExtContext)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
~MachineModuleInfo()69 MachineModuleInfo::~MachineModuleInfo() { finalize(); }
70
71 MachineFunction *
getMachineFunction(const Function & F) const72 MachineModuleInfo::getMachineFunction(const Function &F) const {
73 auto I = MachineFunctions.find(&F);
74 return I != MachineFunctions.end() ? I->second.get() : nullptr;
75 }
76
getOrCreateMachineFunction(Function & F)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
deleteMachineFunctionFor(Function & F)106 void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
107 MachineFunctions.erase(&F);
108 LastRequest = nullptr;
109 LastResult = nullptr;
110 }
111
insertFunction(const Function & F,std::unique_ptr<MachineFunction> && MF)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
FreeMachineFunction()126 FreeMachineFunction() : FunctionPass(ID) {}
127
getAnalysisUsage(AnalysisUsage & AU) const128 void getAnalysisUsage(AnalysisUsage &AU) const override {
129 AU.addRequired<MachineModuleInfoWrapperPass>();
130 AU.addPreserved<MachineModuleInfoWrapperPass>();
131 }
132
runOnFunction(Function & F)133 bool runOnFunction(Function &F) override {
134 MachineModuleInfo &MMI =
135 getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
136 MMI.deleteMachineFunctionFor(F);
137 return true;
138 }
139
getPassName() const140 StringRef getPassName() const override {
141 return "Free MachineFunction";
142 }
143 };
144
145 } // end anonymous namespace
146
147 char FreeMachineFunction::ID;
148
createFreeMachineFunctionPass()149 FunctionPass *llvm::createFreeMachineFunctionPass() {
150 return new FreeMachineFunction();
151 }
152
MachineModuleInfoWrapperPass(const TargetMachine * TM)153 MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
154 const TargetMachine *TM)
155 : ImmutablePass(ID), MMI(TM) {
156 initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
157 }
158
MachineModuleInfoWrapperPass(const TargetMachine * TM,MCContext * ExtContext)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
getLocCookie(const SMDiagnostic & SMD,const SourceMgr & SrcMgr,std::vector<const MDNode * > & LocInfos)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
doInitialization(Module & M)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
doFinalization(Module & M)212 bool MachineModuleInfoWrapperPass::doFinalization(Module &M) {
213 MMI.finalize();
214 return false;
215 }
216
217 AnalysisKey MachineModuleAnalysis::Key;
218
219 MachineModuleAnalysis::Result
run(Module & M,ModuleAnalysisManager &)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