// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- mode: C++ -*-
//
// Copyright 2021-2025 Google LLC
//
// Licensed under the Apache License v2.0 with LLVM Exceptions (the
// "License"); you may not use this file except in compliance with the
// License.  You may obtain a copy of the License at
//
//     https://llvm.org/LICENSE.txt
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Giuliano Procida
// Author: Ignes Simeonova

#include "abigail_reader.h"

#include <fcntl.h>

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <ios>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <sstream>
#include <string>
#include <string_view>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>

#include <libxml/globals.h>  // xmlFree moves to xmlmemory.h later
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlstring.h>
#include "error.h"
#include "file_descriptor.h"
#include "graph.h"
#include "runtime.h"
#include "scope.h"
#include "type_normalisation.h"

namespace stg {
namespace abixml {

namespace {

// Cast a libxml string to C string and present it as a string_view.
std::string_view FromLibxml(const xmlChar* str) {
  return reinterpret_cast<const char*>(str);
}

// Cast a C string to a libxml string.
const xmlChar* ToLibxml(const char* str) {
  return reinterpret_cast<const xmlChar*>(str);
}

// Get the name of an XML element.
std::string_view GetName(xmlNodePtr element) {
  return FromLibxml(element->name);
}

void CheckName(const char* name, xmlNodePtr element) {
  const auto element_name = GetName(element);
  if (element_name != name) {
    Die() << "expected element '" << name
          << "' but got '" << element_name << "'";
  }
}

xmlNodePtr Child(xmlNodePtr node) {
  return node->children;
}

xmlNodePtr Next(xmlNodePtr node) {
  return node->next;
}

xmlNodePtr GetOnlyChild(xmlNodePtr element) {
  const xmlNodePtr child = Child(element);
  if (child == nullptr || Next(child) != nullptr) {
    Die() << "element '" << GetName(element) << "' without exactly one child";
  }
  return child;
}

// Get an optional attribute.
std::optional<std::string> GetAttribute(xmlNodePtr node, const char* name) {
  std::optional<std::string> result;
  xmlChar* attribute = xmlGetProp(node, ToLibxml(name));
  if (attribute) {
    result.emplace(FromLibxml(attribute));
    xmlFree(attribute);
  }
  return result;
}

// Get an attribute.
std::string GetAttributeOrDie(xmlNodePtr node, const char* name) {
  xmlChar* attribute = xmlGetProp(node, ToLibxml(name));
  if (!attribute) {
    Die() << "element '" << GetName(node)
          << "' missing attribute '" << name << "'";
  }
  const std::string result(FromLibxml(attribute));
  xmlFree(attribute);
  return result;
}

// Set an attribute value.
void SetAttribute(xmlNodePtr node, const char* name, const std::string& value) {
  xmlSetProp(node, ToLibxml(name), ToLibxml(value.c_str()));
}

// Unset an attribute value.
void UnsetAttribute(xmlNodePtr node, const char* name) {
  xmlUnsetProp(node, ToLibxml(name));
}

// Remove a node and free its storage.
void RemoveNode(xmlNodePtr node) {
  xmlUnlinkNode(node);
  xmlFreeNode(node);
}

// Move a node to be the last child of another.
void MoveNode(xmlNodePtr node, xmlNodePtr destination) {
  xmlUnlinkNode(node);
  xmlAddChild(destination, node);
}

template <typename T>
std::optional<T> Parse(const std::string& value) {
  T result;
  std::istringstream is(value);
  is >> std::noskipws >> result;
  if (is && is.eof()) {
    return {result};
  }
  return {};
}

template <>
std::optional<bool> Parse<bool>(const std::string& value) {
  if (value == "yes") {
    return {true};
  } else if (value == "no") {
    return {false};
  }
  return {};
}

template <>
std::optional<ElfSymbol::SymbolType> Parse<ElfSymbol::SymbolType>(
    const std::string& value) {
  if (value == "no-type") {
    return {ElfSymbol::SymbolType::NOTYPE};
  } else if (value == "object-type") {
    return {ElfSymbol::SymbolType::OBJECT};
  } else if (value == "func-type") {
    return {ElfSymbol::SymbolType::FUNCTION};
  } else if (value == "common-type") {
    return {ElfSymbol::SymbolType::COMMON};
  } else if (value == "tls-type") {
    return {ElfSymbol::SymbolType::TLS};
  } else if (value == "gnu-ifunc-type") {
    return {ElfSymbol::SymbolType::GNU_IFUNC};
  }
  return {};
}

template <>
std::optional<ElfSymbol::Binding> Parse<ElfSymbol::Binding>(
    const std::string& value) {
  if (value == "global-binding") {
    return {ElfSymbol::Binding::GLOBAL};
  } else if (value == "local-binding") {
    return {ElfSymbol::Binding::LOCAL};
  } else if (value == "weak-binding") {
    return {ElfSymbol::Binding::WEAK};
  } else if (value == "gnu-unique-binding") {
    return {ElfSymbol::Binding::GNU_UNIQUE};
  }
  return {};
}

template <>
std::optional<ElfSymbol::Visibility> Parse<ElfSymbol::Visibility>(
    const std::string& value) {
  if (value == "default-visibility") {
    return {ElfSymbol::Visibility::DEFAULT};
  } else if (value == "protected-visibility") {
    return {ElfSymbol::Visibility::PROTECTED};
  } else if (value == "hidden-visibility") {
    return {ElfSymbol::Visibility::HIDDEN};
  } else if (value == "internal-visibility") {
    return {ElfSymbol::Visibility::INTERNAL};
  }
  return {};
}

template <>
std::optional<ElfSymbol::CRC> Parse<ElfSymbol::CRC>(const std::string& value) {
  uint32_t number;
  std::istringstream is(value);
  is >> std::noskipws >> std::hex >> number;
  if (is && is.eof()) {
    return std::make_optional<ElfSymbol::CRC>(number);
  }
  return std::nullopt;
}

template <typename T>
T GetParsedValueOrDie(xmlNodePtr element, const char* name,
                      const std::string& value, const std::optional<T>& parse) {
  if (parse) {
    return *parse;
  }
  Die() << "element '" << GetName(element)
        << "' has attribute '" << name
        << "' with bad value '" << value << "'";
}

template <typename T>
T ReadAttributeOrDie(xmlNodePtr element, const char* name) {
  const auto value = GetAttributeOrDie(element, name);
  return GetParsedValueOrDie(element, name, value, Parse<T>(value));
}

template <typename T>
std::optional<T> ReadAttribute(xmlNodePtr element, const char* name) {
  const auto value = GetAttribute(element, name);
  if (value) {
    return {GetParsedValueOrDie(element, name, *value, Parse<T>(*value))};
  }
  return {};
}

template <typename T>
T ReadAttribute(xmlNodePtr element, const char* name, const T& default_value) {
  const auto value = GetAttribute(element, name);
  if (value) {
    return GetParsedValueOrDie(element, name, *value, Parse<T>(*value));
  }
  return default_value;
}

template <typename T>
T ReadAttribute(xmlNodePtr element, const char* name,
                std::function<std::optional<T>(const std::string&)> parse) {
  const auto value = GetAttributeOrDie(element, name);
  return GetParsedValueOrDie(element, name, value, parse(value));
}

// Remove non-element nodes, recursively.
//
// This simplifies subsequent manipulation. This should only remove comment,
// text and possibly CDATA nodes.
void StripNonElements(xmlNodePtr node) {
  switch (node->type) {
    case XML_COMMENT_NODE:
    case XML_TEXT_NODE:
    case XML_CDATA_SECTION_NODE:
      RemoveNode(node);
      break;
    case XML_ELEMENT_NODE: {
      xmlNodePtr child = Child(node);
      while (child) {
        const xmlNodePtr next = Next(child);
        StripNonElements(child);
        child = next;
      }
      break;
    }
    default:
      Die() << "unexpected XML node type: " << node->type;
  }
}

// Determine whether one XML element is a subtree of another, and optionally,
// actually equal to it.
bool SubOrEqualTree(bool also_equal, xmlNodePtr left, xmlNodePtr right) {
  // Node names must match.
  const auto left_name = GetName(left);
  const auto right_name = GetName(right);
  if (left_name != right_name) {
    return false;
  }

  // Attributes may be missing on the left, but must match otherwise.
  size_t left_attributes = 0;
  for (auto* p = left->properties; p; p = p->next) {
    ++left_attributes;
    const auto attribute = FromLibxml(p->name);
    const char* attribute_name = attribute.data();
    const auto left_value = GetAttributeOrDie(left, attribute_name);
    const auto right_value = GetAttribute(right, attribute_name);
    if (!right_value || left_value != right_value.value()) {
      return false;
    }
  }
  // To also be equal, we just need to check the counts are the same.
  if (also_equal) {
    size_t right_attributes = 0;
    for (auto* p = right->properties; p; p = p->next) {
      ++right_attributes;
    }
    if (left_attributes != right_attributes) {
      return false;
    }
  }

  // The left subelements must be a subsequence of the right ones and to also be
  // equal, we must not have skipped any right ones.
  xmlNodePtr left_child = Child(left);
  xmlNodePtr right_child = Child(right);
  while (left_child != nullptr && right_child != nullptr) {
    if (SubOrEqualTree(also_equal, left_child, right_child)) {
      left_child = Next(left_child);
    } else if (also_equal) {
      return false;
    }
    right_child = Next(right_child);
  }
  return left_child == nullptr && (right_child == nullptr || !also_equal);
}

}  // namespace

// Determine whether one XML element is a subtree of another.
bool SubTree(xmlNodePtr left, xmlNodePtr right) {
  return SubOrEqualTree(false, left, right);
}

// Determine whether one XML element is the same as another.
bool EqualTree(xmlNodePtr left, xmlNodePtr right) {
  return SubOrEqualTree(true, left, right);
}

// Find a maximal XML element if one exists.
std::optional<size_t> MaximalTree(const std::vector<xmlNodePtr>& nodes) {
  if (nodes.empty()) {
    return std::nullopt;
  }

  // Find a potentially maximal candidate by scanning through and retaining the
  // new node if it's a supertree of the current candidate.
  const auto count = nodes.size();
  std::vector<bool> ok(count);
  size_t candidate = 0;
  ok[candidate] = true;
  for (size_t ix = 1; ix < count; ++ix) {
    if (SubTree(nodes[candidate], nodes[ix])) {
      candidate = ix;
      ok[candidate] = true;
    }
  }

  // Verify the candidate is indeed maximal by comparing it with the nodes not
  // already known to be subtrees of it.
  const auto& candidate_node = nodes[candidate];
  for (size_t ix = 0; ix < count; ++ix) {
    const auto& node = nodes[ix];
    if (!ok[ix] && !SubTree(node, candidate_node)) {
      return std::nullopt;
    }
  }

  return std::make_optional(candidate);
}

namespace {

// Check if string_view is in an array.
template<size_t N>
bool Contains(const std::array<std::string_view, N>& haystack,
              std::string_view needle) {
  return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
}

// Remove source location attributes.
//
// This simplifies element comparison later.
void StripLocationInfo(xmlNodePtr node) {
  static const std::array<std::string_view, 7> has_location_info = {
    "class-decl",
    "enum-decl",
    "function-decl",
    "parameter",
    "typedef-decl",
    "union-decl",
    "var-decl"
  };

  if (Contains(has_location_info, GetName(node))) {
    UnsetAttribute(node, "filepath");
    UnsetAttribute(node, "line");
    UnsetAttribute(node, "column");
  }
  for (auto* child = Child(node); child; child = Next(child)) {
    StripLocationInfo(child);
  }
}

// Remove access attribute.
//
// This simplifies element comparison later in a very specific way: libabigail
// (possibly older versions) uses the access specifier for the type it's trying
// to "emit in scope", even for its containing types, making deduplicating types
// trickier. We don't care about access anyway, so just remove it everywhere.
void StripAccess(xmlNodePtr node) {
  static const std::array<std::string_view, 5> has_access = {
    "base-class",
    "data-member",
    "member-function",
    "member-template",
    "member-type",
  };

  if (Contains(has_access, GetName(node))) {
    UnsetAttribute(node, "access");
  }
  for (auto* child = Child(node); child; child = Next(child)) {
    StripAccess(child);
  }
}

// Elements corresponding to named types that can be anonymous or marked as
// unreachable by libabigail, so user-defined types, excepting typedefs.
const std::array<std::string_view, 3> kNamedTypes = {
  "class-decl",
  "enum-decl",
  "union-decl",
};

// Remove attributes emitted by abidw --load-all-types.
//
// With this invocation and if any user-defined types are deemed unreachable,
// libabigail will output a tracking-non-reachable-types attribute on top-level
// elements and an is-non-reachable attribute on each such type element.
//
// We have our own graph-theoretic notion of reachability and these attributes
// have no ABI relevance and can interfere with element comparisons.
void StripReachabilityAttributes(xmlNodePtr node) {
  const auto node_name = GetName(node);

  if (node_name == "abi-corpus-group" || node_name == "abi-corpus") {
    UnsetAttribute(node, "tracking-non-reachable-types");
  } else if (Contains(kNamedTypes, node_name)) {
    UnsetAttribute(node, "is-non-reachable");
  }

  for (auto* child = Child(node); child; child = Next(child)) {
    StripReachabilityAttributes(child);
  }
}

// Fix bad DWARF -> ELF links caused by size zero symbol confusion.
//
// libabigail used to be confused by these sorts of symbols, resulting in
// declarations pointing at the wrong ELF symbols:
//
// 573623: ffffffc0122383c0   256 OBJECT  GLOBAL DEFAULT   33 vm_node_stat
// 573960: ffffffc0122383c0     0 OBJECT  GLOBAL DEFAULT   33 vm_numa_stat
void FixBadDwarfElfLinks(xmlNodePtr root) {
  std::unordered_map<std::string, size_t> elf_links;

  // See which ELF symbol IDs have multiple declarations.
  const std::function<void(xmlNodePtr)> count = [&](xmlNodePtr node) {
    if (GetName(node) == "var-decl") {
      const auto symbol_id = GetAttribute(node, "elf-symbol-id");
      if (symbol_id) {
        ++elf_links[symbol_id.value()];
      }
    }

    for (auto* child = Child(node); child; child = Next(child)) {
      count(child);
    }
  };
  count(root);

  // Fix up likely bad links from DWARF declaration to ELF symbol.
  const std::function<void(xmlNodePtr)> fix = [&](xmlNodePtr node) {
    if (GetName(node) == "var-decl") {
      const auto name = GetAttributeOrDie(node, "name");
      const auto mangled_name = GetAttribute(node, "mangled-name");
      const auto symbol_id = GetAttribute(node, "elf-symbol-id");
      if (mangled_name && symbol_id && name != symbol_id.value()
          && elf_links[symbol_id.value()] > 1) {
        if (mangled_name.value() == name) {
          Warn() << "fixing up ELF symbol for '" << name
                 << "' (was '" << symbol_id.value() << "')";
          SetAttribute(node, "elf-symbol-id", name);
        } else if (mangled_name.value() == symbol_id.value()) {
          Warn() << "fixing up mangled name and ELF symbol for '" << name
                 << "' (was '" << symbol_id.value() << "')";
          SetAttribute(node, "mangled-name", name);
          SetAttribute(node, "elf-symbol-id", name);
        }
      }
    }

    for (auto* child = Child(node); child; child = Next(child)) {
      fix(child);
    }
  };
  fix(root);
}

// Tidy anonymous types in various ways.
//
// 1. Normalise anonymous type names by dropping the name attribute.
//
// Anonymous type names take the form __anonymous_foo__N where foo is one of
// enum, struct or union and N is an optional numerical suffix. We don't care
// about these names but they may cause trouble when comparing elements.
//
// 2. Reanonymise anonymous types that have been given names.
//
// At some point abidw changed its behaviour given an anonymous type with a
// naming typedef. In addition to linking the typedef and type in both
// directions, the code now gives (some) anonymous types the same name as the
// typedef. This misrepresents the original types.
//
// Such types should be anonymous. We set is-anonymous and drop the name.
//
// 3. Discard naming typedef backlinks.
//
// The attribute naming-typedef-id is a backwards link from an anonymous type to
// the typedef that refers to it.
//
// We don't care about these attributes and they may cause comparison issues.
void TidyAnonymousTypes(xmlNodePtr node) {
  if (Contains(kNamedTypes, GetName(node))) {
    const bool is_anon = ReadAttribute<bool>(node, "is-anonymous", false);
    const auto naming_attribute = GetAttribute(node, "naming-typedef-id");
    if (is_anon) {
      UnsetAttribute(node, "name");
    } else if (naming_attribute) {
      SetAttribute(node, "is-anonymous", "yes");
      UnsetAttribute(node, "name");
    }
    if (naming_attribute) {
      UnsetAttribute(node, "naming-typedef-id");
    }
  }

  for (auto* child = Child(node); child; child = Next(child)) {
    TidyAnonymousTypes(child);
  }
}

// Remove duplicate members.
void RemoveDuplicateMembers(xmlNodePtr root) {
  std::vector<xmlNodePtr> types;

  // find all structs and unions
  std::function<void(xmlNodePtr)> dfs = [&](xmlNodePtr node) {
    const auto node_name = GetName(node);
    // preorder in case we delete a nested element
    for (auto* child = Child(node); child; child = Next(child)) {
      dfs(child);
    }
    if (node_name == "class-decl" || node_name == "union-decl") {
      types.push_back(node);
    }
  };
  dfs(root);

  for (const auto& node : types) {
    // partition members by node name
    std::map<std::string_view, std::vector<xmlNodePtr>> member_map;
    for (auto* child = Child(node); child; child = Next(child)) {
      member_map[GetName(child)].push_back(child);
    }
    // for each kind of member...
    for (auto& [name, members] : member_map) {
      // ... remove identical duplicate members - O(n^2)
      for (size_t i = 0; i < members.size(); ++i) {
        xmlNodePtr& i_node = members[i];
        bool duplicate = false;
        for (size_t j = 0; j < i; ++j) {
          const xmlNodePtr& j_node = members[j];
          if (j_node != nullptr && EqualTree(i_node, j_node)) {
            duplicate = true;
            break;
          }
        }
        if (duplicate) {
          RemoveNode(i_node);
          i_node = nullptr;
        }
      }
    }
  }
}

// Eliminate non-conflicting / report conflicting duplicate definitions.
//
// XML elements representing types are sometimes emitted multiple times,
// identically. Also, member typedefs are sometimes emitted separately from
// their types, resulting in duplicate XML fragments.
//
// Both these issues can be resolved by first detecting duplicate occurrences of
// a given type id and then checking to see if there's an instance that subsumes
// the others, which can then be eliminated.
//
// This function eliminates exact type duplicates and duplicates where there is
// at least one maximal definition. It can report the remaining duplicate
// definitions.
//
// If a type has duplicate definitions in multiple namespace scopes or
// definitions with different effective names, these are considered to be
// *conflicting* duplicate definitions. TODO: update text
void HandleDuplicateTypes(xmlNodePtr root) {
  // Convenience typedef referring to a namespace scope.
  using namespace_scope = std::vector<std::string>;
  // map of type-id to pair of set of namespace scopes and vector of
  // xmlNodes
  std::unordered_map<
      std::string,
      std::pair<
          std::set<namespace_scope>,
          std::vector<xmlNodePtr>>> types;
  namespace_scope namespaces;

  // find all type occurrences
  std::function<void(xmlNodePtr)> dfs = [&](xmlNodePtr node) {
    const auto node_name = GetName(node);
    std::optional<std::string> namespace_name;
    if (node_name == "namespace-decl") {
      namespace_name = GetAttribute(node, "name");
    }
    if (namespace_name) {
      namespaces.push_back(namespace_name.value());
    }
    if (node_name == "abi-corpus-group"
        || node_name == "abi-corpus"
        || node_name == "abi-instr"
        || namespace_name) {
      for (auto* child = Child(node); child; child = Next(child)) {
        dfs(child);
      }
    } else {
      const auto id = GetAttribute(node, "id");
      if (id) {
        auto& info = types[id.value()];
        info.first.insert(namespaces);
        info.second.push_back(node);
      }
    }
    if (namespace_name) {
      namespaces.pop_back();
    }
  };
  dfs(root);

  for (const auto& [id, scopes_and_definitions] : types) {
    const auto& [scopes, definitions] = scopes_and_definitions;

    if (scopes.size() > 1) {
      Warn() << "conflicting scopes found for type '" << id << '\'';
      continue;
    }

    const auto possible_maximal = MaximalTree(definitions);
    if (possible_maximal) {
      // Remove all but the maximal definition.
      const size_t maximal = possible_maximal.value();
      for (size_t ix = 0; ix < definitions.size(); ++ix) {
        if (ix != maximal) {
          RemoveNode(definitions[ix]);
        }
      }
      continue;
    }

    // As a rare alternative, check for a stray anonymous member that has been
    // separated from the main definition.
    size_t strays = 0;
    std::optional<size_t> stray;
    std::optional<size_t> non_stray;
    for (size_t ix = 0; ix < definitions.size(); ++ix) {
      auto node = definitions[ix];
      auto member = Child(node);
      if (member && !Next(member) && GetName(member) == "data-member") {
        auto decl = Child(member);
        if (decl && !Next(decl) && GetName(decl) == "var-decl") {
          auto name = GetAttribute(decl, "name");
          if (name && name.value().empty()) {
            ++strays;
            stray = ix;
            continue;
          }
        }
      }
      non_stray = ix;
    }
    if (strays + 1 == definitions.size() && stray.has_value()
        && non_stray.has_value()) {
      const auto stray_index = stray.value();
      const auto non_stray_index = non_stray.value();
      bool good = true;
      for (size_t ix = 0; ix < definitions.size(); ++ix) {
        if (ix == stray_index || ix == non_stray_index) {
          continue;
        }
        if (EqualTree(definitions[stray_index], definitions[ix])) {
          // it doesn't hurt if we remove exact duplicates and then fail
          RemoveNode(definitions[ix]);
        } else {
          good = false;
          break;
        }
      }
      if (good) {
        MoveNode(Child(definitions[stray_index]), definitions[non_stray_index]);
        RemoveNode(definitions[stray_index]);
        continue;
      }
    }

    Warn() << "unresolvable duplicate definitions found for type '" << id
           << '\'';
  }
}

}  // namespace

// Remove XML nodes and attributes that are neither used or wanted.
void Clean(xmlNodePtr root) {
  // Strip non-element nodes to simplify other operations.
  StripNonElements(root);

  // Strip location information.
  StripLocationInfo(root);

  // Strip access.
  StripAccess(root);

  // Strip reachability attributes.
  StripReachabilityAttributes(root);
}

namespace {

// Transform XML elements to improve their semantics.
void Tidy(xmlNodePtr root) {
  // Fix bad ELF symbol links
  FixBadDwarfElfLinks(root);

  // Normalise anonymous type names.
  // Reanonymise anonymous types.
  // Discard naming typedef backlinks.
  TidyAnonymousTypes(root);

  // Remove duplicate members.
  RemoveDuplicateMembers(root);

  // Eliminate complete duplicates and extra fragments of types.
  // Report conflicting duplicate definitions.
  // Record whether there are conflicting duplicate definitions.
  HandleDuplicateTypes(root);
}

std::optional<uint64_t> ParseLength(const std::string& value) {
  if (value == "infinite" || value == "unknown") {
    return {0};
  }
  return Parse<uint64_t>(value);
}

std::optional<PointerReference::Kind> ParseReferenceKind(
    const std::string& value) {
  if (value == "lvalue") {
    return {PointerReference::Kind::LVALUE_REFERENCE};
  } else if (value == "rvalue") {
    return {PointerReference::Kind::RVALUE_REFERENCE};
  }
  return {};
}

// Parser for libabigail's ABI XML format, creating a Symbol-Type Graph.
//
// On construction Abigail consumes a libxml node tree and builds a graph.
//
// Note that the core parser sees a "clean and tidy" XML document due to
// preprocessing that simplifies the XML and resolves several issues. One
// notable exception is that duplicate nodes may still remain.
//
// The main producer of ABI XML is abidw. The format has no formal specification
// and has very limited semantic versioning. This parser makes no attempt to
// support or correct for deficiencies in older versions of the format.
//
// The parser detects and will abort on the presence of unexpected elements.
//
// The parser ignores attributes it doesn't care about, including member access
// specifiers and (meaningless) type ids on array dimensions.
//
// The STG IR and libabigail ABI XML models diverge in some ways. The parser has
// to do extra work for each of these, as follows.
//
// 0. XML uses type and symbol ids to link together elements. These become edges
// in the graph between symbols and types and between types and types. Dangling
// type references will cause an abort. libabigail is much more relaxed about
// symbols without type information and these are modelled as such.
//
// 1. XML function declarations have in-line types. The parser creates
// free-standing types on-the-fly. A useful space optimisation might be to
// prevent duplicate creation of such types.
//
// 2. Variadic parameters are currently flagged with an XML attribute. A
// variadic type node is created on demand and will be shared by all such
// paramerters.
//
// 3. XML symbols and aliases have a rather poor repesentation with aliases
// represented as comma-separated attribute values. Aliases are resolved in a
// post-processing phase.
//
// 4. XML anonymous types may also have names, these are ignored.
class Abigail {
 public:
  explicit Abigail(Graph& graph);
  Id ProcessRoot(xmlNodePtr root);

