//===- RuntimeLibcallEmitter.cpp - Properties from RuntimeLibcalls.td -----===//
//
// 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
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "runtime-libcall-emitter"

#include "RuntimeLibcalls.h"

#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/xxhash.h"
#include "llvm/TableGen/CodeGenHelpers.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/SetTheory.h"
#include "llvm/TableGen/StringToOffsetTable.h"
#include "llvm/TableGen/TableGenBackend.h"

using namespace llvm;

namespace {
// Pair of a RuntimeLibcallAvailability and LibcallCallingConv to use as a map
// key.
struct PredicateWithCC {
  const Record *Availability = nullptr;
  const Record *CallingConv = nullptr;

  PredicateWithCC() = default;
  PredicateWithCC(std::pair<const Record *, const Record *> P)
      : Availability(P.first), CallingConv(P.second) {}

  PredicateWithCC(const Record *P, const Record *C)
      : Availability(P), CallingConv(C) {}
};

inline bool operator==(PredicateWithCC LHS, PredicateWithCC RHS) {
  return LHS.Availability == RHS.Availability &&
         LHS.CallingConv == RHS.CallingConv;
}
} // namespace

namespace {
/// A floating-point libcall family parsed from a RuntimeLibcallFamily record.
struct FPLibcallFamily {
  StringRef Base;
  std::vector<StringRef> Intrinsics;
  std::vector<StringRef> VectorSuffixes;

  explicit FPLibcallFamily(const Record *R)
      : Base(R->getValueAsString("LibcallBase")),
        Intrinsics(R->getValueAsListOfStrings("Intrinsics")),
        VectorSuffixes(R->getValueAsListOfStrings("VectorSuffixes")) {}
};
} // namespace

namespace llvm {
template <> struct DenseMapInfo<PredicateWithCC, void> {
  static unsigned getHashValue(const PredicateWithCC Val) {
    auto Pair = std::make_pair(Val.Availability, Val.CallingConv);
    return DenseMapInfo<
        std::pair<const Record *, const Record *>>::getHashValue(Pair);
  }

  static bool isEqual(PredicateWithCC LHS, PredicateWithCC RHS) {
    return LHS == RHS;
  }
};

class RuntimeLibcallEmitter {
private:
  const RecordKeeper &Records;
  RuntimeLibcalls Libcalls;

  void emitGetRuntimeLibcallEnum(raw_ostream &OS) const;

  void emitNameMatchHashTable(raw_ostream &OS,
                              StringToOffsetTable &OffsetTable) const;

  void emitGetInitRuntimeLibcallNames(raw_ostream &OS) const;

  // Emit the sorted per-predicate `setAvailable` tables/loops. The
  // always-available bucket emits at \p BaseIndent; each predicated bucket is
  // wrapped in `if (pred)`. All calls are emitted in member context (no
  // receiver prefix).
  void
  emitPredicateGroups(raw_ostream &OS, const Record *R,
                      DenseMap<PredicateWithCC, LibcallsWithCC> &Pred2Funcs,
                      SetVector<PredicateWithCC> &PredicateSorter,
                      unsigned BaseIndent) const;

  // A LibraryRef opt-out: the impls a consumer drops from a shared library,
  // plus the consumer's triple predicate.
  struct LibraryExclusion {
    const Record *TriplePred;
    std::vector<const RuntimeLibcallImpl *> Impls;
  };

  // A single LibcallLibrary variant, expanded into its per-predicate impl
  // groups. Unconditional impls are tracked separately for cross-variant
  // deduplication. A variant is Deferred when it re-adds an impl its own
  // consumer excludes; deferred variants are emitted after the LibraryRef
  // exclusions so the re-add wins over the opt-out.
  struct ExpandedLibrary {
    const Record *Lib;
    DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
    SetVector<PredicateWithCC> PredicateSorter;
    SetVector<const RuntimeLibcallImpl *> Unconditional;
    bool Deferred = false;
  };

  // Emit one variant's guarded `setAvailable` block into the enclosing
  // `setAvailableLibFuncs_<name>` function.
  void emitLibraryVariant(raw_ostream &OS, ExpandedLibrary &EL) const;

  // Emit a `setAvailableLibFuncs_<name>` member function for all LibcallLibrary
  // defs sharing \p Name, each gated by its own availability predicate. \p
  // Exclusions are emitted as guarded setUnavailable calls at the end.
  void emitLibraryFunction(raw_ostream &OS, StringRef Name,
                           ArrayRef<const Record *> Libs,
                           ArrayRef<LibraryExclusion> Exclusions) const;

  // Group all LibcallLibrary defs by their shared LibraryName, preserving
  // definition order. Both the member-declaration fragment and the definitions
  // iterate this to stay in lockstep.
  MapVector<StringRef, std::vector<const Record *>>
  collectLibrariesByName() const;

  void emitRuntimeLibcallsInfoMemberDecls(raw_ostream &OS) const;

  void emitSystemRuntimeLibrarySetCalls(raw_ostream &OS) const;

  DenseSet<StringRef> collectLibcallNames() const;

  void checkFPLibcallFamilies(ArrayRef<FPLibcallFamily> Families,
                              const DenseSet<StringRef> &LibcallNames) const;

  void emitFPLibcallSelectorDecls(raw_ostream &OS,
                                  ArrayRef<FPLibcallFamily> Families) const;

  void emitFPLibcallSelectors(raw_ostream &OS,
                              ArrayRef<FPLibcallFamily> Families,
                              const DenseSet<StringRef> &LibcallNames) const;

  void
  emitGetLibcallForIntrinsic(raw_ostream &OS,
                             ArrayRef<FPLibcallFamily> Families,
                             const DenseSet<StringRef> &LibcallNames) const;

public:
  RuntimeLibcallEmitter(const RecordKeeper &R) : Records(R), Libcalls(R) {}

