// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- mode: C++ -*-
//
// Copyright 2020-2024 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: Maria Teguiani
// Author: Giuliano Procida
// Author: Ignes Simeonova

#include "comparison.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <functional>
#include <map>
#include <optional>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>

#include "error.h"
#include "graph.h"
#include "order.h"
#include "runtime.h"
#include "scc.h"

namespace stg {
namespace diff {

namespace {

struct IgnoreDescriptor {
  std::string_view name;
  Ignore::Value value;
};

constexpr std::array<IgnoreDescriptor, 9> kIgnores{{
  {"type_declaration_status",  Ignore::TYPE_DECLARATION_STATUS  },
  {"symbol_type_presence",     Ignore::SYMBOL_TYPE_PRESENCE     },
  {"primitive_type_encoding",  Ignore::PRIMITIVE_TYPE_ENCODING  },
  {"member_size",              Ignore::MEMBER_SIZE              },
  {"enum_underlying_type",     Ignore::ENUM_UNDERLYING_TYPE     },
  {"qualifier",                Ignore::QUALIFIER                },
  {"linux_symbol_crc",         Ignore::SYMBOL_CRC               },
  {"interface_addition",       Ignore::INTERFACE_ADDITION       },
  {"type_definition_addition", Ignore::TYPE_DEFINITION_ADDITION },
}};

}  // namespace

std::optional<Ignore::Value> ParseIgnore(std::string_view ignore) {
  for (const auto& [name, value] : kIgnores) {
    if (name == ignore) {
      return {value};
    }
  }
  return {};
}

std::ostream& operator<<(std::ostream& os, IgnoreUsage) {
  os << "ignore options:";
  for (const auto& [name, _] : kIgnores) {
    os << ' ' << name;
  }
  return os << '\n';
}

namespace {

struct Result {
  // Used when two nodes cannot be meaningfully compared.
  Result& MarkIncomparable() {
    same = false;
    diff.has_changes = true;
    return *this;
  }

  // Used when a node attribute has changed.
  void AddNodeDiff(const std::string& text) {
    same = false;
    diff.has_changes = true;
    diff.Add(text, {});
  }

  // Used when a node attribute may have changed.
  template <typename T>
  void MaybeAddNodeDiff(
      const std::string& text, const T& before, const T& after) {
    if (before != after) {
      std::ostringstream os;
      os << text << " changed from " << before << " to " << after;
      AddNodeDiff(os.str());
    }
  }

  // Used when a node attribute may have changed, lazy version.
  template <typename T>
  void MaybeAddNodeDiff(const std::function<void(std::ostream&)>& text,
                        const T& before, const T& after) {
    if (before != after) {
      std::ostringstream os;
      text(os);
      os << " changed from " << before << " to " << after;
      AddNodeDiff(os.str());
    }
  }

  // Used when node attributes are optional values.
  template <typename T>
  void MaybeAddNodeDiff(const std::string& text, const std::optional<T>& before,
                        const std::optional<T>& after) {
    if (before && after) {
      MaybeAddNodeDiff(text, *before, *after);
    } else if (before) {
      std::ostringstream os;
      os << text << ' ' << *before << " was removed";
      AddNodeDiff(os.str());
    } else if (after) {
      std::ostringstream os;
      os << text << ' ' << *after << " was added";
      AddNodeDiff(os.str());
    }
  }

  // Used when an edge has been removed or added.
  void AddEdgeDiff(const std::string& text, const Comparison& comparison) {
    same = false;
    diff.Add(text, comparison);
  }

  // Used when an edge to a possible comparison is present.
  void MaybeAddEdgeDiff(const std::string& text,
                        const std::pair<bool, Comparison>& p) {
    same &= p.first;
    const auto& comparison = p.second;
    if (comparison != Comparison{}) {
      diff.Add(text, comparison);
    }
  }

  // Used when an edge to a possible comparison is present, lazy version.
  void MaybeAddEdgeDiff(const std::function<void(std::ostream&)>& text,
                        const std::pair<bool, Comparison>& p) {
    same &= p.first;
    const auto& comparison = p.second;
    if (comparison != Comparison{}) {
      std::ostringstream os;
      text(os);
      diff.Add(os.str(), comparison);
    }
  }