 private:
  struct SymbolInfo {
    std::string name;
    std::optional<ElfSymbol::VersionInfo> version_info;
    xmlNodePtr node;
  };

  // Map from libabigail type ids to STG node ids; except for the type of
  // variadic parameters.
  Maker<std::string> maker_;
  // The STG IR uses a distinct node type for the variadic parameter type; if
  // allocated, this is its STG node id.
  std::optional<Id> variadic_;

  // symbol id to symbol information
  std::unordered_map<std::string, SymbolInfo> symbol_info_map_;
  // alias symbol id to main symbol id
  std::unordered_map<std::string, std::string> alias_to_main_;
  // libabigail decorates certain declarations with symbol ids; this is the
  // mapping from symbol id to the corresponding type and full name.
  std::unordered_map<std::string, std::pair<Id, std::string>>
      symbol_id_and_full_name_;

  // Full name of the current scope.
  Scope scope_;

  Id GetEdge(xmlNodePtr element);
  Id GetVariadic();
  Function MakeFunctionType(xmlNodePtr function);

  void ProcessCorpusGroup(xmlNodePtr group);
  void ProcessCorpus(xmlNodePtr corpus);
  void ProcessSymbols(xmlNodePtr symbols);
  void ProcessSymbol(xmlNodePtr symbol);

