1*0b57cec5SDimitry Andric //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
10*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
11*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
12*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
13*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
1481ad6265SDimitry Andric #include "llvm/IR/Constants.h"
15fe6060f1SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
16fe6060f1SDimitry Andric #include "llvm/IR/LLVMContext.h"
17*0b57cec5SDimitry Andric #include "llvm/IR/Module.h"
18480093f4SDimitry Andric #include "llvm/InitializePasses.h"
19*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
20*0b57cec5SDimitry Andric #include "llvm/Pass.h"
2181ad6265SDimitry Andric #include "llvm/Support/CommandLine.h"
22*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
23*0b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
24*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
25*0b57cec5SDimitry Andric #include <algorithm>
26*0b57cec5SDimitry Andric #include <cassert>
27*0b57cec5SDimitry Andric #include <memory>
28*0b57cec5SDimitry Andric #include <utility>
29*0b57cec5SDimitry Andric #include <vector>
30*0b57cec5SDimitry Andric 
31*0b57cec5SDimitry Andric using namespace llvm;
32*0b57cec5SDimitry Andric using namespace llvm::dwarf;
33*0b57cec5SDimitry Andric 
3481ad6265SDimitry Andric static cl::opt<bool>
3581ad6265SDimitry Andric     DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
3681ad6265SDimitry Andric                              cl::desc("Disable debug info printing"));
3781ad6265SDimitry Andric 
38*0b57cec5SDimitry Andric // Out of line virtual method.
39*0b57cec5SDimitry Andric MachineModuleInfoImpl::~MachineModuleInfoImpl() = default;
40*0b57cec5SDimitry Andric 
418bcb0991SDimitry Andric void MachineModuleInfo::initialize() {
42*0b57cec5SDimitry Andric   ObjFileMMI = nullptr;
43*0b57cec5SDimitry Andric   CurCallSite = 0;
44fe6060f1SDimitry Andric   NextFnNum = 0;
4581ad6265SDimitry Andric   UsesMSVCFloatingPoint = false;
4681ad6265SDimitry Andric   DbgInfoAvailable = false;
47*0b57cec5SDimitry Andric }
48*0b57cec5SDimitry Andric 
498bcb0991SDimitry Andric void MachineModuleInfo::finalize() {
50*0b57cec5SDimitry Andric   Context.reset();
51e8d8bef9SDimitry Andric   // We don't clear the ExternalContext.
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric   delete ObjFileMMI;
54*0b57cec5SDimitry Andric   ObjFileMMI = nullptr;
55*0b57cec5SDimitry Andric }
56*0b57cec5SDimitry Andric 
578bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
588bcb0991SDimitry Andric     : TM(std::move(MMI.TM)),
59fe6060f1SDimitry Andric       Context(MMI.TM.getTargetTriple(), MMI.TM.getMCAsmInfo(),
60fe6060f1SDimitry Andric               MMI.TM.getMCRegisterInfo(), MMI.TM.getMCSubtargetInfo(), nullptr,
6181ad6265SDimitry Andric               &MMI.TM.Options.MCOptions, false),
62e8d8bef9SDimitry Andric       MachineFunctions(std::move(MMI.MachineFunctions)) {
63fe6060f1SDimitry Andric   Context.setObjectFileInfo(MMI.TM.getObjFileLowering());
648bcb0991SDimitry Andric   ObjFileMMI = MMI.ObjFileMMI;
658bcb0991SDimitry Andric   CurCallSite = MMI.CurCallSite;
66e8d8bef9SDimitry Andric   ExternalContext = MMI.ExternalContext;
678bcb0991SDimitry Andric   TheModule = MMI.TheModule;
688bcb0991SDimitry Andric }
698bcb0991SDimitry Andric 
708bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM)
71fe6060f1SDimitry Andric     : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
72fe6060f1SDimitry Andric                        TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
7381ad6265SDimitry Andric                        nullptr, &TM->Options.MCOptions, false) {
74fe6060f1SDimitry Andric   Context.setObjectFileInfo(TM->getObjFileLowering());
758bcb0991SDimitry Andric   initialize();
768bcb0991SDimitry Andric }
778bcb0991SDimitry Andric 
78e8d8bef9SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM,
79e8d8bef9SDimitry Andric                                      MCContext *ExtContext)
80fe6060f1SDimitry Andric     : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
81fe6060f1SDimitry Andric                        TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
8281ad6265SDimitry Andric                        nullptr, &TM->Options.MCOptions, false),
83e8d8bef9SDimitry Andric       ExternalContext(ExtContext) {
84fe6060f1SDimitry Andric   Context.setObjectFileInfo(TM->getObjFileLowering());
85e8d8bef9SDimitry Andric   initialize();
86e8d8bef9SDimitry Andric }
87e8d8bef9SDimitry Andric 
888bcb0991SDimitry Andric MachineModuleInfo::~MachineModuleInfo() { finalize(); }
898bcb0991SDimitry Andric 
90*0b57cec5SDimitry Andric MachineFunction *
91*0b57cec5SDimitry Andric MachineModuleInfo::getMachineFunction(const Function &F) const {
92*0b57cec5SDimitry Andric   auto I = MachineFunctions.find(&F);
93*0b57cec5SDimitry Andric   return I != MachineFunctions.end() ? I->second.get() : nullptr;
94*0b57cec5SDimitry Andric }
95*0b57cec5SDimitry Andric 
965ffd83dbSDimitry Andric MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) {
97*0b57cec5SDimitry Andric   // Shortcut for the common case where a sequence of MachineFunctionPasses
98*0b57cec5SDimitry Andric   // all query for the same Function.
99*0b57cec5SDimitry Andric   if (LastRequest == &F)
100*0b57cec5SDimitry Andric     return *LastResult;
101*0b57cec5SDimitry Andric 
102*0b57cec5SDimitry Andric   auto I = MachineFunctions.insert(
103*0b57cec5SDimitry Andric       std::make_pair(&F, std::unique_ptr<MachineFunction>()));
104*0b57cec5SDimitry Andric   MachineFunction *MF;
105*0b57cec5SDimitry Andric   if (I.second) {
106*0b57cec5SDimitry Andric     // No pre-existing machine function, create a new one.
107*0b57cec5SDimitry Andric     const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F);
108*0b57cec5SDimitry Andric     MF = new MachineFunction(F, TM, STI, NextFnNum++, *this);
109bdd1243dSDimitry Andric     MF->initTargetMachineFunctionInfo(STI);
110*0b57cec5SDimitry Andric     // Update the set entry.
111*0b57cec5SDimitry Andric     I.first->second.reset(MF);
112*0b57cec5SDimitry Andric   } else {
113*0b57cec5SDimitry Andric     MF = I.first->second.get();
114*0b57cec5SDimitry Andric   }
115*0b57cec5SDimitry Andric 
116*0b57cec5SDimitry Andric   LastRequest = &F;
117*0b57cec5SDimitry Andric   LastResult = MF;
118*0b57cec5SDimitry Andric   return *MF;
119*0b57cec5SDimitry Andric }
120*0b57cec5SDimitry Andric 
121*0b57cec5SDimitry Andric void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
122*0b57cec5SDimitry Andric   MachineFunctions.erase(&F);
123*0b57cec5SDimitry Andric   LastRequest = nullptr;
124*0b57cec5SDimitry Andric   LastResult = nullptr;
125*0b57cec5SDimitry Andric }
126*0b57cec5SDimitry Andric 
12781ad6265SDimitry Andric void MachineModuleInfo::insertFunction(const Function &F,
12881ad6265SDimitry Andric                                        std::unique_ptr<MachineFunction> &&MF) {
12981ad6265SDimitry Andric   auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF)));
13081ad6265SDimitry Andric   assert(I.second && "machine function already mapped");
13181ad6265SDimitry Andric   (void)I;
13281ad6265SDimitry Andric }
13381ad6265SDimitry Andric 
134*0b57cec5SDimitry Andric namespace {
135*0b57cec5SDimitry Andric 
136*0b57cec5SDimitry Andric /// This pass frees the MachineFunction object associated with a Function.
137*0b57cec5SDimitry Andric class FreeMachineFunction : public FunctionPass {
138*0b57cec5SDimitry Andric public:
139*0b57cec5SDimitry Andric   static char ID;
140*0b57cec5SDimitry Andric 
141*0b57cec5SDimitry Andric   FreeMachineFunction() : FunctionPass(ID) {}
142*0b57cec5SDimitry Andric 
143*0b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
1448bcb0991SDimitry Andric     AU.addRequired<MachineModuleInfoWrapperPass>();
1458bcb0991SDimitry Andric     AU.addPreserved<MachineModuleInfoWrapperPass>();
146*0b57cec5SDimitry Andric   }
147*0b57cec5SDimitry Andric 
148*0b57cec5SDimitry Andric   bool runOnFunction(Function &F) override {
1498bcb0991SDimitry Andric     MachineModuleInfo &MMI =
1508bcb0991SDimitry Andric         getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
151*0b57cec5SDimitry Andric     MMI.deleteMachineFunctionFor(F);
152*0b57cec5SDimitry Andric     return true;
153*0b57cec5SDimitry Andric   }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric   StringRef getPassName() const override {
156*0b57cec5SDimitry Andric     return "Free MachineFunction";
157*0b57cec5SDimitry Andric   }
158*0b57cec5SDimitry Andric };
159*0b57cec5SDimitry Andric 
160*0b57cec5SDimitry Andric } // end anonymous namespace
161*0b57cec5SDimitry Andric 
162*0b57cec5SDimitry Andric char FreeMachineFunction::ID;
163*0b57cec5SDimitry Andric 
164*0b57cec5SDimitry Andric FunctionPass *llvm::createFreeMachineFunctionPass() {
165*0b57cec5SDimitry Andric   return new FreeMachineFunction();
166*0b57cec5SDimitry Andric }
1678bcb0991SDimitry Andric 
1688bcb0991SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
1698bcb0991SDimitry Andric     const LLVMTargetMachine *TM)
1708bcb0991SDimitry Andric     : ImmutablePass(ID), MMI(TM) {
1718bcb0991SDimitry Andric   initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
1728bcb0991SDimitry Andric }
1738bcb0991SDimitry Andric 
174e8d8bef9SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
175e8d8bef9SDimitry Andric     const LLVMTargetMachine *TM, MCContext *ExtContext)
176e8d8bef9SDimitry Andric     : ImmutablePass(ID), MMI(TM, ExtContext) {
177e8d8bef9SDimitry Andric   initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
178e8d8bef9SDimitry Andric }
179e8d8bef9SDimitry Andric 
1808bcb0991SDimitry Andric // Handle the Pass registration stuff necessary to use DataLayout's.
1818bcb0991SDimitry Andric INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo",
1828bcb0991SDimitry Andric                 "Machine Module Information", false, false)
1838bcb0991SDimitry Andric char MachineModuleInfoWrapperPass::ID = 0;
1848bcb0991SDimitry Andric 
185fe6060f1SDimitry Andric static unsigned getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr,
186fe6060f1SDimitry Andric                              std::vector<const MDNode *> &LocInfos) {
187fe6060f1SDimitry Andric   // Look up a LocInfo for the buffer this diagnostic is coming from.
188fe6060f1SDimitry Andric   unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc());
189fe6060f1SDimitry Andric   const MDNode *LocInfo = nullptr;
190fe6060f1SDimitry Andric   if (BufNum > 0 && BufNum <= LocInfos.size())
191fe6060f1SDimitry Andric     LocInfo = LocInfos[BufNum - 1];
192fe6060f1SDimitry Andric 
193fe6060f1SDimitry Andric   // If the inline asm had metadata associated with it, pull out a location
194fe6060f1SDimitry Andric   // cookie corresponding to which line the error occurred on.
195fe6060f1SDimitry Andric   unsigned LocCookie = 0;
196fe6060f1SDimitry Andric   if (LocInfo) {
197fe6060f1SDimitry Andric     unsigned ErrorLine = SMD.getLineNo() - 1;
198fe6060f1SDimitry Andric     if (ErrorLine >= LocInfo->getNumOperands())
199fe6060f1SDimitry Andric       ErrorLine = 0;
200fe6060f1SDimitry Andric 
201fe6060f1SDimitry Andric     if (LocInfo->getNumOperands() != 0)
202fe6060f1SDimitry Andric       if (const ConstantInt *CI =
203fe6060f1SDimitry Andric               mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
204fe6060f1SDimitry Andric         LocCookie = CI->getZExtValue();
205fe6060f1SDimitry Andric   }
206fe6060f1SDimitry Andric 
207fe6060f1SDimitry Andric   return LocCookie;
208fe6060f1SDimitry Andric }
209fe6060f1SDimitry Andric 
2108bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doInitialization(Module &M) {
2118bcb0991SDimitry Andric   MMI.initialize();
2128bcb0991SDimitry Andric   MMI.TheModule = &M;
213fe6060f1SDimitry Andric   // FIXME: Do this for new pass manager.
214fe6060f1SDimitry Andric   LLVMContext &Ctx = M.getContext();
215fe6060f1SDimitry Andric   MMI.getContext().setDiagnosticHandler(
2161fd87a68SDimitry Andric       [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
2171fd87a68SDimitry Andric                  const SourceMgr &SrcMgr,
218fe6060f1SDimitry Andric                  std::vector<const MDNode *> &LocInfos) {
219fe6060f1SDimitry Andric         unsigned LocCookie = 0;
220fe6060f1SDimitry Andric         if (IsInlineAsm)
221fe6060f1SDimitry Andric           LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
2221fd87a68SDimitry Andric         Ctx.diagnose(
2231fd87a68SDimitry Andric             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
224fe6060f1SDimitry Andric       });
22581ad6265SDimitry Andric   MMI.DbgInfoAvailable = !DisableDebugInfoPrinting &&
22681ad6265SDimitry Andric                          !M.debug_compile_units().empty();
2278bcb0991SDimitry Andric   return false;
2288bcb0991SDimitry Andric }
2298bcb0991SDimitry Andric 
2308bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doFinalization(Module &M) {
2318bcb0991SDimitry Andric   MMI.finalize();
2328bcb0991SDimitry Andric   return false;
2338bcb0991SDimitry Andric }
2348bcb0991SDimitry Andric 
2358bcb0991SDimitry Andric AnalysisKey MachineModuleAnalysis::Key;
2368bcb0991SDimitry Andric 
2378bcb0991SDimitry Andric MachineModuleInfo MachineModuleAnalysis::run(Module &M,
2388bcb0991SDimitry Andric                                              ModuleAnalysisManager &) {
2398bcb0991SDimitry Andric   MachineModuleInfo MMI(TM);
2408bcb0991SDimitry Andric   MMI.TheModule = &M;
24181ad6265SDimitry Andric   MMI.DbgInfoAvailable = !DisableDebugInfoPrinting &&
24281ad6265SDimitry Andric                          !M.debug_compile_units().empty();
2438bcb0991SDimitry Andric   return MMI;
2448bcb0991SDimitry Andric }
245