  bool same = true;
  Diff diff;
};

struct ResolveTypedef {
  ResolveTypedef(const Graph& graph, Id& id, std::vector<std::string>& names)
      : graph(graph), id(id), names(names) {}

  bool operator()(const Typedef& x) const {
    id = x.referred_type_id;
    names.push_back(x.name);
    return true;
  }

  template <typename Node>
  bool operator()(const Node&) const {
    return false;
  }

  const Graph& graph;
  Id& id;
  std::vector<std::string>& names;
};

using Qualifiers = std::set<Qualifier>;

struct ResolveQualifier {
  ResolveQualifier(const Graph& graph, Id& id, Qualifiers& qualifiers)
      : graph(graph), id(id), qualifiers(qualifiers) {}

  bool operator()(const Qualified& x) const {
    id = x.qualified_type_id;
    qualifiers.insert(x.qualifier);
    return true;
  }

  bool operator()(const Array&) const {
    // There should be no qualifiers here.
    qualifiers.clear();
    return false;
  }

  bool operator()(const Function&) const {
    // There should be no qualifiers here.
    qualifiers.clear();
    return false;
  }

  template <typename Node>
  bool operator()(const Node&) const {
    return false;
  }

  const Graph& graph;
  Id& id;
  Qualifiers& qualifiers;
};

// Separate qualifiers from underlying type.
//
// The caller must always be prepared to receive a different type as qualifiers
// are sometimes discarded.
std::pair<Id, Qualifiers> ResolveQualifiers(const Graph& graph, Id id) {
  std::pair<Id, Qualifiers> result = {id, {}};
  ResolveQualifier resolve(graph, result.first, result.second);
  while (graph.Apply(resolve, result.first)) {}
  return result;
}

struct MatchingKey {
  explicit MatchingKey(const Graph& graph) : graph(graph) {}

  std::string operator()(Id id) const {
    return graph.Apply(*this, id);
  }

  std::string operator()(const BaseClass& x) const {
    return (*this)(x.type_id);
  }

  std::string operator()(const Method& x) const {
    return x.name + ',' + x.mangled_name;
  }

  std::string operator()(const Member& x) const {
    if (!x.name.empty()) {
      return x.name;
    }
    return (*this)(x.type_id);
  }

  std::string operator()(const VariantMember& x) const {
    return x.name;
  }

  std::string operator()(const StructUnion& x) const {
    if (!x.name.empty()) {
      return x.name;
    }
    if (x.definition) {
      const auto& members = x.definition->members;
      for (const auto& member : members) {
        const auto recursive = (*this)(member);
        if (!recursive.empty()) {
          return recursive + '+';
        }
      }
    }
    return {};
  }

  template <typename Node>
  std::string operator()(const Node&) const {
    return {};
  }