  bool ProcessUserDefinedType(std::string_view name, const std::string& id,
                              xmlNodePtr decl);
  void ProcessScope(xmlNodePtr scope);

  void ProcessInstr(xmlNodePtr instr);
  void ProcessNamespace(xmlNodePtr scope);

  Id ProcessDecl(bool is_variable, xmlNodePtr decl);

  void ProcessFunctionType(const std::string& id, xmlNodePtr function);
  void ProcessTypedef(const std::string& id, xmlNodePtr type_definition);
  void ProcessPointer(const std::string& id, bool is_pointer,
                      xmlNodePtr pointer);
  void ProcessQualified(const std::string& id, xmlNodePtr qualified);
  void ProcessArray(const std::string& id, xmlNodePtr array);
  void ProcessTypeDecl(const std::string& id, xmlNodePtr type_decl);
  void ProcessStructUnion(const std::string& id, bool is_struct,
                          xmlNodePtr struct_union);
  void ProcessEnum(const std::string& id, xmlNodePtr enumeration);

  Id ProcessBaseClass(xmlNodePtr base_class);
  std::optional<Id> ProcessDataMember(bool is_struct, xmlNodePtr data_member);
  void ProcessMemberFunction(std::vector<Id>& methods, xmlNodePtr method);
  void ProcessMemberType(xmlNodePtr member_type);

