//===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a target parser to recognise AArch64 hardware features
// such as FPU/CPU/ARCH and extension names.
//
//===----------------------------------------------------------------------===//

#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/ARMTargetParserCommon.h"
#include "llvm/TargetParser/Triple.h"
#include <cctype>
#include <vector>

#define DEBUG_TYPE "target-parser"

using namespace llvm;

#define EMIT_FMV_INFO
#include "llvm/TargetParser/AArch64TargetParserDef.inc"

static unsigned checkArchVersion(llvm::StringRef Arch) {
  if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
    return (Arch[1] - 48);
  return 0;
}

const AArch64::ArchInfo *AArch64::getArchForCpu(StringRef CPU) {
  // Note: this now takes cpu aliases into account
  std::optional<CpuInfo> Cpu = parseCpu(CPU);
  if (!Cpu)
    return nullptr;
  return &ArchInfos[Cpu->ArchIdx];
}

std::optional<AArch64::ArchInfo> AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
  for (const auto &A : AArch64::ArchInfos)
    if (A.getSubArch() == SubArch)
      return A;
  return {};
}

std::optional<AArch64::FMVInfo> lookupFMVByID(AArch64::ArchExtKind ExtID) {
  for (const AArch64::FMVInfo &Info : AArch64::getFMVInfo())
    if (Info.ID == ExtID)
      return Info;
  return {};
}

std::optional<AArch64::FMVInfo> getFMVInfoFrom(StringRef Feature) {
  std::optional<AArch64::FMVInfo> FMV = AArch64::parseFMVExtension(Feature);
  if (!FMV && Feature.starts_with('+'))
    if (std::optional<AArch64::ExtensionInfo> Ext =
            AArch64::targetFeatureToExtension(Feature))
      FMV = lookupFMVByID(Ext->ID);
  return FMV;
}

APInt AArch64::getFMVPriority(ArrayRef<StringRef> Features) {
  // Transitively enable the Arch Extensions which correspond to each feature.
  ExtensionSet FeatureBits;
  APInt PriorityMask = APInt::getZero(128);
  for (const StringRef Feature : Features) {
    if (std::optional<FMVInfo> FMV = getFMVInfoFrom(Feature)) {
      // FMV feature without a corresponding Arch Extension may affect priority
      if (FMV->ID)
        FeatureBits.enable(*FMV->ID);
      else
        PriorityMask.setBit(FMV->PriorityBit);
    }
  }

  // Construct a bitmask for all the transitively enabled Arch Extensions.
  for (const FMVInfo &Info : getFMVInfo())
    if (Info.ID && FeatureBits.Enabled.test(*Info.ID))
      PriorityMask.setBit(Info.PriorityBit);

  return PriorityMask;
}

APInt AArch64::getCpuSupportsMask(ArrayRef<StringRef> Features) {
  // Transitively enable the Arch Extensions which correspond to each feature.
  ExtensionSet FeatureBits;
  for (const StringRef Feature : Features)
    if (std::optional<FMVInfo> FMV = getFMVInfoFrom(Feature))
      if (FMV->ID)
        FeatureBits.enable(*FMV->ID);

  // Construct a bitmask for all the transitively enabled Arch Extensions.
  APInt FeaturesMask = APInt::getZero(128);
  for (const FMVInfo &Info : getFMVInfo())
    if (Info.ID && FeatureBits.Enabled.test(*Info.ID))
      FeaturesMask.setBit(*Info.FeatureBit);

  return FeaturesMask;
}

bool AArch64::getExtensionFeatures(
    const AArch64::ExtensionBitset &InputExts,
    std::vector<StringRef> &Features) {
  for (const auto &E : Extensions)
    /* INVALID and NONE have no feature name. */
    if (InputExts.test(E.ID))
      Features.push_back(StrTab[E.PosTargetFeature]);

  return true;
}

StringRef AArch64::resolveCPUAlias(StringRef Name) {
  for (const auto &A : CpuAliases)
    if (StrTab[A.AltName] == Name)
      return StrTab[A.Name];
  return Name;
}

StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
  bool IsNegated = ArchExt.starts_with("no");
  StringRef ArchExtBase = IsNegated ? ArchExt.drop_front(2) : ArchExt;

  if (auto AE = parseArchExtension(ArchExtBase))
    return StrTab[IsNegated ? AE->NegTargetFeature : AE->PosTargetFeature];
  return StringRef();
}

void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
  for (const auto &C : CpuInfos)
    Values.push_back(StrTab[C.Name]);

  for (const auto &Alias : CpuAliases)
    // The apple-latest alias is backend only, do not expose it to clang's -mcpu.
    if (StrTab[Alias.AltName] != "apple-latest")
      Values.push_back(StrTab[Alias.AltName]);

  llvm::sort(Values);
}

bool AArch64::isX18ReservedByDefault(const Triple &TT) {
  return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
         TT.isOSWindows() || TT.isOHOSFamily();
}

// Allows partial match, ex. "v8a" matches "armv8a".
const AArch64::ArchInfo *AArch64::parseArch(StringRef Arch) {
  Arch = llvm::ARM::getCanonicalArchName(Arch);
  if (checkArchVersion(Arch) < 8)
    return {};

  StringRef Syn = llvm::ARM::getArchSynonym(Arch);
  for (const auto &A : ArchInfos) {
    if (StrTab[A.Name].ends_with(Syn))
      return &A;
  }
  return {};
}

std::optional<AArch64::ExtensionInfo>
AArch64::parseArchExtension(StringRef ArchExt) {
  if (ArchExt.empty())
    return {};
  static const DenseMap<StringRef, const ExtensionInfo *> NameToExt = [] {
    DenseMap<StringRef, const ExtensionInfo *> Map;
    for (const auto &A : Extensions)
      for (StringRef Name : {StrTab[A.UserVisibleName], StrTab[A.Alias]})
        Map.try_emplace(Name, &A);
    return Map;
  }();
  if (const ExtensionInfo *A = NameToExt.lookup(ArchExt))
    return *A;
  return {};
}

std::optional<AArch64::FMVInfo> AArch64::parseFMVExtension(StringRef FMVExt) {
  // FIXME introduce general alias functionality, or remove this exception.
  if (FMVExt == "rdma")
    FMVExt = "rdm";

  for (const auto &I : getFMVInfo()) {
    if (FMVExt == I.Name)
      return I;
  }
  return {};
}

std::optional<AArch64::ExtensionInfo>
AArch64::targetFeatureToExtension(StringRef TargetFeature) {
  static const DenseMap<StringRef, const ExtensionInfo *> FeatureToExt = [] {
    DenseMap<StringRef, const ExtensionInfo *> Map;
    for (const auto &E : Extensions)
      for (StringRef Feature :
           {StrTab[E.PosTargetFeature], StrTab[E.NegTargetFeature]})
        Map.try_emplace(Feature, &E);
    return Map;
  }();
  if (const ExtensionInfo *E = FeatureToExt.lookup(TargetFeature))
    return *E;
  return {};
}

std::optional<AArch64::CpuInfo> AArch64::parseCpu(StringRef Name) {
  // Resolve aliases first.
  Name = resolveCPUAlias(Name);

  // Then find the CPU name.
  for (const auto &C : CpuInfos)
    if (Name == StrTab[C.Name])
      return C;

  return {};
}

void AArch64::PrintSupportedExtensions() {
  outs() << "All available -march extensions for AArch64\n\n"
         << "    " << left_justify("Name", 20)
         << left_justify("Architecture Feature(s)", 55)
         << "Description\n";
  for (const auto &Ext : Extensions) {
    // Extensions without a feature cannot be used with -march.
    if (Ext.UserVisibleName.value() && Ext.PosTargetFeature.value()) {
      // NB: StringTable strings are null-terminated, so the StringRef can be
      // used as C string without further conversion.
      outs() << "    "
             << format(!Ext.Description.value() ? "%-20s%s\n"
                                                : "%-20s%-55s%s\n",
                       StrTab[Ext.UserVisibleName].data(),
                       StrTab[Ext.ArchFeatureName].data(),
                       StrTab[Ext.Description].data());
    }
  }
}

