//===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/DebugLoc.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/IR/DebugInfo.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// DebugLoc Implementation
//===----------------------------------------------------------------------===//

MDNode *DebugLoc::getScope(const LLVMContext &Ctx) const {
  if (ScopeIdx == 0) return nullptr;
  
  if (ScopeIdx > 0) {
    // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
    // position specified.
    assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
           "Invalid ScopeIdx!");
    return Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
  }
  
  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
}

MDNode *DebugLoc::getInlinedAt(const LLVMContext &Ctx) const {
  // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
  // position specified.  Zero is invalid.
  if (ScopeIdx >= 0) return nullptr;
  
  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
}

/// Return both the Scope and the InlinedAt values.
void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
                                    const LLVMContext &Ctx) const {
  if (ScopeIdx == 0) {
    Scope = IA = nullptr;
    return;
  }
  
  if (ScopeIdx > 0) {
    // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
    // position specified.
    assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
           "Invalid ScopeIdx!");
    Scope = Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
    IA = nullptr;
    return;
  }
  
  // Otherwise, the index is in the ScopeInlinedAtRecords array.
  assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
         "Invalid ScopeIdx");
  Scope = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
  IA    = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
}

MDNode *DebugLoc::getScopeNode(const LLVMContext &Ctx) const {
  if (MDNode *InlinedAt = getInlinedAt(Ctx))
    return DebugLoc::getFromDILocation(InlinedAt).getScopeNode(Ctx);
  return getScope(Ctx);
}

DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) const {
  const MDNode *Scope = getScopeNode(Ctx);
  DISubprogram SP = getDISubprogram(Scope);
  if (SP.isSubprogram())
    return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);

  return DebugLoc();
}

DebugLoc DebugLoc::get(unsigned Line, unsigned Col,
                       MDNode *Scope, MDNode *InlinedAt) {
  DebugLoc Result;
  
  // If no scope is available, this is an unknown location.
  if (!Scope) return Result;

  // Saturate line and col to "unknown".
  if (Col > 255) Col = 0;
  if (Line >= (1 << 24)) Line = 0;
  Result.LineCol = Line | (Col << 24);
  
  LLVMContext &Ctx = Scope->getContext();
  
  // If there is no inlined-at location, use the ScopeRecords array.
  if (!InlinedAt)
    Result.ScopeIdx = Ctx.pImpl->getOrAddScopeRecordIdxEntry(Scope, 0);
  else
    Result.ScopeIdx = Ctx.pImpl->getOrAddScopeInlinedAtIdxEntry(Scope,
                                                                InlinedAt, 0);

  return Result;
}

/// getAsMDNode - This method converts the compressed DebugLoc node into a
/// DILocation-compatible MDNode.
MDNode *DebugLoc::getAsMDNode(const LLVMContext &Ctx) const {
  if (isUnknown()) return nullptr;
  
  MDNode *Scope, *IA;
  getScopeAndInlinedAt(Scope, IA, Ctx);
  assert(Scope && "If scope is null, this should be isUnknown()");
  
  LLVMContext &Ctx2 = Scope->getContext();
  Type *Int32 = Type::getInt32Ty(Ctx2);
  Value *Elts[] = {
    ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()),
    Scope, IA
  };
  return MDNode::get(Ctx2, Elts);
}

/// getFromDILocation - Translate the DILocation quad into a DebugLoc.
DebugLoc DebugLoc::getFromDILocation(MDNode *N) {
  DILocation Loc(N);
  MDNode *Scope = Loc.getScope();
  if (!Scope) return DebugLoc();
  return get(Loc.getLineNumber(), Loc.getColumnNumber(), Scope,
             Loc.getOrigLocation());
}

/// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc.
DebugLoc DebugLoc::getFromDILexicalBlock(MDNode *N) {
  DILexicalBlock LexBlock(N);
  MDNode *Scope = LexBlock.getContext();
  if (!Scope) return DebugLoc();
  return get(LexBlock.getLineNumber(), LexBlock.getColumnNumber(), Scope,
             nullptr);
}

void DebugLoc::dump(const LLVMContext &Ctx) const {
#ifndef NDEBUG
  if (!isUnknown()) {
    dbgs() << getLine();
    if (getCol() != 0)
      dbgs() << ',' << getCol();
    DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx));
    if (!InlinedAtDL.isUnknown()) {
      dbgs() << " @ ";
      InlinedAtDL.dump(Ctx);
    } else
      dbgs() << "\n";
  }
#endif
}

void DebugLoc::print(const LLVMContext &Ctx, raw_ostream &OS) const {
  if (!isUnknown()) {
    // Print source line info.
    DIScope Scope(getScope(Ctx));
    assert((!Scope || Scope.isScope()) &&
           "Scope of a DebugLoc should be null or a DIScope.");
    if (Scope)
      OS << Scope.getFilename();
    else
      OS << "<unknown>";
    OS << ':' << getLine();
    if (getCol() != 0)
      OS << ':' << getCol();
    DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx));
    if (!InlinedAtDL.isUnknown()) {
      OS << " @[ ";
      InlinedAtDL.print(Ctx, OS);
      OS << " ]";
    }
  }
}

//===----------------------------------------------------------------------===//
// DenseMap specialization
//===----------------------------------------------------------------------===//

unsigned DenseMapInfo<DebugLoc>::getHashValue(const DebugLoc &Key) {
  return static_cast<unsigned>(hash_combine(Key.LineCol, Key.ScopeIdx));
}

//===----------------------------------------------------------------------===//
// LLVMContextImpl Implementation
//===----------------------------------------------------------------------===//