  void run(raw_ostream &OS);
};

} // End anonymous namespace.

void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum(raw_ostream &OS) const {
  IfDefEmitter IfDef(OS, "GET_RUNTIME_LIBCALL_ENUM");

  OS << "namespace llvm {\n"
        "namespace RTLIB {\n"
        "enum Libcall : unsigned short {\n";

  for (const RuntimeLibcall &LibCall : Libcalls.getRuntimeLibcallDefList()) {
    StringRef Name = LibCall.getName();
    OS << "  " << Name << " = " << LibCall.getEnumVal() << ",\n";
  }

  OS << "  UNKNOWN_LIBCALL = " << Libcalls.getRuntimeLibcallDefList().size()
     << "\n};\n\n"
        "enum LibcallImpl : unsigned short {\n"
        "  Unsupported = 0,\n";

  for (const RuntimeLibcallImpl &LibCall :
       Libcalls.getRuntimeLibcallImplDefList()) {
    OS << "  impl_" << LibCall.getName() << " = " << LibCall.getEnumVal()
       << ", // " << LibCall.getLibcallFuncName() << '\n';
  }

  OS << "};\n"
     << "constexpr size_t NumLibcallImpls = "
     << Libcalls.getRuntimeLibcallImplDefList().size() + 1
     << ";\n"
        "} // End namespace RTLIB\n"
        "} // End namespace llvm\n";
}

// StringMap uses xxh3_64bits, truncated to uint32_t.
static uint64_t hash(StringRef Str) {
  return static_cast<uint32_t>(xxh3_64bits(Str));
}

static void emitHashFunction(raw_ostream &OS) {
  OS << "static inline uint64_t hash(StringRef Str) {\n"
        "  return static_cast<uint32_t>(xxh3_64bits(Str));\n"
        "}\n\n";
}

/// Return the table size, maximum number of collisions for the set of hashes
static std::pair<int, int>
computePerfectHashParameters(ArrayRef<uint64_t> Hashes) {
  // Chosen based on experimentation with llvm/benchmarks/RuntimeLibcalls.cpp
  const int SizeOverhead = 4;

  // Index derived from hash -> number of collisions.
  DenseMap<uint64_t, int> Table;

  unsigned NumHashes = Hashes.size();

  for (int MaxCollisions = 1;; ++MaxCollisions) {
    for (unsigned N = NextPowerOf2(NumHashes - 1); N < SizeOverhead * NumHashes;
         N <<= 1) {
      Table.clear();

      bool NeedResize = false;
      for (uint64_t H : Hashes) {
        uint64_t Idx = H % static_cast<uint64_t>(N);
        if (++Table[Idx] > MaxCollisions) {
          // Need to resize the final table if we increased the collision count.
          NeedResize = true;
          break;
        }
      }

      if (!NeedResize)
        return {N, MaxCollisions};
    }
  }
}

static std::vector<unsigned>
constructPerfectHashTable(ArrayRef<RuntimeLibcallImpl> Keywords,
                          ArrayRef<uint64_t> Hashes,
                          ArrayRef<unsigned> TableValues, int Size,
                          int Collisions, StringToOffsetTable &OffsetTable) {
  std::vector<unsigned> Lookup(Size * Collisions);

  for (auto [HashValue, TableValue] : zip(Hashes, TableValues)) {
    uint64_t Idx = (HashValue % static_cast<uint64_t>(Size)) *
                   static_cast<uint64_t>(Collisions);

    bool Found = false;
    for (int J = 0; J < Collisions; ++J) {
      unsigned &Entry = Lookup[Idx + J];
      if (Entry == 0) {
        Entry = TableValue;
        Found = true;
        break;
      }
    }

    if (!Found)
      reportFatalInternalError("failure to hash");
  }

  return Lookup;
}

