//===-- llvm/CodeGen/DIEHash.cpp - Dwarf Hashing Framework ----------------===//
//
// 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 contains support for DWARF4 hashing of DIEs.
//
//===----------------------------------------------------------------------===//

#include "DIEHash.h"
#include "ByteStreamer.h"
#include "DwarfCompileUnit.h"
#include "DwarfDebug.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TYPE "dwarfdebug"

/// Grabs the string in whichever attribute is passed in and returns
/// a reference to it.
static StringRef getDIEStringAttr(const DIE &Die, uint16_t Attr) {
  // Iterate through all the attributes until we find the one we're
  // looking for, if we can't find it return an empty string.
  for (const auto &V : Die.values())
    if (V.getAttribute() == Attr)
      return V.getDIEString().getString();

  return StringRef("");
}

/// Adds the string in \p Str to the hash. This also hashes
/// a trailing NULL with the string.
void DIEHash::addString(StringRef Str) {
  LLVM_DEBUG(dbgs() << "Adding string " << Str << " to hash.\n");
  Hash.update(Str);
  Hash.update(ArrayRef((uint8_t)'\0'));
}

// FIXME: The LEB128 routines are copied and only slightly modified out of
// LEB128.h.

/// Adds the unsigned in \p Value to the hash encoded as a ULEB128.
void DIEHash::addULEB128(uint64_t Value) {
  LLVM_DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
  do {
    uint8_t Byte = Value & 0x7f;
    Value >>= 7;
    if (Value != 0)
      Byte |= 0x80; // Mark this byte to show that more bytes will follow.
    Hash.update(Byte);
  } while (Value != 0);
}

void DIEHash::addSLEB128(int64_t Value) {
  LLVM_DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
  bool More;
  do {
    uint8_t Byte = Value & 0x7f;
    Value >>= 7;
    More = !((((Value == 0) && ((Byte & 0x40) == 0)) ||
              ((Value == -1) && ((Byte & 0x40) != 0))));
    if (More)
      Byte |= 0x80; // Mark this byte to show that more bytes will follow.
    Hash.update(Byte);
  } while (More);
}

/// Including \p Parent adds the context of Parent to the hash..
void DIEHash::addParentContext(const DIE &Parent) {

  LLVM_DEBUG(dbgs() << "Adding parent context to hash...\n");

  // [7.27.2] For each surrounding type or namespace beginning with the
  // outermost such construct...
  SmallVector<const DIE *, 1> Parents;
  const DIE *Cur = &Parent;
  while (Cur->getParent()) {
    Parents.push_back(Cur);
    Cur = Cur->getParent();
  }
  assert(Cur->getTag() == dwarf::DW_TAG_compile_unit ||
         Cur->getTag() == dwarf::DW_TAG_type_unit);

  // Reverse iterate over our list to go from the outermost construct to the
  // innermost.
  for (const DIE *Die : llvm::reverse(Parents)) {
    // ... Append the letter "C" to the sequence...
    addULEB128('C');

    // ... Followed by the DWARF tag of the construct...
    addULEB128(Die->getTag());

    // ... Then the name, taken from the DW_AT_name attribute.
    StringRef Name = getDIEStringAttr(*Die, dwarf::DW_AT_name);
    LLVM_DEBUG(dbgs() << "... adding context: " << Name << "\n");
    if (!Name.empty())
      addString(Name);
  }
}

// Collect all of the attributes for a particular DIE in single structure.
void DIEHash::collectAttributes(const DIE &Die, DIEAttrs &Attrs) {

  for (const auto &V : Die.values()) {
    LLVM_DEBUG(dbgs() << "Attribute: "
                      << dwarf::AttributeString(V.getAttribute())
                      << " added.\n");
    switch (V.getAttribute()) {
#define HANDLE_DIE_HASH_ATTR(NAME)                                             \
  case dwarf::NAME:                                                            \
    Attrs.NAME = V;                                                            \
    break;
#include "DIEHashAttributes.def"
    default:
      break;
    }
  }
}

