//===-- 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 &Cpu->Arch;
}

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 && *Info.ID == ExtID)
      return Info;
  return {};
}

uint64_t AArch64::getFMVPriority(ArrayRef<StringRef> Features) {
  // Transitively enable the Arch Extensions which correspond to each feature.
  ExtensionSet FeatureBits;
  for (const StringRef Feature : Features) {
    std::optional<FMVInfo> FMV = parseFMVExtension(Feature);
    if (!FMV) {
      if (std::optional<ExtensionInfo> Info = targetFeatureToExtension(Feature))
        FMV = lookupFMVByID(Info->ID);
    }
    if (FMV && FMV->ID)
      FeatureBits.enable(*FMV->ID);
  }

  // Construct a bitmask for all the transitively enabled Arch Extensions.
  uint64_t PriorityMask = 0;
  for (const FMVInfo &Info : getFMVInfo())
    if (Info.ID && FeatureBits.Enabled.test(*Info.ID))
      PriorityMask |= (1ULL << Info.PriorityBit);

  return PriorityMask;
}

uint64_t 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> Info = parseFMVExtension(Feature))
      if (Info->ID)
        FeatureBits.enable(*Info->ID);

  // Construct a bitmask for all the transitively enabled Arch Extensions.
  uint64_t FeaturesMask = 0;
  for (const FMVInfo &Info : getFMVInfo())
    if (Info.ID && FeatureBits.Enabled.test(*Info.ID))
      FeaturesMask |= (1ULL << 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) && !E.PosTargetFeature.empty())
      Features.push_back(E.PosTargetFeature);

  return true;
}

StringRef AArch64::resolveCPUAlias(StringRef Name) {
  for (const auto &A : CpuAliases)
    if (A.AltName == Name)
      return 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)) {
    assert(!(AE.has_value() && AE->NegTargetFeature.empty()));
    return IsNegated ? AE->NegTargetFeature : AE->PosTargetFeature;
  }

  return StringRef();
}

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

  for (const auto &Alias : CpuAliases)
    // The apple-latest alias is backend only, do not expose it to clang's -mcpu.
    if (Alias.AltName != "apple-latest")
      Values.push_back(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 (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 == A.UserVisibleName || ArchExt == 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 == E.PosTargetFeature)
      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 == 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.empty() && !Ext.PosTargetFeature.empty()) {
      outs() << "    "
             << format(Ext.Description.empty() ? "%-20s%s\n" : "%-20s%-55s%s\n",
                       Ext.UserVisibleName.str().c_str(),
                       Ext.ArchFeatureName.str().c_str(),
                       Ext.Description.str().c_str());
    }
  }
}

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 Lhs.ArchFeatureName < Rhs.ArchFeatureName;
            });

  for (const auto &Ext : EnabledExtensionsInfo) {
    outs() << "    "
           << format("%-55s%s\n",
                     Ext.ArchFeatureName.str().c_str(),
                     Ext.Description.str().c_str());
  }
}

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

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

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

  LLVM_DEBUG(llvm::dbgs() << "Disable " << 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(" << CPU.Name << ")\n");
  BaseArch = &CPU.Arch;

  AArch64::ExtensionBitset CPUExtensions = CPU.getImpliedExtensions();
  for (const auto &E : Extensions)
    if (CPUExtensions.test(E.ID))
      enable(E.ID);
}

void AArch64::ExtensionSet::addArchDefaults(const ArchInfo &Arch) {
  LLVM_DEBUG(llvm::dbgs() << "addArchDefaults(" << 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 (AE->PosTargetFeature.empty() || AE->NegTargetFeature.empty())
      return false;
    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);
}