/// Generate hash table based lookup by name.
void RuntimeLibcallEmitter::emitNameMatchHashTable(
    raw_ostream &OS, StringToOffsetTable &OffsetTable) const {
  ArrayRef<RuntimeLibcallImpl> RuntimeLibcallImplDefList =
      Libcalls.getRuntimeLibcallImplDefList();
  std::vector<uint64_t> Hashes(RuntimeLibcallImplDefList.size());
  std::vector<unsigned> TableValues(RuntimeLibcallImplDefList.size());
  DenseSet<StringRef> SeenFuncNames;

  size_t MaxFuncNameSize = 0;
  size_t Index = 0;

  for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
    StringRef ImplName = LibCallImpl.getLibcallFuncName();
    if (SeenFuncNames.insert(ImplName).second) {
      MaxFuncNameSize = std::max(MaxFuncNameSize, ImplName.size());
      TableValues[Index] = LibCallImpl.getEnumVal();
      Hashes[Index++] = hash(ImplName);
    }
  }

  // Trim excess elements from non-unique entries.
  Hashes.resize(SeenFuncNames.size());
  TableValues.resize(SeenFuncNames.size());

  LLVM_DEBUG({
    for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
      StringRef ImplName = LibCallImpl.getLibcallFuncName();
      if (ImplName.size() == MaxFuncNameSize) {
        dbgs() << "Maximum runtime libcall name size: " << ImplName << '('
               << MaxFuncNameSize << ")\n";
      }
    }
  });

  // Early exiting on the symbol name provides a significant speedup in the miss
  // case on the set of symbols in a clang binary. Emit this as an inlinable
  // precondition in the header.
  //
  // The empty check is also used to get sensible behavior on anonymous
  // functions.
  //
  // TODO: It may make more sense to split the search by string size more. There
  // are a few outliers, most call names are small.
  {
    IfDefEmitter IfDef(OS, "GET_LOOKUP_LIBCALL_IMPL_NAME_BODY");

    OS << "  size_t Size = Name.size();\n"
          "  if (Size == 0 || Size > "
       << MaxFuncNameSize
       << ")\n"
          "    return enum_seq(RTLIB::Unsupported, RTLIB::Unsupported);\n"
          " return lookupLibcallImplNameImpl(Name);\n";
  }

  auto [Size, Collisions] = computePerfectHashParameters(Hashes);
  std::vector<unsigned> Lookup =
      constructPerfectHashTable(RuntimeLibcallImplDefList, Hashes, TableValues,
                                Size, Collisions, OffsetTable);

  LLVM_DEBUG(dbgs() << "Runtime libcall perfect hashing parameters: Size = "
                    << Size << ", maximum collisions = " << Collisions << '\n');

  IfDefEmitter IfDef(OS, "DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME");
  emitHashFunction(OS);

  OS << "iota_range<RTLIB::LibcallImpl> RTLIB::RuntimeLibcallsInfo::"
        "lookupLibcallImplNameImpl(StringRef Name) {\n";

  // Emit RTLIB::LibcallImpl values
  OS << "  static constexpr uint16_t HashTableNameToEnum[" << Lookup.size()
     << "] = {\n";

  for (unsigned TableVal : Lookup)
    OS << "    " << TableVal << ",\n";

  OS << "  };\n\n";

  OS << "  unsigned Idx = (hash(Name) % " << Size << ") * " << Collisions
     << ";\n\n"
        "  for (int I = 0; I != "
     << Collisions << R"(; ++I) {
    const uint16_t Entry = HashTableNameToEnum[Idx + I];
    const uint16_t StrOffset = RuntimeLibcallNameOffsetTable[Entry];
    const uint8_t StrSize = RuntimeLibcallNameSizeTable[Entry];
    StringRef Str(
      &RTLIB::RuntimeLibcallsInfo::RuntimeLibcallImplNameTableStorage[StrOffset],
      StrSize);
    if (Str == Name)
      return libcallImplNameHit(Entry, StrOffset);
  }

  return enum_seq(RTLIB::Unsupported, RTLIB::Unsupported);
}
)";
}

void RuntimeLibcallEmitter::emitGetInitRuntimeLibcallNames(
    raw_ostream &OS) const {
  // Emit the implementation names
  StringToOffsetTable Table(/*AppendZero=*/true,
                            "RTLIB::RuntimeLibcallsInfo::");

  {
    IfDefEmitter IfDef(OS, "GET_INIT_RUNTIME_LIBCALL_NAMES");

    for (const RuntimeLibcallImpl &LibCallImpl :
         Libcalls.getRuntimeLibcallImplDefList())
      Table.GetOrAddStringOffset(LibCallImpl.getLibcallFuncName());

    Table.EmitStringTableDef(OS, "RuntimeLibcallImplNameTable");
    OS << R"(
const uint16_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameOffsetTable[] = {
)";

    OS << formatv("  {}, // {}\n", Table.GetStringOffset(""),
                  ""); // Unsupported entry
    for (const RuntimeLibcallImpl &LibCallImpl :
         Libcalls.getRuntimeLibcallImplDefList()) {
      StringRef ImplName = LibCallImpl.getLibcallFuncName();
      OS << formatv("  {}, // {}\n", Table.GetStringOffset(ImplName), ImplName);
    }
    OS << "};\n";

    OS << R"(
const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = {
)";

    OS << "  0,\n";
    for (const RuntimeLibcallImpl &LibCallImpl :
         Libcalls.getRuntimeLibcallImplDefList())
      OS << "  " << LibCallImpl.getLibcallFuncName().size() << ",\n";
    OS << "};\n\n";

    // Emit the reverse mapping from implementation libraries to RTLIB::Libcall
    OS << "const RTLIB::Libcall llvm::RTLIB::RuntimeLibcallsInfo::"
          "ImplToLibcall[RTLIB::NumLibcallImpls] = {\n"
          "  RTLIB::UNKNOWN_LIBCALL, // RTLIB::Unsupported\n";

    for (const RuntimeLibcallImpl &LibCallImpl :
         Libcalls.getRuntimeLibcallImplDefList()) {
      const RuntimeLibcall *Provides = LibCallImpl.getProvides();
      OS << "  ";
      Provides->emitEnumEntry(OS);
      OS << ", // ";
      LibCallImpl.emitEnumEntry(OS);
      OS << '\n';
    }

    OS << "};\n\n";
  }

  emitNameMatchHashTable(OS, Table);
}