void
AArch64::printEnabledExtensions(const std::set<StringRef> &EnabledFeatureNames) {
  outs() << "Extensions enabled for the given AArch64 target\n\n"
         << "    " << left_justify("Architecture Feature(s)", 55)
         << "Description\n";
  std::vector<ExtensionInfo> EnabledExtensionsInfo;
  for (const auto &FeatureName : EnabledFeatureNames) {
    std::string PosFeatureName = '+' + FeatureName.str();
    if (auto ExtInfo = targetFeatureToExtension(PosFeatureName))
      EnabledExtensionsInfo.push_back(*ExtInfo);
  }

  std::sort(EnabledExtensionsInfo.begin(), EnabledExtensionsInfo.end(),
            [](const ExtensionInfo &Lhs, const ExtensionInfo &Rhs) {
              return StrTab[Lhs.ArchFeatureName] < StrTab[Rhs.ArchFeatureName];
            });

  for (const auto &Ext : EnabledExtensionsInfo) {
    // NB: StringTable strings are null-terminated, so the StringRef can be used
    // as C string without further conversion.
    outs() << "    "
           << format("%-55s%s\n", StrTab[Ext.ArchFeatureName].data(),
                     StrTab[Ext.Description].data());
  }
}

const llvm::AArch64::ExtensionInfo &
lookupExtensionByID(llvm::AArch64::ArchExtKind ExtID) {
  for (const auto &E : llvm::AArch64::Extensions)
    if (E.ID == ExtID)
      return E;
  llvm_unreachable("Invalid extension ID");
}

void AArch64::ExtensionSet::enable(ArchExtKind E) {
  if (Enabled.test(E))
    return;

  LLVM_DEBUG(llvm::dbgs() << "Enable "
                          << StrTab[lookupExtensionByID(E).UserVisibleName]
                          << "\n");

  Touched.set(E);
  Enabled.set(E);

  // Recursively enable all features that this one depends on. This handles all
  // of the simple cases, where the behaviour doesn't depend on the base
  // architecture version.
  for (auto Dep : ExtensionDependencies)
    if (E == Dep.Later)
      enable(Dep.Earlier);

  // Special cases for dependencies which vary depending on the base
  // architecture version.
  if (BaseArch) {
    // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+
    if (E == AEK_FP16 && BaseArch->is_superset(ARMV8_4A) &&
        !BaseArch->is_superset(ARMV9A))
      enable(AEK_FP16FML);

    // For v8.4A+ and v9.0A+, +crypto also enables +sha3 and +sm4.
    if (E == AEK_CRYPTO && BaseArch->is_superset(ARMV8_4A)) {
      enable(AEK_SHA3);
      enable(AEK_SM4);
    }
  }
}

void AArch64::ExtensionSet::disable(ArchExtKind E) {
  // -crypto always disables aes, sha2, sha3 and sm4, even for architectures
  // where the latter two would not be enabled by +crypto.
  if (E == AEK_CRYPTO) {
    disable(AEK_AES);
    disable(AEK_SHA2);
    disable(AEK_SHA3);
    disable(AEK_SM4);
  }

  // sve2-aes was historically associated with both FEAT_SVE2 and FEAT_SVE_AES,
  // the latter is now associated with sve-aes and sve2-aes has become shorthand
  // for +sve2+sve-aes. For backwards compatibility, when we disable sve2-aes we
  // must also disable sve-aes.
  if (E == AEK_SVE2AES)
    disable(AEK_SVEAES);

  // sve2-sm4 was historically associated with both FEAT_SVE2 and
  // FEAT_SVE_SM4, the latter is now associated with sve-sm4 and sve2-sm4 has
  // become shorthand for +sve2+sve-sm4. For backwards compatibility, when we
  // disable sve2-sm4 we must also disable sve-sm4.
  if (E == AEK_SVE2SM4)
    disable(AEK_SVESM4);

  // sve2-sha3 was historically associated with both FEAT_SVE2 and
  // FEAT_SVE_SHA3, the latter is now associated with sve-sha3 and sve2-sha3 has
  // become shorthand for +sve2+sve-sha3. For backwards compatibility, when we
  // disable sve2-sha3 we must also disable sve-sha3.
  if (E == AEK_SVE2SHA3)
    disable(AEK_SVESHA3);

  if (E == AEK_SVE2BITPERM){
    disable(AEK_SVEBITPERM);
    disable(AEK_SVE2);
  }

  if (!Enabled.test(E))
    return;

  LLVM_DEBUG(llvm::dbgs() << "Disable "
                          << StrTab[lookupExtensionByID(E).UserVisibleName]
                          << "\n");

  Touched.set(E);
  Enabled.reset(E);

  // Recursively disable all features that depends on this one.
  for (auto Dep : ExtensionDependencies)
    if (E == Dep.Earlier)
      disable(Dep.Later);
}

