//===- DebugSSAUpdater.cpp - Debug Variable SSA Update Tool ---------------===//
//
// 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 DebugSSAUpdater class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/DebugSSAUpdater.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Transforms/Utils/SSAUpdaterImpl.h"

using namespace llvm;

#define DEBUG_TYPE "debug-ssa-updater"

void DbgValueDef::print(raw_ostream &OS) const {
  OS << "DbgVal{ ";
  if (IsUndef) {
    OS << "undef }";
    return;
  }
  if (Phi) {
    OS << *Phi << "}";
    return;
  }
  OS << (IsMemory ? "Mem: " : "Def: ") << *Locations << " - " << *Expression
     << " }";
}

void DbgSSAPhi::print(raw_ostream &OS) const {
  OS << "DbgPhi ";
  for (auto &[BB, DV] : IncomingValues)
    OS << "[" << BB->BB.getName() << ", " << DV << "] ";
}

using AvailableValsTy = DenseMap<DbgSSABlock *, DbgValueDef>;

DebugSSAUpdater::DebugSSAUpdater(SmallVectorImpl<DbgSSAPhi *> *NewPHI)
    : InsertedPHIs(NewPHI) {}

void DebugSSAUpdater::initialize() { AV.clear(); }

bool DebugSSAUpdater::hasValueForBlock(DbgSSABlock *BB) const {
  return AV.count(BB);
}

DbgValueDef DebugSSAUpdater::findValueForBlock(DbgSSABlock *BB) const {
  return AV.lookup(BB);
}

void DebugSSAUpdater::addAvailableValue(DbgSSABlock *BB, DbgValueDef DV) {
  AV[BB] = DV;
}

DbgValueDef DebugSSAUpdater::getValueAtEndOfBlock(DbgSSABlock *BB) {
  DbgValueDef Res = getValueAtEndOfBlockInternal(BB);
  return Res;
}

DbgValueDef DebugSSAUpdater::getValueInMiddleOfBlock(DbgSSABlock *BB) {
  // If there is no definition of the renamed variable in this block, just use
  // 'getValueAtEndOfBlock' to do our work.
  if (!hasValueForBlock(BB))
    return getValueAtEndOfBlock(BB);

  // Otherwise, we have the hard case. Get the live-in values for each
  // predecessor.
  SmallVector<std::pair<DbgSSABlock *, DbgValueDef>, 8> PredValues;
  DbgValueDef SingularValue;

  bool IsFirstPred = true;
  for (DbgSSABlock *PredBB : BB->predecessors()) {
    DbgValueDef PredVal = getValueAtEndOfBlock(PredBB);
    PredValues.push_back(std::make_pair(PredBB, PredVal));

    // Compute SingularValue.
    if (IsFirstPred) {
      SingularValue = PredVal;
      IsFirstPred = false;
    } else if (!PredVal.agreesWith(SingularValue))
      SingularValue = DbgValueDef();
  }

  // If there are no predecessors, just return undef.
  if (PredValues.empty())
    return DbgValueDef();

  // Otherwise, if all the merged values are the same, just use it.
  if (!SingularValue.IsUndef)
    return SingularValue;

  // Ok, we have no way out, insert a new one now.
  DbgSSAPhi *InsertedPHI = BB->newPHI();

  // Fill in all the predecessors of the PHI.
  for (const auto &PredValue : PredValues)
    InsertedPHI->addIncoming(PredValue.first, PredValue.second);

  // See if the PHI node can be merged to a single value. This can happen in
  // loop cases when we get a PHI of itself and one other value.

  // If the client wants to know about all new instructions, tell it.
  if (InsertedPHIs)
    InsertedPHIs->push_back(InsertedPHI);

  LLVM_DEBUG(dbgs() << "  Inserted PHI: " << *InsertedPHI << "\n");
  return InsertedPHI;
}

DbgSSABlock *DbgSSABlockSuccIterator::operator*() {
  return Updater.getDbgSSABlock(*SuccIt);
}
DbgSSABlock *DbgSSABlockPredIterator::operator*() {
  return Updater.getDbgSSABlock(*PredIt);
}

