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   Personalities.clear();
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric   Context.reset();
53e8d8bef9SDimitry Andric   // We don't clear the ExternalContext.
54*0b57cec5SDimitry Andric 
55*0b57cec5SDimitry Andric   delete ObjFileMMI;
56*0b57cec5SDimitry Andric   ObjFileMMI = nullptr;
57*0b57cec5SDimitry Andric }
58*0b57cec5SDimitry Andric 
598bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
608bcb0991SDimitry Andric     : TM(std::move(MMI.TM)),
61fe6060f1SDimitry Andric       Context(MMI.TM.getTargetTriple(), MMI.TM.getMCAsmInfo(),
62fe6060f1SDimitry Andric               MMI.TM.getMCRegisterInfo(), MMI.TM.getMCSubtargetInfo(), nullptr,
6381ad6265SDimitry Andric               &MMI.TM.Options.MCOptions, false),
64e8d8bef9SDimitry Andric       MachineFunctions(std::move(MMI.MachineFunctions)) {
65fe6060f1SDimitry Andric   Context.setObjectFileInfo(MMI.TM.getObjFileLowering());
668bcb0991SDimitry Andric   ObjFileMMI = MMI.ObjFileMMI;
678bcb0991SDimitry Andric   CurCallSite = MMI.CurCallSite;
68e8d8bef9SDimitry Andric   ExternalContext = MMI.ExternalContext;
698bcb0991SDimitry Andric   TheModule = MMI.TheModule;
708bcb0991SDimitry Andric }
718bcb0991SDimitry Andric 
728bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM)
73fe6060f1SDimitry Andric     : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
74fe6060f1SDimitry Andric                        TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
7581ad6265SDimitry Andric                        nullptr, &TM->Options.MCOptions, false) {
76fe6060f1SDimitry Andric   Context.setObjectFileInfo(TM->getObjFileLowering());
778bcb0991SDimitry Andric   initialize();
788bcb0991SDimitry Andric }
798bcb0991SDimitry Andric 
80e8d8bef9SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM,
81e8d8bef9SDimitry Andric                                      MCContext *ExtContext)
82fe6060f1SDimitry Andric     : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
83fe6060f1SDimitry Andric                        TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
8481ad6265SDimitry Andric                        nullptr, &TM->Options.MCOptions, false),
85e8d8bef9SDimitry Andric       ExternalContext(ExtContext) {
86fe6060f1SDimitry Andric   Context.setObjectFileInfo(TM->getObjFileLowering());
87e8d8bef9SDimitry Andric   initialize();
88e8d8bef9SDimitry Andric }
89e8d8bef9SDimitry Andric 
908bcb0991SDimitry Andric MachineModuleInfo::~MachineModuleInfo() { finalize(); }
918bcb0991SDimitry Andric 
92*0b57cec5SDimitry Andric /// \name Exception Handling
93*0b57cec5SDimitry Andric /// \{
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric void MachineModuleInfo::addPersonality(const Function *Personality) {
96fe6060f1SDimitry Andric   if (!llvm::is_contained(Personalities, Personality))
97*0b57cec5SDimitry Andric     Personalities.push_back(Personality);
98*0b57cec5SDimitry Andric }
99*0b57cec5SDimitry Andric 
100*0b57cec5SDimitry Andric /// \}
101*0b57cec5SDimitry Andric 
102*0b57cec5SDimitry Andric MachineFunction *
103*0b57cec5SDimitry Andric MachineModuleInfo::getMachineFunction(const Function &F) const {
104*0b57cec5SDimitry Andric   auto I = MachineFunctions.find(&F);
105*0b57cec5SDimitry Andric   return I != MachineFunctions.end() ? I->second.get() : nullptr;
106*0b57cec5SDimitry Andric }
107*0b57cec5SDimitry Andric 
1085ffd83dbSDimitry Andric MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) {
109*0b57cec5SDimitry Andric   // Shortcut for the common case where a sequence of MachineFunctionPasses
110*0b57cec5SDimitry Andric   // all query for the same Function.
111*0b57cec5SDimitry Andric   if (LastRequest == &F)
112*0b57cec5SDimitry Andric     return *LastResult;
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric   auto I = MachineFunctions.insert(
115*0b57cec5SDimitry Andric       std::make_pair(&F, std::unique_ptr<MachineFunction>()));
116*0b57cec5SDimitry Andric   MachineFunction *MF;
117*0b57cec5SDimitry Andric   if (I.second) {
118*0b57cec5SDimitry Andric     // No pre-existing machine function, create a new one.
119*0b57cec5SDimitry Andric     const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F);
120*0b57cec5SDimitry Andric     MF = new MachineFunction(F, TM, STI, NextFnNum++, *this);
121*0b57cec5SDimitry Andric     // Update the set entry.
122*0b57cec5SDimitry Andric     I.first->second.reset(MF);
123*0b57cec5SDimitry Andric   } else {
124*0b57cec5SDimitry Andric     MF = I.first->second.get();
125*0b57cec5SDimitry Andric   }
126*0b57cec5SDimitry Andric 
127*0b57cec5SDimitry Andric   LastRequest = &F;
128*0b57cec5SDimitry Andric   LastResult = MF;
129*0b57cec5SDimitry Andric   return *MF;
130*0b57cec5SDimitry Andric }
131*0b57cec5SDimitry Andric 
132*0b57cec5SDimitry Andric void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
133*0b57cec5SDimitry Andric   MachineFunctions.erase(&F);
134*0b57cec5SDimitry Andric   LastRequest = nullptr;
135*0b57cec5SDimitry Andric   LastResult = nullptr;
136*0b57cec5SDimitry Andric }
137*0b57cec5SDimitry Andric 
13881ad6265SDimitry Andric void MachineModuleInfo::insertFunction(const Function &F,
13981ad6265SDimitry Andric                                        std::unique_ptr<MachineFunction> &&MF) {
14081ad6265SDimitry Andric   auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF)));
14181ad6265SDimitry Andric   assert(I.second && "machine function already mapped");
14281ad6265SDimitry Andric   (void)I;
14381ad6265SDimitry Andric }
14481ad6265SDimitry Andric 
145*0b57cec5SDimitry Andric namespace {
146*0b57cec5SDimitry Andric 
147*0b57cec5SDimitry Andric /// This pass frees the MachineFunction object associated with a Function.
148*0b57cec5SDimitry Andric class FreeMachineFunction : public FunctionPass {
149*0b57cec5SDimitry Andric public:
150*0b57cec5SDimitry Andric   static char ID;
151*0b57cec5SDimitry Andric 
152*0b57cec5SDimitry Andric   FreeMachineFunction() : FunctionPass(ID) {}
153*0b57cec5SDimitry Andric 
154*0b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
1558bcb0991SDimitry Andric     AU.addRequired<MachineModuleInfoWrapperPass>();
1568bcb0991SDimitry Andric     AU.addPreserved<MachineModuleInfoWrapperPass>();
157*0b57cec5SDimitry Andric   }
158*0b57cec5SDimitry Andric 
159*0b57cec5SDimitry Andric   bool runOnFunction(Function &F) override {
1608bcb0991SDimitry Andric     MachineModuleInfo &MMI =
1618bcb0991SDimitry Andric         getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
162*0b57cec5SDimitry Andric     MMI.deleteMachineFunctionFor(F);
163*0b57cec5SDimitry Andric     return true;
164*0b57cec5SDimitry Andric   }
165*0b57cec5SDimitry Andric 
166*0b57cec5SDimitry Andric   StringRef getPassName() const override {
167*0b57cec5SDimitry Andric     return "Free MachineFunction";
168*0b57cec5SDimitry Andric   }
169*0b57cec5SDimitry Andric };
170*0b57cec5SDimitry Andric 
171*0b57cec5SDimitry Andric } // end anonymous namespace
172*0b57cec5SDimitry Andric 
173*0b57cec5SDimitry Andric char FreeMachineFunction::ID;
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric FunctionPass *llvm::createFreeMachineFunctionPass() {
176*0b57cec5SDimitry Andric   return new FreeMachineFunction();
177*0b57cec5SDimitry Andric }
1788bcb0991SDimitry Andric 
1798bcb0991SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
1808bcb0991SDimitry Andric     const LLVMTargetMachine *TM)
1818bcb0991SDimitry Andric     : ImmutablePass(ID), MMI(TM) {
1828bcb0991SDimitry Andric   initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
1838bcb0991SDimitry Andric }
1848bcb0991SDimitry Andric 
185e8d8bef9SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
186e8d8bef9SDimitry Andric     const LLVMTargetMachine *TM, MCContext *ExtContext)
187e8d8bef9SDimitry Andric     : ImmutablePass(ID), MMI(TM, ExtContext) {
188e8d8bef9SDimitry Andric   initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
189e8d8bef9SDimitry Andric }
190e8d8bef9SDimitry Andric 
1918bcb0991SDimitry Andric // Handle the Pass registration stuff necessary to use DataLayout's.
1928bcb0991SDimitry Andric INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo",
1938bcb0991SDimitry Andric                 "Machine Module Information", false, false)
1948bcb0991SDimitry Andric char MachineModuleInfoWrapperPass::ID = 0;
1958bcb0991SDimitry Andric 
196fe6060f1SDimitry Andric static unsigned getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr,
197fe6060f1SDimitry Andric                              std::vector<const MDNode *> &LocInfos) {
198fe6060f1SDimitry Andric   // Look up a LocInfo for the buffer this diagnostic is coming from.
199fe6060f1SDimitry Andric   unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc());
200fe6060f1SDimitry Andric   const MDNode *LocInfo = nullptr;
201fe6060f1SDimitry Andric   if (BufNum > 0 && BufNum <= LocInfos.size())
202fe6060f1SDimitry Andric     LocInfo = LocInfos[BufNum - 1];
203fe6060f1SDimitry Andric 
204fe6060f1SDimitry Andric   // If the inline asm had metadata associated with it, pull out a location
205fe6060f1SDimitry Andric   // cookie corresponding to which line the error occurred on.
206fe6060f1SDimitry Andric   unsigned LocCookie = 0;
207fe6060f1SDimitry Andric   if (LocInfo) {
208fe6060f1SDimitry Andric     unsigned ErrorLine = SMD.getLineNo() - 1;
209fe6060f1SDimitry Andric     if (ErrorLine >= LocInfo->getNumOperands())
210fe6060f1SDimitry Andric       ErrorLine = 0;
211fe6060f1SDimitry Andric 
212fe6060f1SDimitry Andric     if (LocInfo->getNumOperands() != 0)
213fe6060f1SDimitry Andric       if (const ConstantInt *CI =
214fe6060f1SDimitry Andric               mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
215fe6060f1SDimitry Andric         LocCookie = CI->getZExtValue();
216fe6060f1SDimitry Andric   }
217fe6060f1SDimitry Andric 
218fe6060f1SDimitry Andric   return LocCookie;
219fe6060f1SDimitry Andric }
220fe6060f1SDimitry Andric 
2218bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doInitialization(Module &M) {
2228bcb0991SDimitry Andric   MMI.initialize();
2238bcb0991SDimitry Andric   MMI.TheModule = &M;
224fe6060f1SDimitry Andric   // FIXME: Do this for new pass manager.
225fe6060f1SDimitry Andric   LLVMContext &Ctx = M.getContext();
226fe6060f1SDimitry Andric   MMI.getContext().setDiagnosticHandler(
2271fd87a68SDimitry Andric       [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
2281fd87a68SDimitry Andric                  const SourceMgr &SrcMgr,
229fe6060f1SDimitry Andric                  std::vector<const MDNode *> &LocInfos) {
230fe6060f1SDimitry Andric         unsigned LocCookie = 0;
231fe6060f1SDimitry Andric         if (IsInlineAsm)
232fe6060f1SDimitry Andric           LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
2331fd87a68SDimitry Andric         Ctx.diagnose(
2341fd87a68SDimitry Andric             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
235fe6060f1SDimitry Andric       });
23681ad6265SDimitry Andric   MMI.DbgInfoAvailable = !DisableDebugInfoPrinting &&
23781ad6265SDimitry Andric                          !M.debug_compile_units().empty();
2388bcb0991SDimitry Andric   return false;
2398bcb0991SDimitry Andric }
2408bcb0991SDimitry Andric 
2418bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doFinalization(Module &M) {
2428bcb0991SDimitry Andric   MMI.finalize();
2438bcb0991SDimitry Andric   return false;
2448bcb0991SDimitry Andric }
2458bcb0991SDimitry Andric 
2468bcb0991SDimitry Andric AnalysisKey MachineModuleAnalysis::Key;
2478bcb0991SDimitry Andric 
2488bcb0991SDimitry Andric MachineModuleInfo MachineModuleAnalysis::run(Module &M,
2498bcb0991SDimitry Andric                                              ModuleAnalysisManager &) {
2508bcb0991SDimitry Andric   MachineModuleInfo MMI(TM);
2518bcb0991SDimitry Andric   MMI.TheModule = &M;
25281ad6265SDimitry Andric   MMI.DbgInfoAvailable = !DisableDebugInfoPrinting &&
25381ad6265SDimitry Andric                          !M.debug_compile_units().empty();
2548bcb0991SDimitry Andric   return MMI;
2558bcb0991SDimitry Andric }
256