void RuntimeLibcallEmitter::emitPredicateGroups(
    raw_ostream &OS, const Record *R,
    DenseMap<PredicateWithCC, LibcallsWithCC> &Pred2Funcs,
    SetVector<PredicateWithCC> &PredicateSorter, unsigned BaseIndent) const {
  SmallVector<PredicateWithCC, 0> SortedPredicates =
      PredicateSorter.takeVector();

  llvm::sort(SortedPredicates, [](PredicateWithCC A, PredicateWithCC B) {
    StringRef AName = A.Availability ? A.Availability->getName() : "";
    StringRef BName = B.Availability ? B.Availability->getName() : "";
    if (AName != BName)
      return AName < BName;
    // Break name ties on the calling convention for a deterministic order.
    StringRef ACC = A.CallingConv ? A.CallingConv->getName() : "";
    StringRef BCC = B.CallingConv ? B.CallingConv->getName() : "";
    return ACC < BCC;
  });

  for (PredicateWithCC Entry : SortedPredicates) {
    AvailabilityPredicate SubsetPredicate(Entry.Availability);
    unsigned IndentDepth = BaseIndent;

    auto It = Pred2Funcs.find(Entry);
    if (It == Pred2Funcs.end())
      continue;

    // Shared-core deduplication can empty a bucket.
    if (It->second.LibcallImpls.empty())
      continue;

    if (!SubsetPredicate.isAlwaysAvailable()) {
      IndentDepth = BaseIndent + 2;

      OS << indent(IndentDepth);
      SubsetPredicate.emitIf(OS);
    }

    LibcallsWithCC &FuncsWithCC = It->second;

    std::vector<const RuntimeLibcallImpl *> &Funcs = FuncsWithCC.LibcallImpls;

    // Records which impls are available, not which is selected, so a libcall
    // may have more than one. Order is irrelevant (each entry is a setAvailable
    // call); sort by the provided libcall, breaking ties on the impl enum for a
    // deterministic total order.
    llvm::sort(Funcs, [](const RuntimeLibcallImpl *A,
                         const RuntimeLibcallImpl *B) {
      return std::make_pair(A->getProvides()->getEnumVal(), A->getEnumVal()) <
             std::make_pair(B->getProvides()->getEnumVal(), B->getEnumVal());
    });

    OS << indent(IndentDepth + 2)
       << "static const RTLIB::LibcallImpl LibraryCalls";
    SubsetPredicate.emitTableVariableNameSuffix(OS);
    if (FuncsWithCC.CallingConv)
      OS << '_' << FuncsWithCC.CallingConv->getName();

    OS << "[] = {\n";
    for (const RuntimeLibcallImpl *LibCallImpl : Funcs) {
      OS << indent(IndentDepth + 6);
      LibCallImpl->emitEnumEntry(OS);
      OS << ", // " << LibCallImpl->getLibcallFuncName() << '\n';
    }

    OS << indent(IndentDepth + 2) << "};\n\n"
       << indent(IndentDepth + 2)
       << "for (const RTLIB::LibcallImpl Impl : LibraryCalls";
    SubsetPredicate.emitTableVariableNameSuffix(OS);
    if (FuncsWithCC.CallingConv)
      OS << '_' << FuncsWithCC.CallingConv->getName();

    OS << ") {\n" << indent(IndentDepth + 4) << "setAvailable(Impl);\n";

    if (FuncsWithCC.CallingConv) {
      StringRef CCEnum =
          FuncsWithCC.CallingConv->getValueAsString("CallingConv");
      OS << indent(IndentDepth + 4) << "setLibcallImplCallingConv(Impl, "
         << CCEnum << ");\n";
    }

    OS << indent(IndentDepth + 2) << "}\n";
    OS << '\n';

    if (!SubsetPredicate.isAlwaysAvailable()) {
      OS << indent(IndentDepth);
      SubsetPredicate.emitEndIf(OS);
      OS << '\n';
    }
  }
}

// Emit the linker name \p Name as a C++ identifier suffix, replacing characters
// invalid in an identifier (e.g. the '-' in "compiler-rt") with '_'.
static void emitLibFuncSuffix(raw_ostream &OS, StringRef Name) {
  for (char C : Name)
    OS << (isAlnum(C) || C == '_' ? C : '_');
}

void RuntimeLibcallEmitter::emitLibraryVariant(raw_ostream &OS,
                                               ExpandedLibrary &EL) const {
  AvailabilityPredicate LibPred(EL.Lib->getValueAsDef("Pred"));

  if (!LibPred.isAlwaysAvailable()) {
    OS << indent(2);
    LibPred.emitIf(OS);
  } else {
    // Own block scope so per-variant `LibraryCalls` tables do not collide.
    OS << indent(2) << "{\n";
  }

  emitPredicateGroups(OS, EL.Lib, EL.Pred2Funcs, EL.PredicateSorter,
                      /*BaseIndent=*/2);

  if (!LibPred.isAlwaysAvailable()) {
    OS << indent(2);
    LibPred.emitEndIf(OS);
  } else {
    OS << indent(2) << "}\n";
  }
}