  const Graph& graph;
};

using KeyIndexPairs = std::vector<std::pair<std::string, size_t>>;

KeyIndexPairs MatchingKeys(const Graph& graph, const std::vector<Id>& ids) {
  KeyIndexPairs keys;
  const auto size = ids.size();
  keys.reserve(size);
  size_t anonymous_ix = 0;
  for (size_t ix = 0; ix < size; ++ix) {
    auto key = MatchingKey(graph)(ids[ix]);
    if (key.empty()) {
      key = "#anon#" + std::to_string(anonymous_ix++);
    }
    keys.emplace_back(key, ix);
  }
  std::stable_sort(keys.begin(), keys.end());
  return keys;
}

KeyIndexPairs MatchingKeys(const Enumeration::Enumerators& enums) {
  KeyIndexPairs names;
  const auto size = enums.size();
  names.reserve(size);
  for (size_t ix = 0; ix < size; ++ix) {
    const auto& name = enums[ix].first;
    names.emplace_back(name, ix);
  }
  std::stable_sort(names.begin(), names.end());
  return names;
}

using MatchedPairs =
    std::vector<std::pair<std::optional<size_t>, std::optional<size_t>>>;

MatchedPairs PairUp(const KeyIndexPairs& keys1, const KeyIndexPairs& keys2) {
  MatchedPairs pairs;
  pairs.reserve(std::max(keys1.size(), keys2.size()));
  auto it1 = keys1.begin();
  auto it2 = keys2.begin();
  const auto end1 = keys1.end();
  const auto end2 = keys2.end();
  while (it1 != end1 || it2 != end2) {
    if (it2 == end2 || (it1 != end1 && it1->first < it2->first)) {
      // removed
      pairs.push_back({{it1->second}, {}});
      ++it1;
    } else if (it1 == end1 || (it2 != end2 && it1->first > it2->first)) {
      // added
      pairs.push_back({{}, {it2->second}});
      ++it2;
    } else {
      // in both
      pairs.push_back({{it1->second}, {it2->second}});
      ++it1;
      ++it2;
    }
  }
  return pairs;
}

std::string QualifiersMessage(Qualifier qualifier, const std::string& action) {
  std::ostringstream os;
  os << "qualifier " << qualifier << ' ' << action;
  return os.str();
}

struct CompareWorker {
  CompareWorker(Runtime& runtime, const Ignore& ignore, const Graph& graph,
                Outcomes& outcomes)
      : ignore(ignore), graph(graph), outcomes(outcomes),
        queried(runtime, "compare.queried"),
        already_compared(runtime, "compare.already_compared"),
        being_compared(runtime, "compare.being_compared"),
        really_compared(runtime, "compare.really_compared"),
        equivalent(runtime, "compare.equivalent"),
        inequivalent(runtime, "compare.inequivalent"),
        scc_size(runtime, "compare.scc_size") {}

  /*
   * We compute a diff for every visited node.
   *
   * Each node has one of:
   *
   * * same == true; perhaps only tentative edge differences
   * * same == false; at least one definitive node or edge difference
   *
   * On the first visit to a node, the value of same is determined via recursive
   * comparison and the diff may contain local and edge differences. If an SCC
   * contains only internal edge differences (and equivalently same is true)
   * then the differences can all (eventually) be discarded.
   *
   * On exit from the first visit to a node, same reflects the tree of
   * comparisons below that node in the DFS and similarly, the diff graph
   * starting from the node contains a subtree of this tree plus potentially
   * edges to existing nodes to the side or below (already visited SCCs,
   * sharing), or above (back links forming cycles).
   *
   * When an SCC is closed, same is true results in the deletion of all the
   * nodes' diffs. The value of same is recorded for all nodes in the SCC.
   *
   * On other visits to a node, there are 2 cases. The node is still open
   * (meaning a recursive visit): return true and an edge diff. The node is
   * closed (meaning a repeat visit): return the stored value and an edge diff.
   */
  std::pair<bool, Comparison> operator()(Id id1, Id id2) {
    const Comparison comparison{{id1}, {id2}};
    ++queried;

    // Check if the comparison has an already known result.
    const auto already_known = known.find(comparison);
    if (already_known != known.end()) {
      // Already visited and closed.
      ++already_compared;
      return already_known->second
          ? std::make_pair(true, Comparison{})
          : std::make_pair(false, comparison);
    }
    // The comparison is either already open or has not been visited at all.

    // Record the comparison with the Strongly-Connected Component finder.
    const auto handle = scc.Open(comparison);
    if (!handle) {
      // Already open.
      //
      // Return a dummy true outcome and some tentative diffs. The diffs may end
      // up not being used and, while it would be nice to be lazier, they encode
      // all the cycling-breaking edges needed to recreate a full diff
      // structure.
      ++being_compared;
      return {true, comparison};
    }
    // The comparison has now been opened, we must close it before returning.

    // Really compare.
    ++really_compared;
    const auto [same, diff] = CompareWithResolution(id1, id2);

    // Record the result and check for a complete Strongly-Connected Component.
    outcomes.insert({comparison, diff});
    const auto comparisons = scc.Close(*handle);
    if (comparisons.empty()) {
      // Open SCC.
      //
      // Note that both same and diff are tentative as comparison is still
      // open.
      return {same, comparison};
    }
    // Closed SCC.
    //
    // Note that same and diff now include every inequality and difference in
    // the SCC via the DFS spanning tree.
    const auto size = comparisons.size();
    scc_size.Add(size);
    (same ? equivalent : inequivalent) += size;
    for (const auto& c : comparisons) {
      // Record equality / inequality.
      known.insert({c, same});
      if (same) {
        // Discard provisional diff.
        outcomes.erase(c);
      }
    }
    return same
        ? std::make_pair(true, Comparison{})
        : std::make_pair(false, comparison);
  }

