//===- ARMTargetDefEmitter.cpp - Generate data about ARM Architectures ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend exports information about CPUs, FPUs, architectures,
// and features into a common format that can be used by both TargetParser and
// the ARM and AArch64 backends.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringToOffsetTable.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <set>
#include <string>

using namespace llvm;

/// Collect the full set of implied features for a SubtargetFeature.
static void collectImpliedFeatures(std::set<const Record *> &SeenFeats,
                                   const Record *Rec) {
  assert(Rec->isSubClassOf("SubtargetFeature") &&
         "Rec is not a SubtargetFeature");

  SeenFeats.insert(Rec);
  for (const Record *Implied : Rec->getValueAsListOfDefs("Implies"))
    collectImpliedFeatures(SeenFeats, Implied);
}

static void checkFeatureTree(const Record *Root) {
  std::set<const Record *> SeenFeats;
  collectImpliedFeatures(SeenFeats, Root);

  // Check that each of the mandatory (implied) features which is an
  // ExtensionWithMArch is also enabled by default.
  auto DefaultExtsVec = Root->getValueAsListOfDefs("DefaultExts");
  std::set<const Record *> DefaultExts{DefaultExtsVec.begin(),
                                       DefaultExtsVec.end()};
  for (const Record *Feat : SeenFeats) {
    if (Feat->isSubClassOf("ExtensionWithMArch") && !DefaultExts.count(Feat))
      PrintFatalError(Root->getLoc(),
                      "ExtensionWithMArch " + Feat->getName() +
                          " is implied (mandatory) as a SubtargetFeature, but "
                          "is not present in DefaultExts");
  }
}