namespace llvm {

template <> class SSAUpdaterTraits<DebugSSAUpdater> {
public:
  using BlkT = DbgSSABlock;
  using ValT = DbgValueDef;
  using PhiT = DbgSSAPhi;
  using BlkSucc_iterator = DbgSSABlockSuccIterator;

  static BlkSucc_iterator BlkSucc_begin(BlkT *BB) { return BB->succ_begin(); }
  static BlkSucc_iterator BlkSucc_end(BlkT *BB) { return BB->succ_end(); }

  class PHI_iterator {
  private:
    DbgSSAPhi *PHI;
    unsigned Idx;

  public:
    explicit PHI_iterator(DbgSSAPhi *P) // begin iterator
        : PHI(P), Idx(0) {}
    PHI_iterator(DbgSSAPhi *P, bool) // end iterator
        : PHI(P), Idx(PHI->getNumIncomingValues()) {}

    PHI_iterator &operator++() {
      ++Idx;
      return *this;
    }
    bool operator==(const PHI_iterator &X) const { return Idx == X.Idx; }
    bool operator!=(const PHI_iterator &X) const { return !operator==(X); }

    DbgValueDef getIncomingValue() { return PHI->getIncomingValue(Idx); }
    DbgSSABlock *getIncomingBlock() { return PHI->getIncomingBlock(Idx); }
  };

  static PHI_iterator PHI_begin(PhiT *PHI) { return PHI_iterator(PHI); }
  static PHI_iterator PHI_end(PhiT *PHI) { return PHI_iterator(PHI, true); }

  /// FindPredecessorBlocks - Put the predecessors of BB into the Preds
  /// vector.
  static void FindPredecessorBlocks(DbgSSABlock *BB,
                                    SmallVectorImpl<DbgSSABlock *> *Preds) {
    for (auto PredIt = BB->pred_begin(); PredIt != BB->pred_end(); ++PredIt)
      Preds->push_back(*PredIt);
  }

  /// GetPoisonVal - Get an undefined value of the same type as the value
  /// being handled.
  static DbgValueDef GetPoisonVal(DbgSSABlock *BB, DebugSSAUpdater *Updater) {
    return DbgValueDef();
  }

  /// CreateEmptyPHI - Create a new debug PHI entry for the specified block.
  static DbgSSAPhi *CreateEmptyPHI(DbgSSABlock *BB, unsigned NumPreds,
                                   DebugSSAUpdater *Updater) {
    DbgSSAPhi *PHI = BB->newPHI();
    return PHI;
  }

  /// AddPHIOperand - Add the specified value as an operand of the PHI for
  /// the specified predecessor block.
  static void AddPHIOperand(DbgSSAPhi *PHI, DbgValueDef Val,
                            DbgSSABlock *Pred) {
    PHI->addIncoming(Pred, Val);
  }

  /// ValueIsPHI - Check if a value is a PHI.
  static DbgSSAPhi *ValueIsPHI(DbgValueDef Val, DebugSSAUpdater *Updater) {
    return Val.Phi;
  }

  /// ValueIsNewPHI - Like ValueIsPHI but also check if the PHI has no source
  /// operands, i.e., it was just added.
  static DbgSSAPhi *ValueIsNewPHI(DbgValueDef Val, DebugSSAUpdater *Updater) {
    DbgSSAPhi *PHI = ValueIsPHI(Val, Updater);
    if (PHI && PHI->getNumIncomingValues() == 0)
      return PHI;
    return nullptr;
  }

  /// GetPHIValue - For the specified PHI instruction, return the value
  /// that it defines.
  static DbgValueDef GetPHIValue(DbgSSAPhi *PHI) { return PHI; }
};

} // end namespace llvm

