//===-- 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/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 {};
  for (const auto &A : Extensions) {
    if (ArchExt == StrTab[A.UserVisibleName] || ArchExt == StrTab[A.Alias])
      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) {
  for (const auto &E : Extensions)
    if (TargetFeature == StrTab[E.PosTargetFeature] ||
        TargetFeature == StrTab[E.NegTargetFeature])
      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);
}

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);
}