static void emitARMTargetDef(const RecordKeeper &RK, raw_ostream &OS) {
  OS << "// Autogenerated by ARMTargetDefEmitter.cpp\n\n";

  // Look through all SubtargetFeature defs with the given FieldName, and
  // collect the set of all Values that that FieldName is set to.
  auto GatherSubtargetFeatureFieldValues = [&RK](StringRef FieldName) {
    llvm::StringSet<> Set;
    for (const Record *Rec : RK.getAllDerivedDefinitions("SubtargetFeature")) {
      if (Rec->getValueAsString("FieldName") == FieldName) {
        Set.insert(Rec->getValueAsString("Value"));
      }
    }
    return Set;
  };

  // Sort the extensions alphabetically, so they don't appear in tablegen order.
  std::vector<const Record *> SortedExtensions =
      RK.getAllDerivedDefinitions("Extension");
  auto Alphabetical = [](const Record *A, const Record *B) -> bool {
    const auto NameA = A->getValueAsString("Name");
    const auto NameB = B->getValueAsString("Name");
    return NameA.compare(NameB) < 0; // A lexographically less than B
  };
  sort(SortedExtensions, Alphabetical);

  // Cache Extension records for quick lookup.
  DenseMap<StringRef, const Record *> ExtensionMap;
  for (const Record *Rec : SortedExtensions) {
    auto Name = Rec->getValueAsString("UserVisibleName");
    if (Name.empty())
      Name = Rec->getValueAsString("Name");
    ExtensionMap[Name] = Rec;
  }

  // The ARMProcFamilyEnum values are initialised by SubtargetFeature defs
  // which set the ARMProcFamily field. We can generate the enum from these defs
  // which look like this:
  //
  // def ProcA5      : SubtargetFeature<"a5", "ARMProcFamily", "CortexA5",
  //                                    "Cortex-A5 ARM processors", []>;
  OS << "#ifndef ARM_PROCESSOR_FAMILY\n"
     << "#define ARM_PROCESSOR_FAMILY(ENUM)\n"
     << "#endif\n\n";
  const StringSet<> ARMProcFamilyVals =
      GatherSubtargetFeatureFieldValues("ARMProcFamily");
  for (const StringRef &Family : ARMProcFamilyVals.keys())
    OS << "ARM_PROCESSOR_FAMILY(" << Family << ")\n";
  OS << "\n#undef ARM_PROCESSOR_FAMILY\n\n";

  OS << "#ifndef ARM_ARCHITECTURE\n"
     << "#define ARM_ARCHITECTURE(ENUM)\n"
     << "#endif\n\n";
  // This should correspond to instances of the Architecture tablegen class.
  const StringSet<> ARMArchVals = GatherSubtargetFeatureFieldValues("ARMArch");
  for (const StringRef &Arch : ARMArchVals.keys())
    OS << "ARM_ARCHITECTURE(" << Arch << ")\n";
  OS << "\n#undef ARM_ARCHITECTURE\n\n";

  // Currently only AArch64 (not ARM) is handled beyond this point.
  if (!RK.getClass("Architecture64"))
    return;

  StringToOffsetTable StrTab;

  // Emit the ArchExtKind enum
  OS << "#ifdef EMIT_ARCHEXTKIND_ENUM\n"
     << "enum ArchExtKind : unsigned {\n";
  for (const Record *Rec : SortedExtensions) {
    auto AEK = Rec->getValueAsString("ArchExtKindSpelling").upper();
    OS << "  " << AEK << ",\n";
  }
  OS << "  AEK_NUM_EXTENSIONS\n"
     << "};\n"
     << "#undef EMIT_ARCHEXTKIND_ENUM\n"
     << "#endif // EMIT_ARCHEXTKIND_ENUM\n";

  // Emit information for each defined Extension; used to build ArmExtKind.
  OS << "#ifdef EMIT_EXTENSIONS\n"
     << "inline constexpr ExtensionInfo Extensions[] = {\n";
  for (const Record *Rec : SortedExtensions) {
    auto AEK = Rec->getValueAsString("ArchExtKindSpelling").upper();
    OS << "  ";
    OS << "{"
       << StrTab.GetOrAddStringOffset(Rec->getValueAsString("UserVisibleName"));
    // Empty string implies no alias.
    OS << ", "
       << StrTab.GetOrAddStringOffset(
              Rec->getValueAsString("UserVisibleAlias"));
    OS << ", AArch64::" << AEK;
    OS << ", "
       << StrTab.GetOrAddStringOffset(Rec->getValueAsString("ArchFeatureName"));
    OS << ", " << StrTab.GetOrAddStringOffset(Rec->getValueAsString("Desc"));
    OS << ", "
       << StrTab.GetOrAddStringOffset(
              std::string("+") +
              Rec->getValueAsString("Name").str()); // posfeature
    OS << ", "
       << StrTab.GetOrAddStringOffset(
              std::string("-") +
              Rec->getValueAsString("Name").str()); // negfeature
    OS << "},\n";
  };
  OS << "};\n";
  OS << "#undef EMIT_EXTENSIONS\n"
     << "#endif // EMIT_EXTENSIONS\n"
     << "\n";

  // Emit FMV information
  auto FMVExts = RK.getAllDerivedDefinitionsIfDefined("FMVExtension");
  OS << "#ifdef EMIT_FMV_INFO\n"
     << "const std::vector<llvm::AArch64::FMVInfo>& "
        "llvm::AArch64::getFMVInfo() {\n"
     << "  static std::vector<FMVInfo> I;\n"
     << "  if(I.size()) return I;\n"
     << "  I.reserve(" << FMVExts.size() << ");\n";
  for (const Record *Rec : FMVExts) {
    auto FeatName = Rec->getValueAsString("BackendFeature");
    const Record *FeatRec = ExtensionMap[FeatName];
    OS << "  I.emplace_back(";
    OS << "\"" << Rec->getValueAsString("Name") << "\"";
    if (FeatRec)
      OS << ", " << Rec->getValueAsString("FeatureBit");
    else
      OS << ", std::nullopt";
    OS << ", " << Rec->getValueAsString("PriorityBit");
    if (FeatRec)
      OS << ", " << FeatRec->getValueAsString("ArchExtKindSpelling").upper();
    else
      OS << ", std::nullopt";
    OS << ");\n";
  };
  OS << "  return I;\n"
     << "}\n"
     << "#undef EMIT_FMV_INFO\n"
     << "#endif // EMIT_FMV_INFO\n"
     << "\n";

  // Emit extension dependencies
  OS << "#ifdef EMIT_EXTENSION_DEPENDENCIES\n"
     << "inline constexpr ExtensionDependency ExtensionDependencies[] = {\n";
  for (const Record *Rec : SortedExtensions) {
    auto LaterAEK = Rec->getValueAsString("ArchExtKindSpelling").upper();
    for (const Record *I : Rec->getValueAsListOfDefs("Implies"))
      if (auto EarlierAEK = I->getValueAsOptionalString("ArchExtKindSpelling"))
        OS << "  {" << EarlierAEK->upper() << ", " << LaterAEK << "},\n";
  }
  // FIXME: Tablegen has the Subtarget Feature FeatureRCPC_IMMO which is implied
  // by FeatureRCPC3 and in turn implies FeatureRCPC. The proper fix is to make
  // FeatureRCPC_IMMO an Extension but that will expose it to the command line.
  OS << "  {AEK_RCPC, AEK_RCPC3},\n";
  OS << "};\n"
     << "#undef EMIT_EXTENSION_DEPENDENCIES\n"
     << "#endif // EMIT_EXTENSION_DEPENDENCIES\n"
     << "\n";

  // Emit architecture information
  OS << "#ifdef EMIT_ARCHITECTURES\n";

  // Return the C++ name of the of an ArchInfo object
  auto ArchInfoName = [](int Major, int Minor,
                         StringRef Profile) -> std::string {
    return Minor == 0 ? "ARMV" + std::to_string(Major) + Profile.upper()
                      : "ARMV" + std::to_string(Major) + "_" +
                            std::to_string(Minor) + Profile.upper();
  };

  auto Architectures = RK.getAllDerivedDefinitionsIfDefined("Architecture64");
  OS << "\n"
     << "/// The set of all architectures\n"
     << "inline constexpr std::array<ArchInfo, " << Architectures.size()
     << "> ArchInfos = {{\n";
  std::vector<std::string> CppSpellings;
  for (const Record *Rec : Architectures) {
    const int Major = Rec->getValueAsInt("Major");
    const int Minor = Rec->getValueAsInt("Minor");
    const std::string ProfileLower = Rec->getValueAsString("Profile").str();
    const std::string ProfileUpper = Rec->getValueAsString("Profile").upper();

    if (ProfileLower != "a" && ProfileLower != "r")
      PrintFatalError(Rec->getLoc(),
                      "error: Profile must be one of 'a' or 'r', got '" +
                          ProfileLower + "'");

    // Name of the object in C++
    std::string CppSpelling = ArchInfoName(Major, Minor, ProfileUpper);
    OS << "  {\n";
    CppSpellings.push_back(std::move(CppSpelling));

    OS << llvm::format("    VersionTuple{%d, %d},\n", Major, Minor);
    OS << llvm::format("    %sProfile,\n", ProfileUpper.c_str());

    // Name as spelled for -march.
    std::string ArchStr;
    llvm::raw_string_ostream AS(ArchStr);
    if (Minor == 0)
      AS << llvm::format("armv%d-%s", Major, ProfileLower.c_str());
    else
      AS << llvm::format("armv%d.%d-%s", Major, Minor, ProfileLower.c_str());
    OS << "    " << StrTab.GetOrAddStringOffset(ArchStr) << ",\n";

    // SubtargetFeature::Name, used for -target-feature. Here the "+" is added.
    std::string TargetFeatureName =
        (Twine("+") + Rec->getValueAsString("Name")).str();
    OS << "    " << StrTab.GetOrAddStringOffset(TargetFeatureName) << ",\n";

    // Construct the list of default extensions
    OS << "    (AArch64::ExtensionBitset({";
    for (auto *E : Rec->getValueAsListOfDefs("DefaultExts")) {
      OS << "AArch64::" << E->getValueAsString("ArchExtKindSpelling").upper()
         << ", ";
    }
    OS << "}))\n";

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

  for (auto [Idx, CppSpelling] : enumerate(CppSpellings))
    OS << "static constexpr const ArchInfo &" << CppSpelling << " = ArchInfos["
       << Idx << "];\n";

  OS << "#undef EMIT_ARCHITECTURES\n"
     << "#endif // EMIT_ARCHITECTURES\n"
     << "\n";

  // Emit CPU Aliases
  OS << "#ifdef EMIT_CPU_ALIAS\n"
     << "inline constexpr Alias CpuAliases[] = {\n";

  llvm::StringSet<> Processors;
  for (const Record *Rec : RK.getAllDerivedDefinitions("ProcessorModel"))
    Processors.insert(Rec->getValueAsString("Name"));

  llvm::StringSet<> Aliases;
  for (const Record *Rec : RK.getAllDerivedDefinitions("ProcessorAlias")) {
    auto Name = Rec->getValueAsString("Name");
    auto Alias = Rec->getValueAsString("Alias");
    if (!Processors.contains(Alias))
      PrintFatalError(
          Rec, "Alias '" + Name + "' references a non-existent ProcessorModel '" + Alias + "'");
    if (Processors.contains(Name))
      PrintFatalError(
          Rec, "Alias '" + Name + "' duplicates an existing ProcessorModel");
    if (!Aliases.insert(Name).second)
      PrintFatalError(
          Rec, "Alias '" + Name + "' duplicates an existing ProcessorAlias");

    OS << "  {" << StrTab.GetOrAddStringOffset(Name) << ", "
       << StrTab.GetOrAddStringOffset(Alias) << "},\n";
  }

  OS << "};\n"
     << "#undef EMIT_CPU_ALIAS\n"
     << "#endif // EMIT_CPU_ALIAS\n"
     << "\n";

  // Emit CPU information
  OS << "#ifdef EMIT_CPU_INFO\n"
     << "inline constexpr CpuInfo CpuInfos[] = {\n";

  for (const Record *Rec : RK.getAllDerivedDefinitions("ProcessorModel")) {
    auto Name = Rec->getValueAsString("Name");
    auto Features = Rec->getValueAsListOfDefs("Features");

    // "apple-latest" is backend-only, should not be accepted by TargetParser.
    if (Name == "apple-latest")
      continue;

    const Record *Arch;
    if (Name == "generic") {
      // "generic" is an exception. It does not have an architecture, and there
      // are tests that depend on e.g. -mattr=-v8.4a meaning HasV8_0aOps==false.
      // However, in TargetParser CPUInfo, it is written as 8.0-A.
      Arch = RK.getDef("HasV8_0aOps");
    } else {
      // Search for an Architecture64 in the list of features.
      auto IsArch = [](const Record *F) {
        return F->isSubClassOf("Architecture64");
      };
      auto ArchIter = llvm::find_if(Features, IsArch);
      if (ArchIter == Features.end())
        PrintFatalError(Rec, "Features must include an Architecture64.");
      Arch = *ArchIter;

      // Check there is only one Architecture in the list.
      if (llvm::count_if(Features, IsArch) > 1)
        PrintFatalError(Rec, "Features has multiple Architecture64 entries");
    }

    auto Major = Arch->getValueAsInt("Major");
    auto Minor = Arch->getValueAsInt("Minor");
    auto Profile = Arch->getValueAsString("Profile");
    auto ArchInfo = ArchInfoName(Major, Minor, Profile);
    unsigned ArchIdx =
        llvm::find(CppSpellings, ArchInfo) - CppSpellings.begin();

    checkFeatureTree(Arch);

    OS << "  {\n"
       << "    " << StrTab.GetOrAddStringOffset(Name) << ",\n"
       << "    " << ArchIdx << " /* " << ArchInfo << " */,\n"
       << "    AArch64::ExtensionBitset({\n";

    // Keep track of extensions we have seen
    StringSet<> SeenExts;
    for (const Record *E : Rec->getValueAsListOfDefs("Features"))
      // Only process subclasses of Extension
      if (E->isSubClassOf("Extension")) {
        const auto AEK = E->getValueAsString("ArchExtKindSpelling").upper();
        if (!SeenExts.insert(AEK).second)
          PrintFatalError(Rec, "feature already added: " + E->getName());
        OS << "      AArch64::" << AEK << ",\n";
      }
    OS << "    })\n"
       << "  },\n";
  }
  OS << "};\n";

  OS << "#undef EMIT_CPU_INFO\n"
     << "#endif // EMIT_CPU_INFO\n"
     << "\n";

  // Emit string table.
  OS << "#ifdef EMIT_STRTAB\n";
  StrTab.EmitStringTableDef(OS, "StrTab");
  OS << "#undef EMIT_STRTAB\n"
     << "#endif // EMIT_STRTAB\n"
     << "\n";
}

static TableGen::Emitter::Opt
    X("gen-arm-target-def", emitARMTargetDef,
      "Generate the ARM or AArch64 Architecture information header.");