  Id BuildSymbol(const SymbolInfo& info,
                 std::optional<Id> type_id,
                 const std::optional<std::string>& name);
  Id BuildSymbols();
};

Abigail::Abigail(Graph& graph) : maker_(graph) {}

Id Abigail::GetEdge(xmlNodePtr element) {
  return maker_.Get(GetAttributeOrDie(element, "type-id"));
}

Id Abigail::GetVariadic() {
  if (!variadic_) {
    variadic_ = {maker_.Add<Special>(Special::Kind::VARIADIC)};
  }
  return *variadic_;
}

Function Abigail::MakeFunctionType(xmlNodePtr function) {
  std::vector<Id> parameters;
  std::optional<Id> return_type;
  for (auto* child = Child(function); child; child = Next(child)) {
    const auto child_name = GetName(child);
    if (return_type) {
      Die() << "unexpected element after return-type";
    }
    if (child_name == "parameter") {
      const auto is_variadic = ReadAttribute<bool>(child, "is-variadic", false);
      parameters.push_back(is_variadic ? GetVariadic() : GetEdge(child));
    } else if (child_name == "return") {
      return_type = {GetEdge(child)};
    } else {
      Die() << "unrecognised " << GetName(function)
            << " child element '" << child_name << "'";
    }
  }
  if (!return_type) {
    Die() << "missing return-type";
  }
  return {*return_type, parameters};
}

Id Abigail::ProcessRoot(xmlNodePtr root) {
  Clean(root);
  Tidy(root);
  const auto name = GetName(root);
  if (name == "abi-corpus-group") {
    ProcessCorpusGroup(root);
  } else if (name == "abi-corpus") {
    ProcessCorpus(root);
  } else {
    Die() << "unrecognised root element '" << name << "'";
  }
  return BuildSymbols();
}

void Abigail::ProcessCorpusGroup(xmlNodePtr group) {
  for (auto* corpus = Child(group); corpus; corpus = Next(corpus)) {
    CheckName("abi-corpus", corpus);
    ProcessCorpus(corpus);
  }
}

void Abigail::ProcessCorpus(xmlNodePtr corpus) {
  for (auto* element = Child(corpus); element; element = Next(element)) {
    const auto name = GetName(element);
    if (name == "elf-function-symbols" || name == "elf-variable-symbols") {
      ProcessSymbols(element);
    } else if (name == "elf-needed") {
      // ignore this
    } else if (name == "abi-instr") {
      ProcessInstr(element);
    } else {
      Die() << "unrecognised abi-corpus child element '" << name << "'";
    }
  }
}

void Abigail::ProcessSymbols(xmlNodePtr symbols) {
  for (auto* element = Child(symbols); element; element = Next(element)) {
    CheckName("elf-symbol", element);
    ProcessSymbol(element);
  }
}

void Abigail::ProcessSymbol(xmlNodePtr symbol) {
  // Symbol processing is done in two parts. In this first part, we parse just
  // enough XML attributes to generate a symbol id and determine any aliases.
  // Symbol ids in this format can be found in elf-symbol alias attributes and
  // in {var,function}-decl elf-symbol-id attributes.
  const auto name = GetAttributeOrDie(symbol, "name");
  const auto version =
      ReadAttribute<std::string>(symbol, "version", std::string());
  const bool is_default_version =
      ReadAttribute<bool>(symbol, "is-default-version", false);
  const auto alias = GetAttribute(symbol, "alias");

  std::string elf_symbol_id = name;
  std::optional<ElfSymbol::VersionInfo> version_info;
  if (!version.empty()) {
    version_info = ElfSymbol::VersionInfo{is_default_version, version};
    elf_symbol_id += VersionInfoToString(*version_info);
  }

  Check(symbol_info_map_
            .emplace(elf_symbol_id, SymbolInfo{name, version_info, symbol})
            .second)
      << "multiple symbols with id " << elf_symbol_id;

  if (alias) {
    std::istringstream is(*alias);
    std::string item;
    while (std::getline(is, item, ',')) {
      Check(alias_to_main_.insert({item, elf_symbol_id}).second)
          << "multiple aliases with id " << item;
    }
  }
}

bool Abigail::ProcessUserDefinedType(
    std::string_view name, const std::string& id, xmlNodePtr decl) {
  if (name == "typedef-decl") {
    ProcessTypedef(id, decl);
  } else if (name == "class-decl") {
    ProcessStructUnion(id, true, decl);
  } else if (name == "union-decl") {
    ProcessStructUnion(id, false, decl);
  } else if (name == "enum-decl") {
    ProcessEnum(id, decl);
  } else {
    return false;
  }
  return true;
}

void Abigail::ProcessScope(xmlNodePtr scope) {
  for (auto* element = Child(scope); element; element = Next(element)) {
    const auto name = GetName(element);
    const auto maybe_id = GetAttribute(element, "id");
    // all type elements have "id", all non-types do not
    if (maybe_id) {
      const auto& id = *maybe_id;
      if (name == "function-type") {
        ProcessFunctionType(id, element);
      } else if (name == "pointer-type-def") {
        ProcessPointer(id, true, element);
      } else if (name == "reference-type-def") {
        ProcessPointer(id, false, element);
      } else if (name == "qualified-type-def") {
        ProcessQualified(id, element);
      } else if (name == "array-type-def") {
        ProcessArray(id, element);
      } else if (name == "type-decl") {
        ProcessTypeDecl(id, element);
      } else if (!ProcessUserDefinedType(name, id, element)) {
        Die() << "bad abi-instr type child element '" << name << "'";
      }
    } else {
      if (name == "var-decl") {
        ProcessDecl(true, element);
      } else if (name == "function-decl") {
        ProcessDecl(false, element);
      } else if (name == "namespace-decl") {
        ProcessNamespace(element);
      } else {
        Die() << "bad abi-instr non-type child element '" << name << "'";
      }
    }
  }
}

void Abigail::ProcessInstr(xmlNodePtr instr) {
  ProcessScope(instr);
}

void Abigail::ProcessNamespace(xmlNodePtr scope) {
  const auto name = GetAttributeOrDie(scope, "name");
  const PushScopeName push_scope_name(scope_, "namespace", name);
  ProcessScope(scope);
}

Id Abigail::ProcessDecl(bool is_variable, xmlNodePtr decl) {
  const auto name = scope_.name + GetAttributeOrDie(decl, "name");
  const auto symbol_id = GetAttribute(decl, "elf-symbol-id");
  const auto type = is_variable ? GetEdge(decl)
                                : maker_.Add<Function>(MakeFunctionType(decl));
  if (symbol_id) {
    // There's a link to an ELF symbol.
    const auto [it, inserted] = symbol_id_and_full_name_.emplace(
        *symbol_id, std::make_pair(type, name));
    if (!inserted) {
      Die() << "duplicate type for '" << *symbol_id << "'";
    }
  }
  return type;
}

void Abigail::ProcessFunctionType(const std::string& id, xmlNodePtr function) {
  maker_.MaybeSet<Function>(id, MakeFunctionType(function));
}

void Abigail::ProcessTypedef(const std::string& id,
                             xmlNodePtr type_definition) {
  const auto name = scope_.name + GetAttributeOrDie(type_definition, "name");
  const auto type = GetEdge(type_definition);
  maker_.MaybeSet<Typedef>(id, name, type);
}

void Abigail::ProcessPointer(const std::string& id, bool is_pointer,
                             xmlNodePtr pointer) {
  const auto type = GetEdge(pointer);
  const auto kind = is_pointer ? PointerReference::Kind::POINTER
                               : ReadAttribute<PointerReference::Kind>(
                                     pointer, "kind", &ParseReferenceKind);
  maker_.MaybeSet<PointerReference>(id, kind, type);
}

void Abigail::ProcessQualified(const std::string& id, xmlNodePtr qualified) {
  std::vector<Qualifier> qualifiers;
  // Do these in reverse order so we get CVR ordering.
  if (ReadAttribute<bool>(qualified, "restrict", false)) {
    qualifiers.push_back(Qualifier::RESTRICT);
  }
  if (ReadAttribute<bool>(qualified, "volatile", false)) {
    qualifiers.push_back(Qualifier::VOLATILE);
  }
  if (ReadAttribute<bool>(qualified, "const", false)) {
    qualifiers.push_back(Qualifier::CONST);
  }
  Check(!qualifiers.empty()) << "qualified-type-def has no qualifiers";
  // Handle multiple qualifiers by unconditionally adding as new nodes all but
  // the last qualifier which is set into place.
  auto type = GetEdge(qualified);
  auto count = qualifiers.size();
  for (auto qualifier : qualifiers) {
    --count;
    const Qualified node(qualifier, type);
    if (count) {
      type = maker_.Add<Qualified>(node);
    } else {
      maker_.MaybeSet<Qualified>(id, node);
    }
  }
}

void Abigail::ProcessArray(const std::string& id, xmlNodePtr array) {
  std::vector<size_t> dimensions;
  for (auto* child = Child(array); child; child = Next(child)) {
    CheckName("subrange", child);
    const auto length = ReadAttribute<uint64_t>(child, "length", &ParseLength);
    dimensions.push_back(length);
  }
  Check(!dimensions.empty()) << "array-type-def element has no children";
  // int[M][N] means array[M] of array[N] of int
  //
  // We need to chain a bunch of types together:
  //
  // id = array[n] of id = ... = array[n] of id
  //
  // where the first id is the new type in slot ix
  // and the last id is the old type in slot type
  //
  // Use the same approach as for qualifiers.
  auto type = GetEdge(array);
  auto count = dimensions.size();
  for (auto it = dimensions.crbegin(); it != dimensions.crend(); ++it) {
    --count;
    const auto size = *it;
    const Array node(size, type);
    if (count) {
      type = maker_.Add<Array>(node);
    } else {
      maker_.MaybeSet<Array>(id, node);
    }
  }
}

void Abigail::ProcessTypeDecl(const std::string& id, xmlNodePtr type_decl) {
  const auto name = scope_.name + GetAttributeOrDie(type_decl, "name");
  const auto bits = ReadAttribute<size_t>(type_decl, "size-in-bits", 0);
  if (bits % 8) {
    Die() << "size-in-bits is not a multiple of 8";
  }
  const auto bytes = bits / 8;

  if (name == "void") {
    maker_.MaybeSet<Special>(id, Special::Kind::VOID);
  } else {
    // libabigail doesn't model encoding at all and we don't want to parse names
    // (which will not always work) in an attempt to reconstruct it.
    maker_.MaybeSet<Primitive>(id, name, /* encoding= */ std::nullopt, bytes);
  }
}

void Abigail::ProcessStructUnion(const std::string& id, bool is_struct,
                                 xmlNodePtr struct_union) {
  // Libabigail sometimes reports is-declaration-only but still provides some
  // child elements. So we check both things.
  const bool forward =
      ReadAttribute<bool>(struct_union, "is-declaration-only", false)
      && Child(struct_union) == nullptr;
  const auto kind = is_struct
                    ? StructUnion::Kind::STRUCT
                    : StructUnion::Kind::UNION;
  const bool is_anonymous =
      ReadAttribute<bool>(struct_union, "is-anonymous", false);
  const auto name =
      is_anonymous ? std::string() : GetAttributeOrDie(struct_union, "name");
  const auto full_name =
      is_anonymous ? std::string() : scope_.name + name;
  const PushScopeName push_scope_name(scope_, kind, name);
  if (forward) {
    maker_.MaybeSet<StructUnion>(id, kind, full_name);
    return;
  }
  const auto bits = ReadAttribute<size_t>(struct_union, "size-in-bits", 0);
  const auto bytes = (bits + 7) / 8;

  std::vector<Id> base_classes;
  std::vector<Id> methods;
  std::vector<Id> members;
  for (auto* child = Child(struct_union); child; child = Next(child)) {
    const auto child_name = GetName(child);
    if (child_name == "data-member") {
      if (const auto member = ProcessDataMember(is_struct, child)) {
        members.push_back(*member);
      }
    } else if (child_name == "member-type") {
      ProcessMemberType(child);
    } else if (child_name == "base-class") {
      base_classes.push_back(ProcessBaseClass(child));
    } else if (child_name == "member-function") {
      ProcessMemberFunction(methods, child);
    } else {
      Die() << "unrecognised " << kind << "-decl child element '" << child_name
            << "'";
    }
  }

  maker_.MaybeSet<StructUnion>(id, kind, full_name, bytes, base_classes,
                               methods, members);
}

void Abigail::ProcessEnum(const std::string& id, xmlNodePtr enumeration) {
  const bool forward =
      ReadAttribute<bool>(enumeration, "is-declaration-only", false);
  const auto name = ReadAttribute<bool>(enumeration, "is-anonymous", false)
                    ? std::string()
                    : scope_.name + GetAttributeOrDie(enumeration, "name");
  if (forward) {
    maker_.MaybeSet<Enumeration>(id, name);
    return;
  }

  const xmlNodePtr underlying = Child(enumeration);
  Check(underlying != nullptr) << "enum-decl has no child elements";
  CheckName("underlying-type", underlying);
  const auto type = GetEdge(underlying);

  Enumeration::Enumerators enumerators;
  for (auto* enumerator = Next(underlying); enumerator;
       enumerator = Next(enumerator)) {
    CheckName("enumerator", enumerator);
    const auto enumerator_name = GetAttributeOrDie(enumerator, "name");
    // libabigail currently supports anything that fits in an int64_t
    const auto enumerator_value =
        ReadAttributeOrDie<int64_t>(enumerator, "value");
    enumerators.emplace_back(enumerator_name, enumerator_value);
  }

  maker_.MaybeSet<Enumeration>(id, name, type, enumerators);
}

Id Abigail::ProcessBaseClass(xmlNodePtr base_class) {
  const auto& type = GetEdge(base_class);
  const auto offset =
      ReadAttributeOrDie<size_t>(base_class, "layout-offset-in-bits");
  const auto inheritance = ReadAttribute<bool>(base_class, "is-virtual", false)
                           ? BaseClass::Inheritance::VIRTUAL
                           : BaseClass::Inheritance::NON_VIRTUAL;
  return maker_.Add<BaseClass>(type, offset, inheritance);
}

std::optional<Id> Abigail::ProcessDataMember(bool is_struct,
                                             xmlNodePtr data_member) {
  const xmlNodePtr decl = GetOnlyChild(data_member);
  CheckName("var-decl", decl);
  if (ReadAttribute<bool>(data_member, "static", false)) {
    ProcessDecl(true, decl);
    return {};
  }

  const auto offset = is_struct
                      ? ReadAttributeOrDie<size_t>(data_member,
                                                   "layout-offset-in-bits")
                      : 0;
  const auto name = GetAttributeOrDie(decl, "name");
  const auto type = GetEdge(decl);

  // Note: libabigail does not model member size, yet
  return {maker_.Add<Member>(name, type, offset, 0)};
}

void Abigail::ProcessMemberFunction(std::vector<Id>& methods,
                                    xmlNodePtr method) {
  const xmlNodePtr decl = GetOnlyChild(method);
  CheckName("function-decl", decl);
  // ProcessDecl creates symbol references so must be called unconditionally.
  const auto type = ProcessDecl(false, decl);
  const auto vtable_offset = ReadAttribute<uint64_t>(method, "vtable-offset");
  if (vtable_offset) {
    static const std::string missing = "{missing}";
    const auto mangled_name = ReadAttribute(decl, "mangled-name", missing);
    const auto name = GetAttributeOrDie(decl, "name");
    methods.push_back(
        maker_.Add<Method>(mangled_name, name, vtable_offset.value(), type));
  }
}

void Abigail::ProcessMemberType(xmlNodePtr member_type) {
  const xmlNodePtr decl = GetOnlyChild(member_type);
  const auto id = GetAttributeOrDie(decl, "id");
  const auto name = GetName(decl);
  if (!ProcessUserDefinedType(name, id, decl)) {
    Die() << "unrecognised member-type child element '" << name << "'";
  }
}

Id Abigail::BuildSymbol(const SymbolInfo& info,
                        std::optional<Id> type_id,
                        const std::optional<std::string>& name) {
  const xmlNodePtr symbol = info.node;
  const bool is_defined = ReadAttributeOrDie<bool>(symbol, "is-defined");
  const auto crc = ReadAttribute<ElfSymbol::CRC>(symbol, "crc");
  const auto ns = ReadAttribute<std::string>(symbol, "namespace");
  const auto type = ReadAttributeOrDie<ElfSymbol::SymbolType>(symbol, "type");
  const auto binding =
      ReadAttributeOrDie<ElfSymbol::Binding>(symbol, "binding");
  const auto visibility =
      ReadAttributeOrDie<ElfSymbol::Visibility>(symbol, "visibility");

  return maker_.Add<ElfSymbol>(
      info.name, info.version_info,
      is_defined, type, binding, visibility, crc, ns, type_id, name);
}

Id Abigail::BuildSymbols() {
  // Libabigail's model is (approximately):
  //
  //   (alias)* -> main symbol <- some decl -> type
  //
  // which we turn into:
  //
  //   symbol / alias -> type
  //
  for (const auto& [alias, main] : alias_to_main_) {
    Check(!alias_to_main_.contains(main))
        << "found main symbol and alias with id " << main;
  }
  // Build final symbol table, tying symbols to their types.
  std::map<std::string, Id> symbols;
  for (const auto& [id, symbol_info] : symbol_info_map_) {
    const auto main = alias_to_main_.find(id);
    const auto lookup = main != alias_to_main_.end() ? main->second : id;
    const auto type_id_and_name_it = symbol_id_and_full_name_.find(lookup);
    std::optional<Id> type_id;
    std::optional<std::string> name;
    if (type_id_and_name_it != symbol_id_and_full_name_.end()) {
      const auto& type_id_and_name = type_id_and_name_it->second;
      type_id = {type_id_and_name.first};
      name = {type_id_and_name.second};
    }
    symbols.insert({id, BuildSymbol(symbol_info, type_id, name)});
  }
  return maker_.Add<Interface>(symbols);
}

using Parser = xmlDocPtr(xmlParserCtxtPtr context, const char* url,
                         const char* encoding, int options);

Document Parse(Runtime& runtime, const std::function<Parser>& parser) {
  const std::unique_ptr<
      std::remove_pointer_t<xmlParserCtxtPtr>, void(*)(xmlParserCtxtPtr)>
      context(xmlNewParserCtxt(), xmlFreeParserCtxt);
  Document document(nullptr, xmlFreeDoc);
  {
    const Time t(runtime, "abigail.libxml_parse");
    document.reset(parser(context.get(), nullptr, nullptr, XML_PARSE_NONET));
  }
  Check(document != nullptr) << "failed to parse input as XML";
  return document;
}

}  // namespace

Id ProcessDocument(Graph& graph, xmlDocPtr document) {
  xmlNodePtr root = xmlDocGetRootElement(document);
  Check(root != nullptr) << "XML document has no root element";
  const Id id = Abigail(graph).ProcessRoot(root);
  return RemoveUselessQualifiers(graph, id);
}

Document Read(Runtime& runtime, const std::string& path) {
  const FileDescriptor fd(path.c_str(), O_RDONLY);
  return Parse(runtime, [&](xmlParserCtxtPtr context, const char* url,
                            const char* encoding, int options) {
    return xmlCtxtReadFd(context, fd.Value(), url, encoding, options);
  });
}

Id Read(Runtime& runtime, Graph& graph, const std::string& path) {
  // Read the XML.
  const Document document = Read(runtime, path);
  // Process the XML.
  return ProcessDocument(graph, document.get());
}

Id ReadFromString(Runtime& runtime, Graph& graph, const std::string_view xml) {
  // Read the XML.
  const Document document =
      Parse(runtime, [&](xmlParserCtxtPtr context, const char* url,
                         const char* encoding, int options) {
    return xmlCtxtReadMemory(context, xml.data(), static_cast<int>(xml.size()),
                             url, encoding, options);
  });
  // Process the XML.
  return ProcessDocument(graph, document.get());
}

}  // namespace abixml
}  // namespace stg