/// Check to see if AvailableVals has an entry for the specified BB and if so,
/// return it. If not, construct SSA form by first calculating the required
/// placement of PHIs and then inserting new PHIs where needed.
DbgValueDef DebugSSAUpdater::getValueAtEndOfBlockInternal(DbgSSABlock *BB) {
  if (AV.contains(BB))
    return AV[BB];

  SSAUpdaterImpl<DebugSSAUpdater> Impl(this, &AV, InsertedPHIs);
  return Impl.GetValue(BB);
}

bool isContained(DIScope *Inner, DIScope *Outer) {
  if (Inner == Outer)
    return true;
  if (!Inner->getScope())
    return false;
  return isContained(Inner->getScope(), Outer);
}

void DbgValueRangeTable::addVariable(Function *F, DebugVariableAggregate DVA) {
  const DILocalVariable *Var = DVA.getVariable();
  const DILocation *InlinedAt = DVA.getInlinedAt();

  DenseMap<BasicBlock *, SmallVector<DbgVariableRecord *>> BlockDbgRecordValues;
  DenseSet<BasicBlock *> HasAnyInstructionsInScope;
  int NumRecordsFound = 0;
  DbgVariableRecord *LastRecordFound = nullptr;
  bool DeclareRecordFound = false;

  LLVM_DEBUG(dbgs() << "Finding variable info for " << *Var << " at "
                    << InlinedAt << "\n");

  for (auto &BB : *F) {
    auto &DbgRecordValues = BlockDbgRecordValues[&BB];
    bool FoundInstructionInScope = false;
    for (auto &I : BB) {
      LLVM_DEBUG(dbgs() << "Instruction: '" << I << "'\n");

      for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
        if (DVR.getVariable() == Var &&
            DVR.getDebugLoc().getInlinedAt() == InlinedAt) {
          assert(!DVR.isDbgAssign() && "No support for #dbg_assign yet.");
          if (DVR.isDbgDeclare())
            DeclareRecordFound = true;
          ++NumRecordsFound;
          LastRecordFound = &DVR;
          DbgRecordValues.push_back(&DVR);
        }
      }
      if (!FoundInstructionInScope && I.getDebugLoc()) {
        if (I.getDebugLoc().getInlinedAt() == InlinedAt &&
            isContained(cast<DILocalScope>(I.getDebugLoc().getScope()),
                        Var->getScope())) {
          FoundInstructionInScope = true;
          HasAnyInstructionsInScope.insert(&BB);
        }
      }
    }
    LLVM_DEBUG(dbgs() << "DbgRecordValues found in '" << BB.getName() << "':\n";
               for_each(DbgRecordValues, [](auto *DV) { DV->dump(); }));
  }

  if (!NumRecordsFound) {
    LLVM_DEBUG(dbgs() << "No dbg_records found for variable!\n");
    return;
  }

  // Now that we have all the DbgValues, we can start defining available values
  // for each block. The end goal is to have, for every block with any
  // instructions in scope, a LiveIn value.
  // Currently we anticipate that either a variable has a set of #dbg_values, in
  // which case we need a complete SSA liveness analysis to determine live-in
  // values per-block, or a variable has a single #dbg_declare.
  if (DeclareRecordFound) {
    // FIXME: This should be changed for fragments!
    LLVM_DEBUG(dbgs() << "Single location found for variable!\n");
    assert(NumRecordsFound == 1 &&
           "Found multiple records for a #dbg_declare variable!");
    OrigSingleLocVariableValueTable[DVA] = DbgValueDef(LastRecordFound);
    return;
  }

  // We don't have a single location for the variable's entire scope, so instead
  // we must now perform a liveness analysis to create a location list.
  SmallVector<DbgSSAPhi *> HypotheticalPHIs;
  DebugSSAUpdater SSAUpdater(&HypotheticalPHIs);
  SSAUpdater.initialize();
  for (auto &[BB, DVs] : BlockDbgRecordValues) {
    auto *DbgBB = SSAUpdater.getDbgSSABlock(BB);
    if (DVs.empty())
      continue;
    auto *LastValueInBlock = DVs.back();
    LLVM_DEBUG(dbgs() << "Last value in " << BB->getName() << ": "
                      << *LastValueInBlock << "\n");
    SSAUpdater.addAvailableValue(DbgBB, DbgValueDef(LastValueInBlock));
  }

  for (BasicBlock &BB : *F) {
    if (!HasAnyInstructionsInScope.contains(&BB)) {
      LLVM_DEBUG(dbgs() << "Skipping finding debug ranges for '" << BB.getName()
                        << "' due to no in-scope instructions.\n");
      continue;
    }
    LLVM_DEBUG(dbgs() << "Finding live-in value for '" << BB.getName()
                      << "'...\n");
    DbgValueDef LiveValue =
        SSAUpdater.getValueInMiddleOfBlock(SSAUpdater.getDbgSSABlock(&BB));
    LLVM_DEBUG(dbgs() << "Found live-in: " << LiveValue << "\n");
    auto HasValidValue = [](DbgValueDef DV) {
      return !DV.IsUndef && DV.Phi == nullptr;
    };

    SmallVector<DbgRangeEntry> BlockDbgRanges;
    BasicBlock::iterator LastIt = BB.begin();
    for (auto *DVR : BlockDbgRecordValues[&BB]) {
      // Create a range that ends as of DVR.
      BasicBlock::iterator DVRStartIt =
          const_cast<Instruction *>(DVR->getInstruction())->getIterator();
      if (HasValidValue(LiveValue))
        BlockDbgRanges.push_back({LastIt, DVRStartIt, LiveValue});
      LiveValue = DbgValueDef(DVR);
      LastIt = DVRStartIt;
    }

    // After considering all in-block debug values, if any, create a range
    // covering the remainder of the block.
    if (HasValidValue(LiveValue))
      BlockDbgRanges.push_back({LastIt, BB.end(), LiveValue});
    LLVM_DEBUG(dbgs() << "Create set of ranges with " << BlockDbgRanges.size()
                      << " entries!\n");
    if (!BlockDbgRanges.empty())
      OrigVariableValueRangeTable[DVA].append(BlockDbgRanges);
  }
}