void AArch64::ExtensionSet::addCPUDefaults(const CpuInfo &CPU) {
  LLVM_DEBUG(llvm::dbgs() << "addCPUDefaults(" << StrTab[CPU.Name] << ")\n");
  BaseArch = &ArchInfos[CPU.ArchIdx];

  for (const auto &E : Extensions)
    if (CPU.DefaultExtensions.test(E.ID))
      enable(E.ID);

  // Workaround: mark extensions implied by the base architecture as Enabled
  // so that an explicit "+nofeat" is not silently ignored. We set Enabled
  // directly instead of calling enable() to keep them out of Touched,
  // preserving the previous output as much as possible and avoiding a flood
  // of redundant "+feat" entries.
  for (const auto &E : Extensions)
    if (BaseArch->DefaultExts.test(E.ID))
      Enabled.set(E.ID);
}

void AArch64::ExtensionSet::addArchDefaults(const ArchInfo &Arch) {
  LLVM_DEBUG(llvm::dbgs() << "addArchDefaults(" << StrTab[Arch.Name] << ")\n");
  BaseArch = &Arch;

  for (const auto &E : Extensions)
    if (Arch.DefaultExts.test(E.ID))
      enable(E.ID);
}

bool AArch64::ExtensionSet::parseModifier(StringRef Modifier,
                                          const bool AllowNoDashForm) {
  LLVM_DEBUG(llvm::dbgs() << "parseModifier(" << Modifier << ")\n");

  size_t NChars = 0;
  // The "no-feat" form is allowed in the target attribute but nowhere else.
  if (AllowNoDashForm && Modifier.starts_with("no-"))
    NChars = 3;
  else if (Modifier.starts_with("no"))
    NChars = 2;
  bool IsNegated = NChars != 0;
  StringRef ArchExt = Modifier.drop_front(NChars);

  if (auto AE = parseArchExtension(ArchExt)) {
    if (IsNegated)
      disable(AE->ID);
    else
      enable(AE->ID);
    return true;
  }
  return false;
}

void AArch64::ExtensionSet::reconstructFromParsedFeatures(
    const std::vector<std::string> &Features,
    std::vector<std::string> &NonExtensions) {
  assert(Touched.none() && "Bitset already initialized");
  for (auto &F : Features) {
    bool IsNegated = F[0] == '-';
    if (auto AE = targetFeatureToExtension(F)) {
      Touched.set(AE->ID);
      if (IsNegated)
        Enabled.reset(AE->ID);
      else
        Enabled.set(AE->ID);
      continue;
    }
    NonExtensions.push_back(F);
  }
}

void AArch64::ExtensionSet::dump() const {
  std::vector<StringRef> Features;
  toLLVMFeatureList(Features);
  for (StringRef F : Features)
    llvm::outs() << F << " ";
  llvm::outs() << "\n";
}

const AArch64::ExtensionInfo &
AArch64::getExtensionByID(AArch64::ArchExtKind ExtID) {
  return lookupExtensionByID(ExtID);
}