  Result CompareWithResolution(Id id1, Id id2) {
    const auto [unqualified1, qualifiers1] = ResolveQualifiers(graph, id1);
    const auto [unqualified2, qualifiers2] = ResolveQualifiers(graph, id2);
    if (!qualifiers1.empty() || !qualifiers2.empty()) {
      // Qualified type difference.
      Result result;
      auto it1 = qualifiers1.begin();
      auto it2 = qualifiers2.begin();
      const auto end1 = qualifiers1.end();
      const auto end2 = qualifiers2.end();
      while (it1 != end1 || it2 != end2) {
        if (it2 == end2 || (it1 != end1 && *it1 < *it2)) {
          if (!ignore.Test(Ignore::QUALIFIER)) {
            result.AddNodeDiff(QualifiersMessage(*it1, "removed"));
          }
          ++it1;
        } else if (it1 == end1 || (it2 != end2 && *it1 > *it2)) {
          if (!ignore.Test(Ignore::QUALIFIER)) {
            result.AddNodeDiff(QualifiersMessage(*it2, "added"));
          }
          ++it2;
        } else {
          ++it1;
          ++it2;
        }
      }
      result.MaybeAddEdgeDiff("underlying",
                              (*this)(unqualified1, unqualified2));
      return result;
    }

    const auto [resolved1, typedefs1] = ResolveTypedefs(graph, unqualified1);
    const auto [resolved2, typedefs2] = ResolveTypedefs(graph, unqualified2);
    if (unqualified1 != resolved1 || unqualified2 != resolved2) {
      // Typedef difference.
      Result result;
      result.diff.holds_changes = !typedefs1.empty() && !typedefs2.empty()
                                  && typedefs1[0] == typedefs2[0];
      result.MaybeAddEdgeDiff("resolved", (*this)(resolved1, resolved2));
      return result;
    }

    // Compare nodes directly.
    return graph.Apply2(*this, unqualified1, unqualified2);
  }

  Comparison Removed(Id id) {
    Comparison comparison{{id}, {}};
    outcomes.insert({comparison, {}});
    return comparison;
  }

  Comparison Added(Id id) {
    Comparison comparison{{}, {id}};
    outcomes.insert({comparison, {}});
    return comparison;
  }

  void Defined(bool defined1, bool defined2, Result& result) {
    if (defined1 != defined2) {
      if (!ignore.Test(Ignore::TYPE_DECLARATION_STATUS)
          && !(ignore.Test(Ignore::TYPE_DEFINITION_ADDITION) && defined2)) {
        std::ostringstream os;
        os << "was " << (defined1 ? "fully defined" : "only declared")
           << ", is now " << (defined2 ? "fully defined" : "only declared");
        result.AddNodeDiff(os.str());
      }
    }
  }

  void Nodes(const std::vector<Id>& ids1, const std::vector<Id>& ids2,
             Result& result) {
    const auto keys1 = MatchingKeys(graph, ids1);
    const auto keys2 = MatchingKeys(graph, ids2);
    auto pairs = PairUp(keys1, keys2);
    Reorder(pairs);
    for (const auto& [index1, index2] : pairs) {
      if (index1 && !index2) {
        // removed
        const auto& x1 = ids1[*index1];
        result.AddEdgeDiff("", Removed(x1));
      } else if (!index1 && index2) {
        // added
        const auto& x2 = ids2[*index2];
        result.AddEdgeDiff("", Added(x2));
      } else if (index1 && index2) {
        // in both
        const auto& x1 = ids1[*index1];
        const auto& x2 = ids2[*index2];
        result.MaybeAddEdgeDiff("", (*this)(x1, x2));
      } else {
        Die() << "CompareWorker::Nodes: impossible pair";
      }
    }
  }