void DbgValueRangeTable::printValues(DebugVariableAggregate DVA,
                                     raw_ostream &OS) {
  OS << "Variable Table for '" << DVA.getVariable()->getName() << "' (at "
     << DVA.getInlinedAt() << "):\n";
  if (!hasVariableEntry(DVA)) {
    OS << "  Empty!\n";
    return;
  }
  if (hasSingleLocEntry(DVA)) {
    OS << "  SingleLoc: " << OrigSingleLocVariableValueTable[DVA] << "\n";
    return;
  }
  OS << "  LocRange:\n";
  for (DbgRangeEntry RangeEntry : OrigVariableValueRangeTable[DVA]) {
    OS << "    (";
    if (RangeEntry.Start == RangeEntry.Start->getParent()->begin() &&
        RangeEntry.End == RangeEntry.Start->getParent()->end()) {
      OS << RangeEntry.Start->getParent()->getName();
    } else {
      OS << RangeEntry.Start->getParent()->getName() << ": "
         << *RangeEntry.Start << ", ";
      if (RangeEntry.End == RangeEntry.Start->getParent()->end())
        OS << "..";
      else
        OS << *RangeEntry.End;
    }
    OS << ") [" << RangeEntry.Value << "]\n";
  }
}

SSAValueNameMap::ValueID SSAValueNameMap::addValue(Value *V) {
  auto ExistingID = ValueToIDMap.find(V);
  if (ExistingID != ValueToIDMap.end())
    return ExistingID->second;
  // First, get a new ID and Map V to it.
  ValueID NewID = NextID++;
  ValueToIDMap.insert({V, NewID});
  // Then, get the name string for V and map NewID to it.
  assert(!ValueIDToNameMap.contains(NewID) &&
         "New value ID already maps to a name?");
  std::string &ValueText = ValueIDToNameMap[NewID];
  raw_string_ostream Stream(ValueText);
  V->printAsOperand(Stream, true);
  return NewID;
}