int LLVMContextImpl::getOrAddScopeRecordIdxEntry(MDNode *Scope,
                                                 int ExistingIdx) {
  // If we already have an entry for this scope, return it.
  int &Idx = ScopeRecordIdx[Scope];
  if (Idx) return Idx;
  
  // If we don't have an entry, but ExistingIdx is specified, use it.
  if (ExistingIdx)
    return Idx = ExistingIdx;
  
  // Otherwise add a new entry.
  
  // Start out ScopeRecords with a minimal reasonable size to avoid
  // excessive reallocation starting out.
  if (ScopeRecords.empty())
    ScopeRecords.reserve(128);
  
  // Index is biased by 1 for index.
  Idx = ScopeRecords.size()+1;
  ScopeRecords.push_back(DebugRecVH(Scope, this, Idx));
  return Idx;
}

int LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,
                                                    int ExistingIdx) {
  // If we already have an entry, return it.
  int &Idx = ScopeInlinedAtIdx[std::make_pair(Scope, IA)];
  if (Idx) return Idx;
  
  // If we don't have an entry, but ExistingIdx is specified, use it.
  if (ExistingIdx)
    return Idx = ExistingIdx;
  
  // Start out ScopeInlinedAtRecords with a minimal reasonable size to avoid
  // excessive reallocation starting out.
  if (ScopeInlinedAtRecords.empty())
    ScopeInlinedAtRecords.reserve(128);
    
  // Index is biased by 1 and negated.
  Idx = -ScopeInlinedAtRecords.size()-1;
  ScopeInlinedAtRecords.push_back(std::make_pair(DebugRecVH(Scope, this, Idx),
                                                 DebugRecVH(IA, this, Idx)));
  return Idx;
}


//===----------------------------------------------------------------------===//
// DebugRecVH Implementation
//===----------------------------------------------------------------------===//

/// deleted - The MDNode this is pointing to got deleted, so this pointer needs
/// to drop to null and we need remove our entry from the DenseMap.
void DebugRecVH::deleted() {
  // If this is a non-canonical reference, just drop the value to null, we know
  // it doesn't have a map entry.
  if (Idx == 0) {
    setValPtr(nullptr);
    return;
  }
    
  MDNode *Cur = get();
  
  // If the index is positive, it is an entry in ScopeRecords.
  if (Idx > 0) {
    assert(Ctx->ScopeRecordIdx[Cur] == Idx && "Mapping out of date!");
    Ctx->ScopeRecordIdx.erase(Cur);
    // Reset this VH to null and we're done.
    setValPtr(nullptr);
    Idx = 0;
    return;
  }
  
  // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
  // is the scope or the inlined-at record entry.
  assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
  std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
  assert((this == &Entry.first || this == &Entry.second) &&
         "Mapping out of date!");
  
  MDNode *OldScope = Entry.first.get();
  MDNode *OldInlinedAt = Entry.second.get();
  assert(OldScope && OldInlinedAt &&
         "Entry should be non-canonical if either val dropped to null");

  // Otherwise, we do have an entry in it, nuke it and we're done.
  assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
         "Mapping out of date");
  Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));
  
  // Reset this VH to null.  Drop both 'Idx' values to null to indicate that
  // we're in non-canonical form now.
  setValPtr(nullptr);
  Entry.first.Idx = Entry.second.Idx = 0;
}

void DebugRecVH::allUsesReplacedWith(Value *NewVa) {
  // If being replaced with a non-mdnode value (e.g. undef) handle this as if
  // the mdnode got deleted.
  MDNode *NewVal = dyn_cast<MDNode>(NewVa);
  if (!NewVal) return deleted();

  // If this is a non-canonical reference, just change it, we know it already
  // doesn't have a map entry.
  if (Idx == 0) {
    setValPtr(NewVa);
    return;
  }
  
  MDNode *OldVal = get();
  assert(OldVal != NewVa && "Node replaced with self?");
  
  // If the index is positive, it is an entry in ScopeRecords.
  if (Idx > 0) {
    assert(Ctx->ScopeRecordIdx[OldVal] == Idx && "Mapping out of date!");
    Ctx->ScopeRecordIdx.erase(OldVal);
    setValPtr(NewVal);

    int NewEntry = Ctx->getOrAddScopeRecordIdxEntry(NewVal, Idx);
    
    // If NewVal already has an entry, this becomes a non-canonical reference,
    // just drop Idx to 0 to signify this.
    if (NewEntry != Idx)
      Idx = 0;
    return;
  }
  
  // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
  // is the scope or the inlined-at record entry.
  assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
  std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
  assert((this == &Entry.first || this == &Entry.second) &&
         "Mapping out of date!");
  
  MDNode *OldScope = Entry.first.get();
  MDNode *OldInlinedAt = Entry.second.get();
  assert(OldScope && OldInlinedAt &&
         "Entry should be non-canonical if either val dropped to null");
  
  // Otherwise, we do have an entry in it, nuke it and we're done.
  assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
         "Mapping out of date");
  Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));
  
  // Reset this VH to the new value.
  setValPtr(NewVal);

  int NewIdx = Ctx->getOrAddScopeInlinedAtIdxEntry(Entry.first.get(),
                                                   Entry.second.get(), Idx);
  // If NewVal already has an entry, this becomes a non-canonical reference,
  // just drop Idx to 0 to signify this.
  if (NewIdx != Idx) {
    std::pair<DebugRecVH, DebugRecVH> &Entry=Ctx->ScopeInlinedAtRecords[-Idx-1];
    Entry.first.Idx = Entry.second.Idx = 0;
  }
}