  void Nodes(const std::map<std::string, Id>& x1,
             const std::map<std::string, Id>& x2,
             bool ignore_added, Result& result) {
    // Group diffs into removed, added and changed symbols for readability.
    std::vector<Id> removed;
    std::vector<Id> added;
    std::vector<std::pair<Id, Id>> in_both;

    auto it1 = x1.begin();
    auto it2 = x2.begin();
    const auto end1 = x1.end();
    const auto end2 = x2.end();
    while (it1 != end1 || it2 != end2) {
      if (it2 == end2 || (it1 != end1 && it1->first < it2->first)) {
        // removed
        removed.push_back(it1->second);
        ++it1;
      } else if (it1 == end1 || (it2 != end2 && it1->first > it2->first)) {
        // added
        if (!ignore_added) {
          added.push_back(it2->second);
        }
        ++it2;
      } else {
        // in both
        in_both.emplace_back(it1->second, it2->second);
        ++it1;
        ++it2;
      }
    }

    for (const auto symbol1 : removed) {
      result.AddEdgeDiff("", Removed(symbol1));
    }
    for (const auto symbol2 : added) {
      result.AddEdgeDiff("", Added(symbol2));
    }
    for (const auto& [symbol1, symbol2] : in_both) {
      result.MaybeAddEdgeDiff("", (*this)(symbol1, symbol2));
    }
  }

  Result Mismatch() {
    return Result().MarkIncomparable();
  }

  Result operator()(const Special& x1, const Special& x2) {
    Result result;
    if (x1.kind != x2.kind) {
      return result.MarkIncomparable();
    }
    return result;
  }

  Result operator()(const PointerReference& x1, const PointerReference& x2) {
    Result result;
    if (x1.kind != x2.kind) {
      return result.MarkIncomparable();
    }
    const auto type_diff = (*this)(x1.pointee_type_id, x2.pointee_type_id);
    const char* text = x1.kind == PointerReference::Kind::POINTER
                       ? "pointed-to" : "referred-to";
    result.MaybeAddEdgeDiff(text, type_diff);
    return result;
  }

  Result operator()(const PointerToMember& x1, const PointerToMember& x2) {
    Result result;
    result.MaybeAddEdgeDiff(
        "containing", (*this)(x1.containing_type_id, x2.containing_type_id));
    result.MaybeAddEdgeDiff(
        "", (*this)(x1.pointee_type_id, x2.pointee_type_id));
    return result;
  }

  Result operator()(const Typedef&, const Typedef&) {
    // Compare will never attempt to directly compare Typedefs.
    Die() << "internal error: CompareWorker(Typedef)";
  }

  Result operator()(const Qualified&, const Qualified&) {
    // Compare will never attempt to directly compare Qualifiers.
    Die() << "internal error: CompareWorker(Qualified)";
  }

  Result operator()(const Primitive& x1, const Primitive& x2) {
    Result result;
    if (x1.name != x2.name) {
      return result.MarkIncomparable();
    }
    result.diff.holds_changes = !x1.name.empty();
    if (!ignore.Test(Ignore::PRIMITIVE_TYPE_ENCODING)) {
      result.MaybeAddNodeDiff("encoding", x1.encoding, x2.encoding);
    }
    result.MaybeAddNodeDiff("byte size", x1.bytesize, x2.bytesize);
    return result;
  }

  Result operator()(const Array& x1, const Array& x2) {
    Result result;
    result.MaybeAddNodeDiff("number of elements",
                            x1.number_of_elements, x2.number_of_elements);
    const auto type_diff = (*this)(x1.element_type_id, x2.element_type_id);
    result.MaybeAddEdgeDiff("element", type_diff);
    return result;
  }