void RuntimeLibcallEmitter::emitLibraryFunction(
    raw_ostream &OS, StringRef Name, ArrayRef<const Record *> Libs,
    ArrayRef<LibraryExclusion> Exclusions) const {
  OS << "void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_";
  emitLibFuncSuffix(OS, Name);
  OS << "(const llvm::Triple &TT, "
        "ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, "
        "StringRef ABIName, "
        "LongDoubleFormat LongDoubleFormat) {\n";

  SmallVector<ExpandedLibrary, 2> Expanded;
  for (const Record *Lib : Libs) {
    ExpandedLibrary EL;
    EL.Lib = Lib;

    // Expand this library's members with a library-local Func2Preds.
    SetTheory Sets;
    DenseMap<const RuntimeLibcallImpl *,
             std::pair<std::vector<const Record *>, const Record *>>
        Func2Preds;
    Sets.addExpander("LibcallImpls", std::make_unique<LibcallPredicateExpander>(
                                         Libcalls, Func2Preds));

    SetTheory::RecSet Elements;
    Sets.evaluate(Lib->getValueInit("Impls"), Elements, Lib->getLoc());

    EL.PredicateSorter.insert(
        PredicateWithCC()); // No predicate or CC override first.

    for (const Record *Elt : Elements) {
      const RuntimeLibcallImpl *LibCallImpl =
          Libcalls.getRuntimeLibcallImpl(Elt);
      if (!LibCallImpl) {
        PrintError(Lib, "entry for LibcallLibrary is not a RuntimeLibcallImpl");
        PrintNote(Elt->getLoc(), "invalid entry `" + Elt->getName() + "`");
        continue;
      }

      auto It = Func2Preds.find(LibCallImpl);
      if (It == Func2Preds.end()) {
        EL.Pred2Funcs[PredicateWithCC()].LibcallImpls.push_back(LibCallImpl);
        EL.Unconditional.insert(LibCallImpl);
        continue;
      }

      for (const Record *Pred : It->second.first) {
        const Record *CC = It->second.second;
        PredicateWithCC Key(Pred, CC);
        auto &Entry = EL.Pred2Funcs[Key];
        Entry.LibcallImpls.push_back(LibCallImpl);
        Entry.CallingConv = CC;
        EL.PredicateSorter.insert(Key);
      }
    }

    Expanded.push_back(std::move(EL));
  }

  // Impls unconditional in every variant are emitted once and stripped from
  // each variant, so the shared core is not repeated.
  SetVector<const RuntimeLibcallImpl *> SharedCore;
  if (Expanded.size() > 1) {
    for (const RuntimeLibcallImpl *Impl : Expanded.front().Unconditional) {
      if (all_of(drop_begin(Expanded), [&](const ExpandedLibrary &EL) {
            return EL.Unconditional.contains(Impl);
          }))
        SharedCore.insert(Impl);
    }
  }

  if (!SharedCore.empty()) {
    // Emit the shared core once, then strip it from every variant.
    DenseMap<PredicateWithCC, LibcallsWithCC> CorePred2Funcs;
    SetVector<PredicateWithCC> CoreSorter;
    CoreSorter.insert(PredicateWithCC());
    for (const RuntimeLibcallImpl *Impl : SharedCore)
      CorePred2Funcs[PredicateWithCC()].LibcallImpls.push_back(Impl);
    emitPredicateGroups(OS, Libs.front(), CorePred2Funcs, CoreSorter,
                        /*BaseIndent=*/0);

    for (ExpandedLibrary &EL : Expanded) {
      auto &Funcs = EL.Pred2Funcs[PredicateWithCC()].LibcallImpls;
      llvm::erase_if(Funcs, [&](const RuntimeLibcallImpl *Impl) {
        return SharedCore.contains(Impl);
      });
    }
  }

  // Mark a variant deferred when it re-adds an impl its own consumer excludes
  // (same triple, via LibraryRef). Such a variant must be emitted after the
  // exclusion so the re-add wins while the exclusion still suppresses every
  // other variant's contribution.
  for (ExpandedLibrary &EL : Expanded) {
    const Record *ELPred = EL.Lib->getValueAsDef("Pred");
    SetVector<const RuntimeLibcallImpl *> Impls;
    for (const auto &[Key, Funcs] : EL.Pred2Funcs)
      Impls.insert(Funcs.LibcallImpls.begin(), Funcs.LibcallImpls.end());

    for (const LibraryExclusion &Excl : Exclusions) {
      if (Excl.TriplePred != ELPred)
        continue;
      if (any_of(Excl.Impls, [&](const RuntimeLibcallImpl *Impl) {
            return Impls.contains(Impl);
          })) {
        EL.Deferred = true;
        break;
      }
    }
  }

  // Emit each non-deferred variant under its own Pred.
  for (ExpandedLibrary &EL : Expanded) {
    if (!EL.Deferred)
      emitLibraryVariant(OS, EL);
  }

  // Emit each consumer's LibraryRef opt-outs.
  for (const LibraryExclusion &Excl : Exclusions) {
    OS << '\n' << indent(2);
    AvailabilityPredicate ExcludePred(Excl.TriplePred);
    ExcludePred.emitIf(OS);
    for (const RuntimeLibcallImpl *Impl : Excl.Impls) {
      OS << indent(4) << "setUnavailable(";
      Impl->emitEnumEntry(OS);
      OS << "); // " << Impl->getLibcallFuncName() << '\n';
    }

    OS << indent(2);
    ExcludePred.emitEndIf(OS);
  }

  // Deferred variants: emitted after exclusions so a target's own re-adds
  // override its own LibraryRef opt-outs (the exclusion still applied above
  // to every other variant's contributions).
  for (ExpandedLibrary &EL : Expanded) {
    if (EL.Deferred)
      emitLibraryVariant(OS, EL);
  }

  OS << "}\n\n";
}

MapVector<StringRef, std::vector<const Record *>>
RuntimeLibcallEmitter::collectLibrariesByName() const {
  MapVector<StringRef, std::vector<const Record *>> LibsByName;
  for (const Record *Lib : Records.getAllDerivedDefinitions("LibcallLibrary"))
    LibsByName[Lib->getValueAsString("LibraryName")].push_back(Lib);
  return LibsByName;
}

void RuntimeLibcallEmitter::emitRuntimeLibcallsInfoMemberDecls(
    raw_ostream &OS) const {
  IfDefEmitter IfDef(OS, "GET_RUNTIME_LIBCALLS_INFO_MEMBER_DECLS");
  for (const auto &[Name, Libs] : collectLibrariesByName()) {
    OS << "void setAvailableLibFuncs_";
    emitLibFuncSuffix(OS, Name);
    OS << "(const llvm::Triple &TT, ExceptionHandling ExceptionModel, "
          "FloatABI::ABIType FloatABI, StringRef ABIName, "
          "LongDoubleFormat LongDoubleFormat);\n";
  }
}