void DIEHash::hashShallowTypeReference(dwarf::Attribute Attribute,
                                       const DIE &Entry, StringRef Name) {
  // append the letter 'N'
  addULEB128('N');

  // the DWARF attribute code (DW_AT_type or DW_AT_friend),
  addULEB128(Attribute);

  // the context of the tag,
  if (const DIE *Parent = Entry.getParent())
    addParentContext(*Parent);

  // the letter 'E',
  addULEB128('E');

  // and the name of the type.
  addString(Name);

  // Currently DW_TAG_friends are not used by Clang, but if they do become so,
  // here's the relevant spec text to implement:
  //
  // For DW_TAG_friend, if the referenced entry is the DW_TAG_subprogram,
  // the context is omitted and the name to be used is the ABI-specific name
  // of the subprogram (e.g., the mangled linker name).
}

void DIEHash::hashRepeatedTypeReference(dwarf::Attribute Attribute,
                                        unsigned DieNumber) {
  // a) If T is in the list of [previously hashed types], use the letter
  // 'R' as the marker
  addULEB128('R');

  addULEB128(Attribute);

  // and use the unsigned LEB128 encoding of [the index of T in the
  // list] as the attribute value;
  addULEB128(DieNumber);
}

void DIEHash::hashDIEEntry(dwarf::Attribute Attribute, dwarf::Tag Tag,
                           const DIE &Entry) {
  assert(Tag != dwarf::DW_TAG_friend && "No current LLVM clients emit friend "
                                        "tags. Add support here when there's "
                                        "a use case");
  // Step 5
  // If the tag in Step 3 is one of [the below tags]
  if ((Tag == dwarf::DW_TAG_pointer_type ||
       Tag == dwarf::DW_TAG_reference_type ||
       Tag == dwarf::DW_TAG_rvalue_reference_type ||
       Tag == dwarf::DW_TAG_ptr_to_member_type) &&
      // and the referenced type (via the [below attributes])
      // FIXME: This seems overly restrictive, and causes hash mismatches
      // there's a decl/def difference in the containing type of a
      // ptr_to_member_type, but it's what DWARF says, for some reason.
      Attribute == dwarf::DW_AT_type) {
    // ... has a DW_AT_name attribute,
    StringRef Name = getDIEStringAttr(Entry, dwarf::DW_AT_name);
    if (!Name.empty()) {
      hashShallowTypeReference(Attribute, Entry, Name);
      return;
    }
  }

  unsigned &DieNumber = Numbering[&Entry];
  if (DieNumber) {
    hashRepeatedTypeReference(Attribute, DieNumber);
    return;
  }

  // otherwise, b) use the letter 'T' as the marker, ...
  addULEB128('T');

  addULEB128(Attribute);

  // ... process the type T recursively by performing Steps 2 through 7, and
  // use the result as the attribute value.
  DieNumber = Numbering.size();
  computeHash(Entry);
}

void DIEHash::hashRawTypeReference(const DIE &Entry) {
  unsigned &DieNumber = Numbering[&Entry];
  if (DieNumber) {
    addULEB128('R');
    addULEB128(DieNumber);
    return;
  }
  DieNumber = Numbering.size();
  addULEB128('T');
  computeHash(Entry);
}

// Hash all of the values in a block like set of values. This assumes that
// all of the data is going to be added as integers.
void DIEHash::hashBlockData(const DIE::const_value_range &Values) {
  for (const auto &V : Values)
    if (V.getType() == DIEValue::isBaseTypeRef) {
      const DIE &C =
          *CU->ExprRefedBaseTypes[V.getDIEBaseTypeRef().getIndex()].Die;
      StringRef Name = getDIEStringAttr(C, dwarf::DW_AT_name);
      assert(!Name.empty() &&
             "Base types referenced from DW_OP_convert should have a name");
      hashNestedType(C, Name);
    } else
      Hash.update((uint64_t)V.getDIEInteger().getValue());
}