  Result operator()(const BaseClass& x1, const BaseClass& x2) {
    Result result;
    result.MaybeAddNodeDiff("inheritance", x1.inheritance, x2.inheritance);
    result.MaybeAddNodeDiff("offset", x1.offset, x2.offset);
    result.MaybeAddEdgeDiff("", (*this)(x1.type_id, x2.type_id));
    return result;
  }

  Result operator()(const Method& x1, const Method& x2) {
    Result result;
    result.MaybeAddNodeDiff(
        "vtable offset", x1.vtable_offset, x2.vtable_offset);
    result.MaybeAddEdgeDiff("", (*this)(x1.type_id, x2.type_id));
    return result;
  }

  Result operator()(const Member& x1, const Member& x2) {
    Result result;
    result.MaybeAddNodeDiff("offset", x1.offset, x2.offset);
    if (!ignore.Test(Ignore::MEMBER_SIZE)) {
      const bool bitfield1 = x1.bitsize > 0;
      const bool bitfield2 = x2.bitsize > 0;
      if (bitfield1 != bitfield2) {
        std::ostringstream os;
        os << "was " << (bitfield1 ? "a bit-field" : "not a bit-field")
           << ", is now " << (bitfield2 ? "a bit-field" : "not a bit-field");
        result.AddNodeDiff(os.str());
      } else {
        result.MaybeAddNodeDiff("bit-field size", x1.bitsize, x2.bitsize);
      }
    }
    result.MaybeAddEdgeDiff("", (*this)(x1.type_id, x2.type_id));
    return result;
  }

  Result operator()(const VariantMember& x1, const VariantMember& x2) {
    Result result;
    result.MaybeAddNodeDiff("discriminant", x1.discriminant_value,
                            x2.discriminant_value);
    result.MaybeAddEdgeDiff("", (*this)(x1.type_id, x2.type_id));
    return result;
  }

  Result operator()(const StructUnion& x1, const StructUnion& x2) {
    Result result;
    // Compare two anonymous types recursively, not holding diffs.
    // Compare two identically named types recursively, holding diffs.
    // Everything else treated as distinct. No recursion.
    if (x1.kind != x2.kind || x1.name != x2.name) {
      return result.MarkIncomparable();
    }
    result.diff.holds_changes = !x1.name.empty();

    const auto& definition1 = x1.definition;
    const auto& definition2 = x2.definition;
    Defined(definition1.has_value(), definition2.has_value(), result);

    if (definition1.has_value() && definition2.has_value()) {
      result.MaybeAddNodeDiff(
          "byte size", definition1->bytesize, definition2->bytesize);
      Nodes(definition1->base_classes, definition2->base_classes, result);
      Nodes(definition1->methods, definition2->methods, result);
      Nodes(definition1->members, definition2->members, result);
    }

    return result;
  }

  Result operator()(const Enumeration& x1, const Enumeration& x2) {
    Result result;
    // Compare two anonymous types recursively, not holding diffs.
    // Compare two identically named types recursively, holding diffs.
    // Everything else treated as distinct. No recursion.
    if (x1.name != x2.name) {
      return result.MarkIncomparable();
    }
    result.diff.holds_changes = !x1.name.empty();

    const auto& definition1 = x1.definition;
    const auto& definition2 = x2.definition;
    Defined(definition1.has_value(), definition2.has_value(), result);

    if (definition1.has_value() && definition2.has_value()) {
      if (!ignore.Test(Ignore::ENUM_UNDERLYING_TYPE)) {
        const auto type_diff = (*this)(definition1->underlying_type_id,
                                       definition2->underlying_type_id);
        result.MaybeAddEdgeDiff("underlying", type_diff);
      }

      const auto enums1 = definition1->enumerators;
      const auto enums2 = definition2->enumerators;
      const auto keys1 = MatchingKeys(enums1);
      const auto keys2 = MatchingKeys(enums2);
      auto pairs = PairUp(keys1, keys2);
      Reorder(pairs);
      for (const auto& [index1, index2] : pairs) {
        if (index1 && !index2) {
          // removed
          const auto& enum1 = enums1[*index1];
          std::ostringstream os;
          os << "enumerator '" << enum1.first
             << "' (" << enum1.second << ") was removed";
          result.AddNodeDiff(os.str());
        } else if (!index1 && index2) {
          // added
          const auto& enum2 = enums2[*index2];
          std::ostringstream os;
          os << "enumerator '" << enum2.first
             << "' (" << enum2.second << ") was added";
          result.AddNodeDiff(os.str());
        } else if (index1 && index2) {
          // in both
          const auto& enum1 = enums1[*index1];
          const auto& enum2 = enums2[*index2];
          result.MaybeAddNodeDiff(
              [&](std::ostream& os) {
                os << "enumerator '" << enum1.first << "' value";
              },
              enum1.second, enum2.second);
        } else {
          Die() << "CompareWorker(Enumeration): impossible pair";
        }
      }
    }

    return result;
  }