void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
    raw_ostream &OS) const {
  ArrayRef<const Record *> AllLibs =
      Records.getAllDerivedDefinitions("SystemRuntimeLibrary");

  // Collect each shared library's LibraryRef opt-outs, keyed by library name,
  // so its library function can emit them.
  MapVector<StringRef, std::vector<LibraryExclusion>> ExclusionsByLibName;
  for (const Record *R : AllLibs) {
    const DagInit *MemberDag =
        R->getValueAsDef("MemberList")->getValueAsDag("MemberList");
    for (const Init *Arg : MemberDag->getArgs()) {
      const auto *DI = dyn_cast<DefInit>(Arg);
      if (!DI || !DI->getDef()->isSubClassOf("LibraryRef"))
        continue;
      const Record *Def = DI->getDef();
      LibraryExclusion Excl{R->getValueAsDef("TriplePred"), {}};
      for (const Record *ExcludeRec : Def->getValueAsListOfDefs("Exclude")) {
        if (const RuntimeLibcallImpl *Impl =
                Libcalls.getRuntimeLibcallImpl(ExcludeRec))
          Excl.Impls.push_back(Impl);
      }

      if (!Excl.Impls.empty()) {
        StringRef LibName =
            Def->getValueAsDef("Library")->getValueAsString("LibraryName");
        ExclusionsByLibName[LibName].push_back(std::move(Excl));
      }
    }
  }

  for (const auto &[Name, Libs] : collectLibrariesByName())
    emitLibraryFunction(OS, Name, Libs, ExclusionsByLibName.lookup(Name));

  OS << "void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets("
        "const llvm::Triple &TT, ExceptionHandling ExceptionModel, "
        "FloatABI::ABIType FloatABI, "
        "StringRef ABIName, LongDoubleFormat LongDoubleFormat) {\n";

  for (const Record *R : AllLibs) {
    OS << '\n';

    AvailabilityPredicate TopLevelPredicate(R->getValueAsDef("TriplePred"));

    OS << indent(2);
    TopLevelPredicate.emitIf(OS);

    if (const Record *DefaultCCClass =
            R->getValueAsDef("DefaultLibcallCallingConv")) {
      StringRef DefaultCC =
          DefaultCCClass->getValueAsString("CallingConv").trim();

      if (!DefaultCC.empty()) {
        OS << "    const CallingConv::ID DefaultCC = " << DefaultCC << ";\n"
           << "    for (CallingConv::ID &Entry : LibcallImplCallingConvs) {\n"
              "      Entry = DefaultCC;\n"
              "    }\n\n";
      }
    }

    // Split the top-level member list into named LibcallLibrary references
    // (dispatched to their own setAvailableLibFuncs_<name> under an
    // isLibraryAvailable guard) and the remaining bare impl / LibcallImpls
    // members. A LibraryRef also records impls to drop.
    struct DispatchLib {
      StringRef Name;
      std::vector<const RuntimeLibcallImpl *> Exclude;
    };
    const DagInit *MemberDag =
        R->getValueAsDef("MemberList")->getValueAsDag("MemberList");
    SmallVector<DispatchLib, 4> DispatchLibs;
    SmallVector<const Init *, 16> InlineArgs;
    SmallVector<const StringInit *, 16> InlineArgNames;
    for (auto [Arg, ArgName] :
         zip_equal(MemberDag->getArgs(), MemberDag->getArgNames())) {
      if (const auto *DI = dyn_cast<DefInit>(Arg)) {
        const Record *Def = DI->getDef();
        if (Def->isSubClassOf("LibcallLibrary")) {
          DispatchLibs.push_back({Def->getValueAsString("LibraryName"), {}});
          continue;
        }

        if (Def->isSubClassOf("LibraryRef")) {
          const Record *Lib = Def->getValueAsDef("Library");
          DispatchLib DL{Lib->getValueAsString("LibraryName"), {}};
          for (const Record *ExcludeRec :
               Def->getValueAsListOfDefs("Exclude")) {
            if (const RuntimeLibcallImpl *Impl =
                    Libcalls.getRuntimeLibcallImpl(ExcludeRec))
              DL.Exclude.push_back(Impl);
          }

          DispatchLibs.push_back(std::move(DL));
          continue;
        }
      }
      InlineArgs.push_back(Arg);
      InlineArgNames.push_back(ArgName);
    }

    const DagInit *InlineDag =
        DagInit::get(MemberDag->getOperator(), InlineArgs, InlineArgNames);

    SetTheory Sets;

    DenseMap<const RuntimeLibcallImpl *,
             std::pair<std::vector<const Record *>, const Record *>>
        Func2Preds;
    Sets.addExpander("LibcallImpls", std::make_unique<LibcallPredicateExpander>(
                                         Libcalls, Func2Preds));

    SetTheory::RecSet ElementsSet;
    Sets.evaluate(InlineDag, ElementsSet, R->getLoc());
    const SetTheory::RecSet *Elements = &ElementsSet;

    // Sort to get deterministic output
    SetVector<PredicateWithCC> PredicateSorter;
    PredicateSorter.insert(
        PredicateWithCC()); // No predicate or CC override first.

    constexpr unsigned BitsPerStorageElt = 64;
    DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;

    SmallVector<uint64_t, 32> BitsetValues(divideCeil(
        Libcalls.getRuntimeLibcallImplDefList().size() + 1, BitsPerStorageElt));

    for (const Record *Elt : *Elements) {
      const RuntimeLibcallImpl *LibCallImpl =
          Libcalls.getRuntimeLibcallImpl(Elt);
      if (!LibCallImpl) {
        PrintError(R, "entry for SystemLibrary is not a RuntimeLibcallImpl");
        PrintNote(Elt->getLoc(), "invalid entry `" + Elt->getName() + "`");
        continue;
      }

      size_t BitIdx = LibCallImpl->getEnumVal();
      uint64_t BitmaskVal = uint64_t(1) << (BitIdx % BitsPerStorageElt);
      size_t BitsetIdx = BitIdx / BitsPerStorageElt;

      auto It = Func2Preds.find(LibCallImpl);
      if (It == Func2Preds.end()) {
        BitsetValues[BitsetIdx] |= BitmaskVal;
        Pred2Funcs[PredicateWithCC()].LibcallImpls.push_back(LibCallImpl);
        continue;
      }

      for (const Record *Pred : It->second.first) {
        const Record *CC = It->second.second;
        AvailabilityPredicate SubsetPredicate(Pred);
        if (SubsetPredicate.isAlwaysAvailable())
          BitsetValues[BitsetIdx] |= BitmaskVal;

        PredicateWithCC Key(Pred, CC);
        auto &Entry = Pred2Funcs[Key];
        Entry.LibcallImpls.push_back(LibCallImpl);
        Entry.CallingConv = It->second.second;
        PredicateSorter.insert(Key);
      }
    }

    OS << "    static constexpr LibcallImplBitset SystemAvailableImpls({\n"
       << indent(6);

    ListSeparator LS;
    unsigned EntryCount = 0;
    for (uint64_t Bits : BitsetValues) {
      if (EntryCount++ == 4) {
        EntryCount = 1;
        OS << ",\n" << indent(6);
      } else
        OS << LS;
      OS << format_hex(Bits, 16);
    }
    OS << "\n    });\n"
          "    AvailableLibcallImpls = SystemAvailableImpls;\n\n";

    // Dispatch to each named library's setup function. This must come after the
    // SystemAvailableImpls assignment above (which overwrites the bitset); the
    // library functions union their members in on top via setAvailable.
    for (const DispatchLib &DL : DispatchLibs) {
      OS << indent(4) << "if (isLibraryAvailable(\"" << DL.Name << "\"))\n"
         << indent(6) << "setAvailableLibFuncs_";
      emitLibFuncSuffix(OS, DL.Name);
      OS << "(TT, ExceptionModel, FloatABI, ABIName, LongDoubleFormat);\n";
    }
    if (!DispatchLibs.empty())
      OS << '\n';

    emitPredicateGroups(OS, R, Pred2Funcs, PredicateSorter, /*BaseIndent=*/2);

    OS << indent(4) << "return;\n" << indent(2);
    TopLevelPredicate.emitEndIf(OS);
  }

  // FIXME: This should be a fatal error. A few contexts are improperly relying
  // on RuntimeLibcalls constructed with fully unknown triples.
  OS << "  LLVM_DEBUG(dbgs() << \"no system runtime library applied to target "
        "\\'\" << TT.str() << \"\\'\\n\");\n"
        "}\n\n";
}