// Hash the contents of a loclistptr class.
void DIEHash::hashLocList(const DIELocList &LocList) {
  HashingByteStreamer Streamer(*this);
  DwarfDebug &DD = *AP->getDwarfDebug();
  const DebugLocStream &Locs = DD.getDebugLocs();
  const DebugLocStream::List &List = Locs.getList(LocList.getValue());
  for (const DebugLocStream::Entry &Entry : Locs.getEntries(List))
    DD.emitDebugLocEntry(Streamer, Entry, List.CU);
}

// Hash an individual attribute \param Attr based on the type of attribute and
// the form.
void DIEHash::hashAttribute(const DIEValue &Value, dwarf::Tag Tag) {
  dwarf::Attribute Attribute = Value.getAttribute();

  // Other attribute values use the letter 'A' as the marker, and the value
  // consists of the form code (encoded as an unsigned LEB128 value) followed by
  // the encoding of the value according to the form code. To ensure
  // reproducibility of the signature, the set of forms used in the signature
  // computation is limited to the following: DW_FORM_sdata, DW_FORM_flag,
  // DW_FORM_string, and DW_FORM_block.

  switch (Value.getType()) {
  case DIEValue::isNone:
    llvm_unreachable("Expected valid DIEValue");

    // 7.27 Step 3
    // ... An attribute that refers to another type entry T is processed as
    // follows:
  case DIEValue::isEntry:
    hashDIEEntry(Attribute, Tag, Value.getDIEEntry().getEntry());
    break;
  case DIEValue::isInteger: {
    addULEB128('A');
    addULEB128(Attribute);
    switch (Value.getForm()) {
    case dwarf::DW_FORM_data1:
    case dwarf::DW_FORM_data2:
    case dwarf::DW_FORM_data4:
    case dwarf::DW_FORM_data8:
    case dwarf::DW_FORM_udata:
    case dwarf::DW_FORM_sdata:
      addULEB128(dwarf::DW_FORM_sdata);
      addSLEB128((int64_t)Value.getDIEInteger().getValue());
      break;
    // DW_FORM_flag_present is just flag with a value of one. We still give it a
    // value so just use the value.
    case dwarf::DW_FORM_flag_present:
    case dwarf::DW_FORM_flag:
      addULEB128(dwarf::DW_FORM_flag);
      addULEB128((int64_t)Value.getDIEInteger().getValue());
      break;
    default:
      llvm_unreachable("Unknown integer form!");
    }
    break;
  }
  case DIEValue::isString:
    addULEB128('A');
    addULEB128(Attribute);
    addULEB128(dwarf::DW_FORM_string);
    addString(Value.getDIEString().getString());
    break;
  case DIEValue::isInlineString:
    addULEB128('A');
    addULEB128(Attribute);
    addULEB128(dwarf::DW_FORM_string);
    addString(Value.getDIEInlineString().getString());
    break;
  case DIEValue::isBlock:
  case DIEValue::isLoc:
  case DIEValue::isLocList:
    addULEB128('A');
    addULEB128(Attribute);
    addULEB128(dwarf::DW_FORM_block);
    if (Value.getType() == DIEValue::isBlock) {
      addULEB128(Value.getDIEBlock().computeSize(AP->getDwarfFormParams()));
      hashBlockData(Value.getDIEBlock().values());
    } else if (Value.getType() == DIEValue::isLoc) {
      addULEB128(Value.getDIELoc().computeSize(AP->getDwarfFormParams()));
      hashBlockData(Value.getDIELoc().values());
    } else {
      // We could add the block length, but that would take
      // a bit of work and not add a lot of uniqueness
      // to the hash in some way we could test.
      hashLocList(Value.getDIELocList());
    }
    break;
    // FIXME: It's uncertain whether or not we should handle this at the moment.
  case DIEValue::isExpr:
  case DIEValue::isLabel:
  case DIEValue::isBaseTypeRef:
  case DIEValue::isDelta:
  case DIEValue::isAddrOffset:
    llvm_unreachable("Add support for additional value types.");
  }
}