  Result operator()(const Variant& x1, const Variant& x2) {
    Result result;
    // Compare two identically named variants recursively, holding diffs.
    // Everything else treated as distinct. No recursion.
    if (x1.name != x2.name) {
      return result.MarkIncomparable();
    }
    result.diff.holds_changes = true;  // Anonymous variants are not allowed.

    result.MaybeAddNodeDiff("bytesize", x1.bytesize, x2.bytesize);
    if (x1.discriminant.has_value() && x2.discriminant.has_value()) {
      const auto type_diff =
          (*this)(x1.discriminant.value(), x2.discriminant.value());
      result.MaybeAddEdgeDiff("discriminant", type_diff);
    } else if (x1.discriminant.has_value()) {
      result.AddEdgeDiff("", Removed(x1.discriminant.value()));
    } else if (x2.discriminant.has_value()) {
      result.AddEdgeDiff("", Added(x2.discriminant.value()));
    }
    Nodes(x1.members, x2.members, result);
    return result;
  }

  Result operator()(const Function& x1, const Function& x2) {
    Result result;
    const auto type_diff = (*this)(x1.return_type_id, x2.return_type_id);
    result.MaybeAddEdgeDiff("return", type_diff);

    const auto& parameters1 = x1.parameters;
    const auto& parameters2 = x2.parameters;
    const size_t min = std::min(parameters1.size(), parameters2.size());
    for (size_t i = 0; i < min; ++i) {
      const Id p1 = parameters1.at(i);
      const Id p2 = parameters2.at(i);
      result.MaybeAddEdgeDiff(
          [&](std::ostream& os) {
            os << "parameter " << i + 1;
          },
          (*this)(p1, p2));
    }

    const bool added = parameters1.size() < parameters2.size();
    const auto& which = added ? x2 : x1;
    const auto& parameters = which.parameters;
    for (size_t i = min; i < parameters.size(); ++i) {
      const Id parameter = parameters.at(i);
      std::ostringstream os;
      os << "parameter " << i + 1 << " of";
      auto diff = added ? Added(parameter) : Removed(parameter);
      result.AddEdgeDiff(os.str(), diff);
    }

    return result;
  }