// Scalar FP type suffixes in the argument order of RTLIB::getFPLibCall, paired
// with the llvm::Type predicate used by the IR-level mapping.
static constexpr std::pair<StringRef, StringRef> ScalarFPSuffixes[] = {
    {"F32", "isFloatTy()"},         {"F64", "isDoubleTy()"},
    {"F80", "isX86_FP80Ty()"},      {"F128", "isFP128Ty()"},
    {"PPCF128", "isPPC_FP128Ty()"},
};

static std::vector<FPLibcallFamily>
collectFPLibcallFamilies(const RecordKeeper &Records) {
  std::vector<FPLibcallFamily> Families;
  for (const Record *R :
       Records.getAllDerivedDefinitions("RuntimeLibcallFamily"))
    Families.emplace_back(R);
  llvm::sort(Families, [](const FPLibcallFamily &A, const FPLibcallFamily &B) {
    return A.Base < B.Base;
  });
  return Families;
}

DenseSet<StringRef> RuntimeLibcallEmitter::collectLibcallNames() const {
  DenseSet<StringRef> LibcallNames;
  for (const RuntimeLibcall &LC : Libcalls.getRuntimeLibcallDefList())
    LibcallNames.insert(LC.getName());
  return LibcallNames;
}

void RuntimeLibcallEmitter::checkFPLibcallFamilies(
    ArrayRef<FPLibcallFamily> Families,
    const DenseSet<StringRef> &LibcallNames) const {
  std::vector<std::pair<StringRef, StringRef>> IntrinsicToBase;
  for (const FPLibcallFamily &Family : Families)
    for (StringRef Intrinsic : Family.Intrinsics)
      IntrinsicToBase.emplace_back(Intrinsic, Family.Base);
  llvm::sort(IntrinsicToBase);

  for (size_t I = 1, E = IntrinsicToBase.size(); I < E; ++I) {
    if (IntrinsicToBase[I].first == IntrinsicToBase[I - 1].first)
      PrintFatalError(
          "intrinsic '" + IntrinsicToBase[I].first +
          "' is mapped by multiple RuntimeLibcallFamily records ('" +
          IntrinsicToBase[I - 1].second + "' and '" +
          IntrinsicToBase[I].second + "')");
  }

  for (const FPLibcallFamily &Family : Families) {
    bool AnyScalarLibcall = any_of(
        ScalarFPSuffixes, [&](const std::pair<StringRef, StringRef> &Entry) {
          return LibcallNames.contains((Family.Base + "_" + Entry.first).str());
        });
    if (!AnyScalarLibcall)
      PrintFatalError("no runtime libcall found for base name '" + Family.Base +
                      "'");
  }
}

/// Generate the declarations for the RTLIB::get<base>(EVT) selectors.
void RuntimeLibcallEmitter::emitFPLibcallSelectorDecls(
    raw_ostream &OS, ArrayRef<FPLibcallFamily> Families) const {
  IfDefEmitter IfDef(OS, "GET_RUNTIME_LIBCALL_FP_SELECTOR_DECLS");
  for (const FPLibcallFamily &Family : Families)
    OS << "LLVM_ABI Libcall get" << Family.Base << "(EVT VT);\n";
}