// Go through the attributes from \param Attrs in the order specified in 7.27.4
// and hash them.
void DIEHash::hashAttributes(const DIEAttrs &Attrs, dwarf::Tag Tag) {
#define HANDLE_DIE_HASH_ATTR(NAME)                                             \
  {                                                                            \
    if (Attrs.NAME)                                                           \
      hashAttribute(Attrs.NAME, Tag);                                         \
  }
#include "DIEHashAttributes.def"
  // FIXME: Add the extended attributes.
}

// Add all of the attributes for \param Die to the hash.
void DIEHash::addAttributes(const DIE &Die) {
  DIEAttrs Attrs = {};
  collectAttributes(Die, Attrs);
  hashAttributes(Attrs, Die.getTag());
}

void DIEHash::hashNestedType(const DIE &Die, StringRef Name) {
  // 7.27 Step 7
  // ... append the letter 'S',
  addULEB128('S');

  // the tag of C,
  addULEB128(Die.getTag());

  // and the name.
  addString(Name);
}

// Compute the hash of a DIE. This is based on the type signature computation
// given in section 7.27 of the DWARF4 standard. It is the md5 hash of a
// flattened description of the DIE.
void DIEHash::computeHash(const DIE &Die) {
  // Append the letter 'D', followed by the DWARF tag of the DIE.
  addULEB128('D');
  addULEB128(Die.getTag());

  // Add each of the attributes of the DIE.
  addAttributes(Die);

  // Then hash each of the children of the DIE.
  for (const auto &C : Die.children()) {
    // 7.27 Step 7
    // If C is a nested type entry or a member function entry, ...
    if (isType(C.getTag()) || (C.getTag() == dwarf::DW_TAG_subprogram && isType(C.getParent()->getTag()))) {
      StringRef Name = getDIEStringAttr(C, dwarf::DW_AT_name);
      // ... and has a DW_AT_name attribute
      if (!Name.empty()) {
        hashNestedType(C, Name);
        continue;
      }
    }
    computeHash(C);
  }

  // Following the last (or if there are no children), append a zero byte.
  Hash.update(ArrayRef((uint8_t)'\0'));
}

/// This is based on the type signature computation given in section 7.27 of the
/// DWARF4 standard. It is an md5 hash of the flattened description of the DIE
/// with the inclusion of the full CU and all top level CU entities.
// TODO: Initialize the type chain at 0 instead of 1 for CU signatures.
uint64_t DIEHash::computeCUSignature(StringRef DWOName, const DIE &Die) {
  Numbering.clear();
  Numbering[&Die] = 1;

  if (!DWOName.empty())
    Hash.update(DWOName);
  // Hash the DIE.
  computeHash(Die);

  // Now return the result.
  MD5::MD5Result Result;
  Hash.final(Result);

  // ... take the least significant 8 bytes and return those. Our MD5
  // implementation always returns its results in little endian, so we actually
  // need the "high" word.
  return Result.high();
}

/// This is based on the type signature computation given in section 7.27 of the
/// DWARF4 standard. It is an md5 hash of the flattened description of the DIE
/// with the inclusion of additional forms not specifically called out in the
/// standard.
uint64_t DIEHash::computeTypeSignature(const DIE &Die) {
  Numbering.clear();
  Numbering[&Die] = 1;

  if (const DIE *Parent = Die.getParent())
    addParentContext(*Parent);

  // Hash the DIE.
  computeHash(Die);

  // Now return the result.
  MD5::MD5Result Result;
  Hash.final(Result);

  // ... take the least significant 8 bytes and return those. Our MD5
  // implementation always returns its results in little endian, so we actually
  // need the "high" word.
  return Result.high();
}
