llvm/llvm/lib/CodeGen/LiveDebugVariables.cpp

//===- LiveDebugVariables.cpp - Tracking debug info variables -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveDebugVariables analysis.
//
// Remove all DBG_VALUE instructions referencing virtual registers and replace
// them with a data structure tracking where live user variables are kept - in a
// virtual register or in a stack slot.
//
// Allow the data structure to be updated during register allocation when values
// are moved between registers and stack slots. Finally emit new DBG_VALUE
// instructions after register allocation is complete.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/LiveDebugVariables.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <map>
#include <memory>
#include <optional>
#include <utility>

usingnamespacellvm;

#define DEBUG_TYPE

static cl::opt<bool>
EnableLDV("live-debug-variables", cl::init(true),
          cl::desc("Enable the live debug variables pass"), cl::Hidden);

STATISTIC(NumInsertedDebugValues, "Number of DBG_VALUEs inserted");
STATISTIC(NumInsertedDebugLabels, "Number of DBG_LABELs inserted");

char LiveDebugVariables::ID =;

INITIALIZE_PASS_BEGIN(LiveDebugVariables, DEBUG_TYPE,
                "Debug Variable Analysis", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
INITIALIZE_PASS_END(LiveDebugVariables, DEBUG_TYPE,
                "Debug Variable Analysis", false, false)

void LiveDebugVariables::getAnalysisUsage(AnalysisUsage &AU) const {}

LiveDebugVariables::LiveDebugVariables() :{}

enum : unsigned {};

namespace {
/// Describes a debug variable value by location number and expression along
/// with some flags about the original usage of the location.
class DbgVariableValue {};
} // namespace

/// Map of where a user value is live to that value.
LocMap;

/// Map of stack slot offsets for spilled locations.
/// Non-spilled locations are not added to the map.
SpillOffsetMap;

/// Cache to save the location where it can be used as the starting
/// position as input for calling MachineBasicBlock::SkipPHIsLabelsAndDebug.
/// This is to prevent MachineBasicBlock::SkipPHIsLabelsAndDebug from
/// repeatedly searching the same set of PHIs/Labels/Debug instructions
/// if it is called many times for the same block.
BlockSkipInstsMap;

namespace {

class LDVImpl;

/// A user value is a part of a debug info user variable.
///
/// A DBG_VALUE instruction notes that (a sub-register of) a virtual register
/// holds part of a user variable. The part is identified by a byte offset.
///
/// UserValues are grouped into equivalence classes for easier searching. Two
/// user values are related if they are held by the same virtual register. The
/// equivalence class is the transitive closure of that relation.
class UserValue {};

/// A user label is a part of a debug info user label.
class UserLabel {};

/// Implementation of the LiveDebugVariables pass.
class LDVImpl {};

} // end anonymous namespace

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
static void printDebugLoc(const DebugLoc &DL, raw_ostream &CommentOS,
                          const LLVMContext &Ctx) {
  if (!DL)
    return;

  auto *Scope = cast<DIScope>(DL.getScope());
  // Omit the directory, because it's likely to be long and uninteresting.
  CommentOS << Scope->getFilename();
  CommentOS << ':' << DL.getLine();
  if (DL.getCol() != 0)
    CommentOS << ':' << DL.getCol();

  DebugLoc InlinedAtDL = DL.getInlinedAt();
  if (!InlinedAtDL)
    return;

  CommentOS << " @[ ";
  printDebugLoc(InlinedAtDL, CommentOS, Ctx);
  CommentOS << " ]";
}

static void printExtendedName(raw_ostream &OS, const DINode *Node,
                              const DILocation *DL) {
  const LLVMContext &Ctx = Node->getContext();
  StringRef Res;
  unsigned Line = 0;
  if (const auto *V = dyn_cast<const DILocalVariable>(Node)) {
    Res = V->getName();
    Line = V->getLine();
  } else if (const auto *L = dyn_cast<const DILabel>(Node)) {
    Res = L->getName();
    Line = L->getLine();
  }

  if (!Res.empty())
    OS << Res << "," << Line;
  auto *InlinedAt = DL ? DL->getInlinedAt() : nullptr;
  if (InlinedAt) {
    if (DebugLoc InlinedAtDL = InlinedAt) {
      OS << " @[";
      printDebugLoc(InlinedAtDL, OS, Ctx);
      OS << "]";
    }
  }
}

void UserValue::print(raw_ostream &OS, const TargetRegisterInfo *TRI) {
  OS << "!\"";
  printExtendedName(OS, Variable, dl);

  OS << "\"\t";
  for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) {
    OS << " [" << I.start() << ';' << I.stop() << "):";
    if (I.value().isUndef())
      OS << " undef";
    else {
      I.value().printLocNos(OS);
      if (I.value().getWasIndirect())
        OS << " ind";
      else if (I.value().getWasList())
        OS << " list";
    }
  }
  for (unsigned i = 0, e = locations.size(); i != e; ++i) {
    OS << " Loc" << i << '=';
    locations[i].print(OS, TRI);
  }
  OS << '\n';
}

void UserLabel::print(raw_ostream &OS, const TargetRegisterInfo *TRI) {
  OS << "!\"";
  printExtendedName(OS, Label, dl);

  OS << "\"\t";
  OS << loc;
  OS << '\n';
}

