//===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include <cassert>

using namespace llvm;
using namespace llvm::dwarf;

// Out of line virtual method.
MachineModuleInfoImpl::~MachineModuleInfoImpl() = default;

void MachineModuleInfo::initialize() {
  ObjFileMMI = nullptr;
  NextFnNum = 0;
}

void MachineModuleInfo::finalize() {
  Context.reset();
  // We don't clear the ExternalContext.

  delete ObjFileMMI;
  ObjFileMMI = nullptr;
}

MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI)
    : TM(std::move(MMI.TM)),
      Context(TM.getTargetTriple(), TM.getMCAsmInfo(), TM.getMCRegisterInfo(),
              TM.getMCSubtargetInfo(), nullptr, false),
      MachineFunctions(std::move(MMI.MachineFunctions)) {
  Context.setObjectFileInfo(TM.getObjFileLowering());
  ObjFileMMI = MMI.ObjFileMMI;
  ExternalContext = MMI.ExternalContext;
  TheModule = MMI.TheModule;
}

MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM)
    : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
                       TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
                       nullptr, false) {
  Context.setObjectFileInfo(TM->getObjFileLowering());
  initialize();
}

MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM,
                                     MCContext *ExtContext)
    : TM(*TM), Context(TM->getTargetTriple(), TM->getMCAsmInfo(),
                       TM->getMCRegisterInfo(), TM->getMCSubtargetInfo(),
                       nullptr, false),
      ExternalContext(ExtContext) {
  Context.setObjectFileInfo(TM->getObjFileLowering());
  initialize();
}

MachineModuleInfo::~MachineModuleInfo() { finalize(); }

MachineFunction *
MachineModuleInfo::getMachineFunction(const Function &F) const {
  auto I = MachineFunctions.find(&F);
  return I != MachineFunctions.end() ? I->second.get() : nullptr;
}

MachineFunction &MachineModuleInfo::getOrCreateMachineFunction(Function &F) {
  // Shortcut for the common case where a sequence of MachineFunctionPasses
  // all query for the same Function.
  if (LastRequest == &F)
    return *LastResult;

  auto I = MachineFunctions.insert(
      std::make_pair(&F, std::unique_ptr<MachineFunction>()));
  MachineFunction *MF;
  if (I.second) {
    // No pre-existing machine function, create a new one.
    const TargetSubtargetInfo &STI = *TM.getSubtargetImpl(F);
    MF = new MachineFunction(F, TM, STI, getContext(), NextFnNum++);
    MF->initTargetMachineFunctionInfo(STI);

    // MRI callback for target specific initializations.
    TM.registerMachineRegisterInfoCallback(*MF);

    // Update the set entry.
    I.first->second.reset(MF);
  } else {
    MF = I.first->second.get();
  }

  LastRequest = &F;
  LastResult = MF;
  return *MF;
}

void MachineModuleInfo::deleteMachineFunctionFor(Function &F) {
  MachineFunctions.erase(&F);
  LastRequest = nullptr;
  LastResult = nullptr;
}

void MachineModuleInfo::insertFunction(const Function &F,
                                       std::unique_ptr<MachineFunction> &&MF) {
  auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF)));
  assert(I.second && "machine function already mapped");
  (void)I;
}

namespace {

/// This pass frees the MachineFunction object associated with a Function.
class FreeMachineFunction : public FunctionPass {
public:
  static char ID;

  FreeMachineFunction() : FunctionPass(ID) {}

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<MachineModuleInfoWrapperPass>();
    AU.addPreserved<MachineModuleInfoWrapperPass>();
  }

  bool runOnFunction(Function &F) override {
    MachineModuleInfo &MMI =
        getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
    MMI.deleteMachineFunctionFor(F);
    return true;
  }

  StringRef getPassName() const override {
    return "Free MachineFunction";
  }
};

} // end anonymous namespace

char FreeMachineFunction::ID;

FunctionPass *llvm::createFreeMachineFunctionPass() {
  return new FreeMachineFunction();
}

MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
    const TargetMachine *TM)
    : ImmutablePass(ID), MMI(TM) {}

MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass(
    const TargetMachine *TM, MCContext *ExtContext)
    : ImmutablePass(ID), MMI(TM, ExtContext) {}

// Handle the Pass registration stuff necessary to use DataLayout's.
INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo",
                "Machine Module Information", false, false)
char MachineModuleInfoWrapperPass::ID = 0;

static uint64_t getLocCookie(const SMDiagnostic &SMD, const SourceMgr &SrcMgr,
                             std::vector<const MDNode *> &LocInfos) {
  // Look up a LocInfo for the buffer this diagnostic is coming from.
  unsigned BufNum = SrcMgr.FindBufferContainingLoc(SMD.getLoc());
  const MDNode *LocInfo = nullptr;
  if (BufNum > 0 && BufNum <= LocInfos.size())
    LocInfo = LocInfos[BufNum - 1];

  // If the inline asm had metadata associated with it, pull out a location
  // cookie corresponding to which line the error occurred on.
  uint64_t LocCookie = 0;
  if (LocInfo) {
    unsigned ErrorLine = SMD.getLineNo() - 1;
    if (ErrorLine >= LocInfo->getNumOperands())
      ErrorLine = 0;

    if (LocInfo->getNumOperands() != 0)
      if (const ConstantInt *CI =
              mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
        LocCookie = CI->getZExtValue();
  }

  return LocCookie;
}

bool MachineModuleInfoWrapperPass::doInitialization(Module &M) {
  MMI.initialize();
  MMI.TheModule = &M;
  LLVMContext &Ctx = M.getContext();
  MMI.getContext().setDiagnosticHandler(
      [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
                 const SourceMgr &SrcMgr,
                 std::vector<const MDNode *> &LocInfos) {
        uint64_t LocCookie = 0;
        if (IsInlineAsm)
          LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
        Ctx.diagnose(
            DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
      });
  return false;
}

bool MachineModuleInfoWrapperPass::doFinalization(Module &M) {
  MMI.finalize();
  return false;
}

AnalysisKey MachineModuleAnalysis::Key;

MachineModuleAnalysis::Result
MachineModuleAnalysis::run(Module &M, ModuleAnalysisManager &) {
  MMI.TheModule = &M;
  LLVMContext &Ctx = M.getContext();
  MMI.getContext().setDiagnosticHandler(
      [&Ctx, &M](const SMDiagnostic &SMD, bool IsInlineAsm,
                 const SourceMgr &SrcMgr,
                 std::vector<const MDNode *> &LocInfos) {
        unsigned LocCookie = 0;
        if (IsInlineAsm)
          LocCookie = getLocCookie(SMD, SrcMgr, LocInfos);
        Ctx.diagnose(
            DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
      });
  return Result(MMI);
}
