xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/MachineModuleInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
100b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
110b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
120b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
130b57cec5SDimitry 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"
170b57cec5SDimitry Andric #include "llvm/IR/Module.h"
18480093f4SDimitry Andric #include "llvm/InitializePasses.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
200b57cec5SDimitry Andric #include "llvm/Pass.h"
2181ad6265SDimitry Andric #include "llvm/Support/CommandLine.h"
220b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
230b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
240b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
250b57cec5SDimitry Andric #include <algorithm>
260b57cec5SDimitry Andric #include <cassert>
270b57cec5SDimitry Andric #include <memory>
280b57cec5SDimitry Andric #include <utility>
290b57cec5SDimitry Andric #include <vector>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric using namespace llvm::dwarf;
330b57cec5SDimitry 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 
380b57cec5SDimitry Andric // Out of line virtual method.
390b57cec5SDimitry Andric MachineModuleInfoImpl::~MachineModuleInfoImpl() = default;
400b57cec5SDimitry Andric 
418bcb0991SDimitry Andric void MachineModuleInfo::initialize() {
420b57cec5SDimitry Andric   ObjFileMMI = nullptr;
430b57cec5SDimitry Andric   CurCallSite = 0;
44fe6060f1SDimitry Andric   NextFnNum = 0;
4581ad6265SDimitry Andric   UsesMSVCFloatingPoint = false;
4681ad6265SDimitry Andric   DbgInfoAvailable = false;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
498bcb0991SDimitry Andric void MachineModuleInfo::finalize() {
500b57cec5SDimitry Andric   Context.reset();
51e8d8bef9SDimitry Andric   // We don't clear the ExternalContext.
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   delete ObjFileMMI;
540b57cec5SDimitry Andric   ObjFileMMI = nullptr;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
578bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
588bcb0991SDimitry Andric     : TM(std::move(MMI.TM)),
5906c3fb27SDimitry Andric       Context(TM.getTargetTriple(), TM.getMCAsmInfo(), TM.getMCRegisterInfo(),
6006c3fb27SDimitry Andric               TM.getMCSubtargetInfo(), nullptr, &TM.Options.MCOptions, false),
61e8d8bef9SDimitry Andric       MachineFunctions(std::move(MMI.MachineFunctions)) {
6206c3fb27SDimitry Andric   Context.setObjectFileInfo(TM.getObjFileLowering());
638bcb0991SDimitry Andric   ObjFileMMI = MMI.ObjFileMMI;
648bcb0991SDimitry Andric   CurCallSite = MMI.CurCallSite;
65e8d8bef9SDimitry Andric   ExternalContext = MMI.ExternalContext;
668bcb0991SDimitry Andric   TheModule = MMI.TheModule;
678bcb0991SDimitry Andric }
688bcb0991SDimitry Andric 
698bcb0991SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM)
70fe6060f1SDimitry Andric     : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
71fe6060f1SDimitry Andric                        TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
7281ad6265SDimitry Andric                        nullptr, &TM->Options.MCOptions, false) {
73fe6060f1SDimitry Andric   Context.setObjectFileInfo(TM->getObjFileLowering());
748bcb0991SDimitry Andric   initialize();
758bcb0991SDimitry Andric }
768bcb0991SDimitry Andric 
77e8d8bef9SDimitry Andric MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM,
78e8d8bef9SDimitry Andric                                      MCContext *ExtContext)
79fe6060f1SDimitry Andric     : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
80fe6060f1SDimitry Andric                        TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
8181ad6265SDimitry Andric                        nullptr, &TM->Options.MCOptions, false),
82e8d8bef9SDimitry Andric       ExternalContext(ExtContext) {
83fe6060f1SDimitry Andric   Context.setObjectFileInfo(TM->getObjFileLowering());
84e8d8bef9SDimitry Andric   initialize();
85e8d8bef9SDimitry Andric }
86e8d8bef9SDimitry Andric 
878bcb0991SDimitry Andric MachineModuleInfo::~MachineModuleInfo() { finalize(); }
888bcb0991SDimitry Andric 
890b57cec5SDimitry Andric MachineFunction *
900b57cec5SDimitry Andric MachineModuleInfo::getMachineFunction(const Function &F) const {
910b57cec5SDimitry Andric   auto I = MachineFunctions.find(&F);
920b57cec5SDimitry Andric   return I != MachineFunctions.end() ? I->second.get() : nullptr;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
955ffd83dbSDimitry Andric MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) {
960b57cec5SDimitry Andric   // Shortcut for the common case where a sequence of MachineFunctionPasses
970b57cec5SDimitry Andric   // all query for the same Function.
980b57cec5SDimitry Andric   if (LastRequest == &F)
990b57cec5SDimitry Andric     return *LastResult;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   auto I = MachineFunctions.insert(
1020b57cec5SDimitry Andric       std::make_pair(&F, std::unique_ptr<MachineFunction>()));
1030b57cec5SDimitry Andric   MachineFunction *MF;
1040b57cec5SDimitry Andric   if (I.second) {
1050b57cec5SDimitry Andric     // No pre-existing machine function, create a new one.
1060b57cec5SDimitry Andric     const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F);
1070b57cec5SDimitry Andric     MF = new MachineFunction(F, TM, STI, NextFnNum++, *this);
108bdd1243dSDimitry Andric     MF->initTargetMachineFunctionInfo(STI);
10906c3fb27SDimitry Andric 
11006c3fb27SDimitry Andric     // MRI callback for target specific initializations.
11106c3fb27SDimitry Andric     TM.registerMachineRegisterInfoCallback(*MF);
11206c3fb27SDimitry Andric 
1130b57cec5SDimitry Andric     // Update the set entry.
1140b57cec5SDimitry Andric     I.first->second.reset(MF);
1150b57cec5SDimitry Andric   } else {
1160b57cec5SDimitry Andric     MF = I.first->second.get();
1170b57cec5SDimitry Andric   }
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   LastRequest = &F;
1200b57cec5SDimitry Andric   LastResult = MF;
1210b57cec5SDimitry Andric   return *MF;
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
1250b57cec5SDimitry Andric   MachineFunctions.erase(&F);
1260b57cec5SDimitry Andric   LastRequest = nullptr;
1270b57cec5SDimitry Andric   LastResult = nullptr;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
13081ad6265SDimitry Andric void MachineModuleInfo::insertFunction(const Function &F,
13181ad6265SDimitry Andric                                        std::unique_ptr<MachineFunction> &&MF) {
13281ad6265SDimitry Andric   auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF)));
13381ad6265SDimitry Andric   assert(I.second && "machine function already mapped");
13481ad6265SDimitry Andric   (void)I;
13581ad6265SDimitry Andric }
13681ad6265SDimitry Andric 
1370b57cec5SDimitry Andric namespace {
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric /// This pass frees the MachineFunction object associated with a Function.
1400b57cec5SDimitry Andric class FreeMachineFunction : public FunctionPass {
1410b57cec5SDimitry Andric public:
1420b57cec5SDimitry Andric   static char ID;
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   FreeMachineFunction() : FunctionPass(ID) {}
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
1478bcb0991SDimitry Andric     AU.addRequired<MachineModuleInfoWrapperPass>();
1488bcb0991SDimitry Andric     AU.addPreserved<MachineModuleInfoWrapperPass>();
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   bool runOnFunction(Function &F) override {
1528bcb0991SDimitry Andric     MachineModuleInfo &MMI =
1538bcb0991SDimitry Andric         getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1540b57cec5SDimitry Andric     MMI.deleteMachineFunctionFor(F);
1550b57cec5SDimitry Andric     return true;
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   StringRef getPassName() const override {
1590b57cec5SDimitry Andric     return "Free MachineFunction";
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric };
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric } // end anonymous namespace
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric char FreeMachineFunction::ID;
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric FunctionPass *llvm::createFreeMachineFunctionPass() {
1680b57cec5SDimitry Andric   return new FreeMachineFunction();
1690b57cec5SDimitry Andric }
1708bcb0991SDimitry Andric 
1718bcb0991SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
1728bcb0991SDimitry Andric     const LLVMTargetMachine *TM)
1738bcb0991SDimitry Andric     : ImmutablePass(ID), MMI(TM) {
1748bcb0991SDimitry Andric   initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
1758bcb0991SDimitry Andric }
1768bcb0991SDimitry Andric 
177e8d8bef9SDimitry Andric MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
178e8d8bef9SDimitry Andric     const LLVMTargetMachine *TM, MCContext *ExtContext)
179e8d8bef9SDimitry Andric     : ImmutablePass(ID), MMI(TM, ExtContext) {
180e8d8bef9SDimitry Andric   initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
181e8d8bef9SDimitry Andric }
182e8d8bef9SDimitry Andric 
1838bcb0991SDimitry Andric // Handle the Pass registration stuff necessary to use DataLayout's.
1848bcb0991SDimitry Andric INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo",
1858bcb0991SDimitry Andric                 "Machine Module Information", false, false)
1868bcb0991SDimitry Andric char MachineModuleInfoWrapperPass::ID = 0;
1878bcb0991SDimitry Andric 
188*0fca6ea1SDimitry Andric static uint64_t getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr,
189fe6060f1SDimitry Andric                              std::vector<const MDNode *> &LocInfos) {
190fe6060f1SDimitry Andric   // Look up a LocInfo for the buffer this diagnostic is coming from.
191fe6060f1SDimitry Andric   unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc());
192fe6060f1SDimitry Andric   const MDNode *LocInfo = nullptr;
193fe6060f1SDimitry Andric   if (BufNum > 0 && BufNum <= LocInfos.size())
194fe6060f1SDimitry Andric     LocInfo = LocInfos[BufNum - 1];
195fe6060f1SDimitry Andric 
196fe6060f1SDimitry Andric   // If the inline asm had metadata associated with it, pull out a location
197fe6060f1SDimitry Andric   // cookie corresponding to which line the error occurred on.
198*0fca6ea1SDimitry Andric   uint64_t LocCookie = 0;
199fe6060f1SDimitry Andric   if (LocInfo) {
200fe6060f1SDimitry Andric     unsigned ErrorLine = SMD.getLineNo() - 1;
201fe6060f1SDimitry Andric     if (ErrorLine >= LocInfo->getNumOperands())
202fe6060f1SDimitry Andric       ErrorLine = 0;
203fe6060f1SDimitry Andric 
204fe6060f1SDimitry Andric     if (LocInfo->getNumOperands() != 0)
205fe6060f1SDimitry Andric       if (const ConstantInt *CI =
206fe6060f1SDimitry Andric               mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
207fe6060f1SDimitry Andric         LocCookie = CI->getZExtValue();
208fe6060f1SDimitry Andric   }
209fe6060f1SDimitry Andric 
210fe6060f1SDimitry Andric   return LocCookie;
211fe6060f1SDimitry Andric }
212fe6060f1SDimitry Andric 
2138bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doInitialization(Module &M) {
2148bcb0991SDimitry Andric   MMI.initialize();
2158bcb0991SDimitry Andric   MMI.TheModule = &M;
216fe6060f1SDimitry Andric   LLVMContext &Ctx = M.getContext();
217fe6060f1SDimitry Andric   MMI.getContext().setDiagnosticHandler(
2181fd87a68SDimitry Andric       [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
2191fd87a68SDimitry Andric                  const SourceMgr &SrcMgr,
220fe6060f1SDimitry Andric                  std::vector<const MDNode *> &LocInfos) {
221*0fca6ea1SDimitry Andric         uint64_t LocCookie = 0;
222fe6060f1SDimitry Andric         if (IsInlineAsm)
223fe6060f1SDimitry Andric           LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
2241fd87a68SDimitry Andric         Ctx.diagnose(
2251fd87a68SDimitry Andric             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
226fe6060f1SDimitry Andric       });
22781ad6265SDimitry Andric   MMI.DbgInfoAvailable = !DisableDebugInfoPrinting &&
22881ad6265SDimitry Andric                          !M.debug_compile_units().empty();
2298bcb0991SDimitry Andric   return false;
2308bcb0991SDimitry Andric }
2318bcb0991SDimitry Andric 
2328bcb0991SDimitry Andric bool MachineModuleInfoWrapperPass::doFinalization(Module &M) {
2338bcb0991SDimitry Andric   MMI.finalize();
2348bcb0991SDimitry Andric   return false;
2358bcb0991SDimitry Andric }
2368bcb0991SDimitry Andric 
2378bcb0991SDimitry Andric AnalysisKey MachineModuleAnalysis::Key;
2388bcb0991SDimitry Andric 
239*0fca6ea1SDimitry Andric MachineModuleAnalysis::Result
240*0fca6ea1SDimitry Andric MachineModuleAnalysis::run(Module &M, ModuleAnalysisManager &) {
2418bcb0991SDimitry Andric   MMI.TheModule = &M;
242*0fca6ea1SDimitry Andric   LLVMContext &Ctx = M.getContext();
243*0fca6ea1SDimitry Andric   MMI.getContext().setDiagnosticHandler(
244*0fca6ea1SDimitry Andric       [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
245*0fca6ea1SDimitry Andric                  const SourceMgr &SrcMgr,
246*0fca6ea1SDimitry Andric                  std::vector<const MDNode *> &LocInfos) {
247*0fca6ea1SDimitry Andric         unsigned LocCookie = 0;
248*0fca6ea1SDimitry Andric         if (IsInlineAsm)
249*0fca6ea1SDimitry Andric           LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
250*0fca6ea1SDimitry Andric         Ctx.diagnose(
251*0fca6ea1SDimitry Andric             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
252*0fca6ea1SDimitry Andric       });
253*0fca6ea1SDimitry Andric   MMI.DbgInfoAvailable =
254*0fca6ea1SDimitry Andric       !DisableDebugInfoPrinting && !M.debug_compile_units().empty();
255*0fca6ea1SDimitry Andric   return Result(MMI);
2568bcb0991SDimitry Andric }
257