  Result operator()(const ElfSymbol& x1, const ElfSymbol& x2) {
    // ELF symbols have a lot of different attributes that can impact ABI
    // compatibility and others that either cannot or are subsumed by
    // information elsewhere.
    //
    // Not all attributes are exposed by elf_symbol and fewer still in ABI XML.
    //
    // name - definitely part of the key
    //
    // type - (ELF symbol type, not C type) one important distinction here would
    // be global vs thread-local variables
    //
    // section - not exposed (modulo aliasing information) and don't care
    //
    // value (address, usually) - not exposed (modulo aliasing information) and
    // don't care
    //
    // size - don't care (for variables, subsumed by type information)
    //
    // binding - global vs weak vs unique vs local
    //
    // visibility - default > protected > hidden > internal
    //
    // version / is-default-version - in theory the "hidden" bit (separate from
    // hidden and local above) can be set independently of the version, but in
    // practice at most one version of given name is non-hidden; version
    // (including its presence or absence) is definitely part of the key; we
    // should probably treat is-default-version as a non-key attribute
    //
    // defined - rather fundamental; libabigail currently doesn't track
    // undefined symbols but we should obviously be prepared in case it does

    // There are also some externalities which libabigail cares about, which may
    // or may not be exposed in the XML
    //
    // index - don't care
    //
    // is-common and friends - don't care
    //
    // aliases - exposed, but we don't really care; however we should see what
    // compilers do, if anything, in terms of propagating type information to
    // aliases

    // Linux kernel things.
    //
    // MODVERSIONS CRC - fundamental to ABI compatibility, if present
    //
    // Symbol namespace - fundamental to ABI compatibility, if present

    Result result;
    result.MaybeAddNodeDiff("name", x1.symbol_name, x2.symbol_name);

    if (x1.version_info && x2.version_info) {
      result.MaybeAddNodeDiff("version", x1.version_info->name,
                              x2.version_info->name);
      result.MaybeAddNodeDiff("default version", x1.version_info->is_default,
                              x2.version_info->is_default);
    } else {
      result.MaybeAddNodeDiff("has version", x1.version_info.has_value(),
                              x2.version_info.has_value());
    }

    result.MaybeAddNodeDiff("defined", x1.is_defined, x2.is_defined);
    result.MaybeAddNodeDiff("symbol type", x1.symbol_type, x2.symbol_type);
    result.MaybeAddNodeDiff("binding", x1.binding, x2.binding);
    result.MaybeAddNodeDiff("visibility", x1.visibility, x2.visibility);
    if (!ignore.Test(Ignore::SYMBOL_CRC)) {
      result.MaybeAddNodeDiff("CRC", x1.crc, x2.crc);
    }
    result.MaybeAddNodeDiff("namespace", x1.ns, x2.ns);

    if (x1.type_id && x2.type_id) {
      result.MaybeAddEdgeDiff("", (*this)(*x1.type_id, *x2.type_id));
    } else if (x1.type_id) {
      if (!ignore.Test(Ignore::SYMBOL_TYPE_PRESENCE)) {
        result.AddEdgeDiff("", Removed(*x1.type_id));
      }
    } else if (x2.type_id) {
      if (!ignore.Test(Ignore::SYMBOL_TYPE_PRESENCE)) {
        result.AddEdgeDiff("", Added(*x2.type_id));
      }
    } else {
      // both types missing, we have nothing to say
    }

    return result;
  }

  Result operator()(const Interface& x1, const Interface& x2) {
    Result result;
    result.diff.holds_changes = true;
    const bool ignore_added = ignore.Test(Ignore::INTERFACE_ADDITION);
    Nodes(x1.symbols, x2.symbols, ignore_added, result);
    Nodes(x1.types, x2.types, ignore_added, result);
    return result;
  }

  const Ignore ignore;
  const Graph& graph;
  Outcomes& outcomes;
  std::unordered_map<Comparison, bool, HashComparison> known;
  SCC<Comparison, HashComparison> scc;
  Counter queried;
  Counter already_compared;
  Counter being_compared;
  Counter really_compared;
  Counter equivalent;
  Counter inequivalent;
  Histogram scc_size;
};

}  // namespace

std::pair<Id, std::vector<std::string>> ResolveTypedefs(
    const Graph& graph, Id id) {
  std::pair<Id, std::vector<std::string>> result = {id, {}};
  ResolveTypedef resolve(graph, result.first, result.second);
  while (graph.Apply(resolve, result.first)) {}
  return result;
}

Comparison Compare(Runtime& runtime, Ignore ignore, const Graph& graph,
                   Id root1, Id root2, Outcomes& outcomes) {
  // The root node (Comparison{{id1}, {id2}}) must be the last node to be
  // completely visited by the SCC finder and the SCC finder state must be empty
  // on return from this function call. In particular, the returns where the SCC
  // is "open" are impossible. The remaining cases (of which one is impossible
  // for the root node) both have the same two possible return values:
  //
  // * (true, Comparison{})
  // * (false, Comparison{{id1}, {id2}}
  //
  // So the invariant value.first == (value.second == Comparison{}) holds and we
  // can unambiguously return value.second.
  return CompareWorker(runtime, ignore, graph, outcomes)(root1, root2).second;
}

}  // namespace diff
}  // namespace stg