/// Generate the backend RTLIB::get<base>(EVT) selectors from the floating-point
/// libcall families.
void RuntimeLibcallEmitter::emitFPLibcallSelectors(
    raw_ostream &OS, ArrayRef<FPLibcallFamily> Families,
    const DenseSet<StringRef> &LibcallNames) const {
  IfDefEmitter IfDef(OS, "GET_RUNTIME_LIBCALL_FP_SELECTORS");

  // Only emit a libcall enumerator if it actually exists in the declared set.
  auto scalarEnum = [&](StringRef Base, StringRef Suffix) -> std::string {
    if (LibcallNames.contains((Base + "_" + Suffix).str()))
      return ("RTLIB::" + Base + "_" + Suffix).str();
    return "RTLIB::UNKNOWN_LIBCALL";
  };

  for (const FPLibcallFamily &Family : Families) {
    StringRef Base = Family.Base;
    OS << "RTLIB::Libcall llvm::RTLIB::get" << Base << "(EVT VT) {\n";

    if (!Family.VectorSuffixes.empty()) {
      OS << "  if (VT.isVector()) {\n"
            "    if (!VT.isSimple())\n"
            "      return RTLIB::UNKNOWN_LIBCALL;\n"
            "    switch (VT.getSimpleVT().SimpleTy) {\n";
      for (StringRef Suffix : Family.VectorSuffixes) {
        OS << "    case MVT::" << Suffix.lower()
           << ":\n      return RTLIB::" << Base << "_" << Suffix << ";\n";
      }
      OS << "    default:\n"
            "      return RTLIB::UNKNOWN_LIBCALL;\n"
            "    }\n"
            "  }\n";
    }

    OS << "  return getFPLibCall(VT";
    for (auto [Suffix, Pred] : ScalarFPSuffixes)
      OS << ", " << scalarEnum(Base, Suffix);
    OS << ");\n}\n\n";
  }
}

/// Emit the mapping from floating-point math intrinsics to the runtime libcall
/// they may lower to, keyed by intrinsic ID and floating-point type. This is
/// the IR-level counterpart to the backend's RTLIB::getXXX(EVT) selectors.
void RuntimeLibcallEmitter::emitGetLibcallForIntrinsic(
    raw_ostream &OS, ArrayRef<FPLibcallFamily> Families,
    const DenseSet<StringRef> &LibcallNames) const {
  IfDefEmitter IfDef(OS, "GET_RUNTIME_LIBCALL_INTRINSIC_TO_LIBCALL");

  std::vector<std::pair<StringRef, StringRef>> IntrinsicToBase;
  for (const FPLibcallFamily &Family : Families)
    for (StringRef Intrinsic : Family.Intrinsics)
      IntrinsicToBase.emplace_back(Intrinsic, Family.Base);
  llvm::sort(IntrinsicToBase);

  MapVector<StringRef, SmallVector<StringRef, 2>> BaseToIntrinsics;
  for (auto [Intrinsic, Base] : IntrinsicToBase)
    BaseToIntrinsics[Base].push_back(Intrinsic);

  OS << "RTLIB::Libcall "
        "llvm::RTLIB::RuntimeLibcallsInfo::getLibcallForIntrinsic("
        "Intrinsic::ID ID, FunctionType *FTy) {\n"
        "  Type *Ty = FTy->getReturnType();\n"
        "  if (!Ty->isFloatingPointTy()) {\n"
        "    for (Type *ParamTy : FTy->params()) {\n"
        "      if (ParamTy->isFloatingPointTy()) {\n"
        "        Ty = ParamTy;\n"
        "        break;\n"
        "      }\n"
        "    }\n"
        "  }\n"
        "  if (!Ty->isFloatingPointTy())\n"
        "    return RTLIB::UNKNOWN_LIBCALL;\n"
        "  switch (ID) {\n";

  for (const auto &[Base, Intrinsics] : BaseToIntrinsics) {
    SmallVector<std::pair<StringRef, StringRef>, 5> Arms;
    for (auto [Suffix, Pred] : ScalarFPSuffixes)
      if (LibcallNames.contains((Base + "_" + Suffix).str()))
        Arms.emplace_back(Suffix, Pred);

    for (StringRef Intrinsic : Intrinsics)
      OS << "  case Intrinsic::" << Intrinsic << ":\n";
    for (auto [Suffix, Pred] : Arms)
      OS << "    if (Ty->" << Pred << ")\n      return RTLIB::" << Base << "_"
         << Suffix << ";\n";
    OS << "    return RTLIB::UNKNOWN_LIBCALL;\n";
  }

  OS << "  default:\n"
        "    return RTLIB::UNKNOWN_LIBCALL;\n"
        "  }\n"
        "}\n";
}

void RuntimeLibcallEmitter::run(raw_ostream &OS) {
  emitSourceFileHeader("Runtime LibCalls Source Fragment", OS, Records);
  emitGetRuntimeLibcallEnum(OS);

  emitGetInitRuntimeLibcallNames(OS);

  emitRuntimeLibcallsInfoMemberDecls(OS);

  {
    IfDefEmitter IfDef(OS, "GET_RUNTIME_LIBCALLS_INFO");
    emitSystemRuntimeLibrarySetCalls(OS);
  }

  std::vector<FPLibcallFamily> FPFamilies = collectFPLibcallFamilies(Records);
  DenseSet<StringRef> LibcallNames = collectLibcallNames();
  checkFPLibcallFamilies(FPFamilies, LibcallNames);
  emitFPLibcallSelectorDecls(OS, FPFamilies);
  emitFPLibcallSelectors(OS, FPFamilies, LibcallNames);
  emitGetLibcallForIntrinsic(OS, FPFamilies, LibcallNames);
}

static TableGen::Emitter::OptClass<RuntimeLibcallEmitter>
    X("gen-runtime-libcalls", "Generate RuntimeLibcalls");