void LDVImpl::print(raw_ostream &OS) {
  OS << "********** DEBUG VARIABLES **********\n";
  for (auto &userValue : userValues)
    userValue->print(OS, TRI);
  OS << "********** DEBUG LABELS **********\n";
  for (auto &userLabel : userLabels)
    userLabel->print(OS, TRI);
}
#endif

void UserValue::mapVirtRegs(LDVImpl *LDV) {}

UserValue *
LDVImpl::getUserValue(const DILocalVariable *Var,
                      std::optional<DIExpression::FragmentInfo> Fragment,
                      const DebugLoc &DL) {}

void LDVImpl::mapVirtReg(Register VirtReg, UserValue *EC) {}

UserValue *LDVImpl::lookupVirtReg(Register VirtReg) {}

bool LDVImpl::handleDebugValue(MachineInstr &MI, SlotIndex Idx) {}

MachineBasicBlock::iterator LDVImpl::handleDebugInstr(MachineInstr &MI,
                                                      SlotIndex Idx) {}

bool LDVImpl::handleDebugLabel(MachineInstr &MI, SlotIndex Idx) {}

bool LDVImpl::collectDebugValues(MachineFunction &mf, bool InstrRef) {}

void UserValue::extendDef(
    SlotIndex Idx, DbgVariableValue DbgValue,
    SmallDenseMap<unsigned, std::pair<LiveRange *, const VNInfo *>>
        &LiveIntervalInfo,
    std::optional<std::pair<SlotIndex, SmallVector<unsigned>>> &Kills,
    LiveIntervals &LIS) {}

void UserValue::addDefsFromCopies(
    DbgVariableValue DbgValue,
    SmallVectorImpl<std::pair<unsigned, LiveInterval *>> &LocIntervals,
    SlotIndex KilledAt,
    SmallVectorImpl<std::pair<SlotIndex, DbgVariableValue>> &NewDefs,
    MachineRegisterInfo &MRI, LiveIntervals &LIS) {}

void UserValue::computeIntervals(MachineRegisterInfo &MRI,
                                 const TargetRegisterInfo &TRI,
                                 LiveIntervals &LIS, LexicalScopes &LS) {}

void LDVImpl::computeIntervals() {}

bool LDVImpl::runOnMachineFunction(MachineFunction &mf, bool InstrRef) {}

static void removeDebugInstrs(MachineFunction &mf) {}

bool LiveDebugVariables::runOnMachineFunction(MachineFunction &mf) {}

void LiveDebugVariables::releaseMemory() {}

LiveDebugVariables::~LiveDebugVariables() {}

//===----------------------------------------------------------------------===//
//                           Live Range Splitting
//===----------------------------------------------------------------------===//

bool
UserValue::splitLocation(unsigned OldLocNo, ArrayRef<Register> NewRegs,
                         LiveIntervals& LIS) {}

bool
UserValue::splitRegister(Register OldReg, ArrayRef<Register> NewRegs,
                         LiveIntervals &LIS) {}

void LDVImpl::splitPHIRegister(Register OldReg, ArrayRef<Register> NewRegs) {}

void LDVImpl::splitRegister(Register OldReg, ArrayRef<Register> NewRegs) {}

void LiveDebugVariables::
splitRegister(Register OldReg, ArrayRef<Register> NewRegs, LiveIntervals &LIS) {}

void UserValue::rewriteLocations(VirtRegMap &VRM, const MachineFunction &MF,
                                 const TargetInstrInfo &TII,
                                 const TargetRegisterInfo &TRI,
                                 SpillOffsetMap &SpillOffsets) {}

/// Find an iterator for inserting a DBG_VALUE instruction.
static MachineBasicBlock::iterator
findInsertLocation(MachineBasicBlock *MBB, SlotIndex Idx, LiveIntervals &LIS,
                   BlockSkipInstsMap &BBSkipInstsMap) {}

/// Find an iterator for inserting the next DBG_VALUE instruction
/// (or end if no more insert locations found).
static MachineBasicBlock::iterator
findNextInsertLocation(MachineBasicBlock *MBB, MachineBasicBlock::iterator I,
                       SlotIndex StopIdx, ArrayRef<MachineOperand> LocMOs,
                       LiveIntervals &LIS, const TargetRegisterInfo &TRI) {}

void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
                                 SlotIndex StopIdx, DbgVariableValue DbgValue,
                                 ArrayRef<bool> LocSpills,
                                 ArrayRef<unsigned> SpillOffsets,
                                 LiveIntervals &LIS, const TargetInstrInfo &TII,
                                 const TargetRegisterInfo &TRI,
                                 BlockSkipInstsMap &BBSkipInstsMap) {}

void UserLabel::insertDebugLabel(MachineBasicBlock *MBB, SlotIndex Idx,
                                 LiveIntervals &LIS, const TargetInstrInfo &TII,
                                 BlockSkipInstsMap &BBSkipInstsMap) {}

void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
                                const TargetInstrInfo &TII,
                                const TargetRegisterInfo &TRI,
                                const SpillOffsetMap &SpillOffsets,
                                BlockSkipInstsMap &BBSkipInstsMap) {}

void UserLabel::emitDebugLabel(LiveIntervals &LIS, const TargetInstrInfo &TII,
                               BlockSkipInstsMap &BBSkipInstsMap) {}

void LDVImpl::emitDebugValues(VirtRegMap *VRM) {}

void LiveDebugVariables::emitDebugValues(VirtRegMap *VRM) {}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void LiveDebugVariables::dump() const {
  if (pImpl)
    static_cast<LDVImpl*>(pImpl)->print(dbgs());
}
#endif