//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
//
// 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 class wraps target description classes used by the various code
// generation TableGen backends.  This makes it easier to access the data and
// provides a single place that needs to check it for validity.  All of these
// classes abort on error conditions.
//
//===----------------------------------------------------------------------===//

#include "CodeGenTarget.h"
#include "CodeGenInstruction.h"
#include "CodeGenRegisters.h"
#include "CodeGenSchedule.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <tuple>
using namespace llvm;

static cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
static cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");

static cl::opt<unsigned>
    AsmParserNum("asmparsernum", cl::init(0),
                 cl::desc("Make -gen-asm-parser emit assembly parser #N"),
                 cl::cat(AsmParserCat));

static cl::opt<unsigned>
    AsmWriterNum("asmwriternum", cl::init(0),
                 cl::desc("Make -gen-asm-writer emit assembly writer #N"),
                 cl::cat(AsmWriterCat));

/// Returns the MVT that the specified TableGen
/// record corresponds to.
MVT llvm::getValueType(const Record *Rec) {
  return StringSwitch<MVT>(Rec->getValueAsString("LLVMName"))
#define GET_VT_ATTR(Ty, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy)      \
  .Case(#Ty, MVT::Ty)
#include "llvm/CodeGen/GenVT.inc"
#undef GET_VT_ATTR
      .Case("INVALID_SIMPLE_VALUE_TYPE", MVT::INVALID_SIMPLE_VALUE_TYPE);
}

StringRef llvm::getEnumName(MVT T) {
  // clang-format off
  switch (T.SimpleTy) {
#define GET_VT_ATTR(Ty, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy)   \
  case MVT::Ty: return "MVT::" # Ty;
#include "llvm/CodeGen/GenVT.inc"
#undef GET_VT_ATTR
  default: llvm_unreachable("ILLEGAL VALUE TYPE!");
  }
  // clang-format on
}

/// getQualifiedName - Return the name of the specified record, with a
/// namespace qualifier if the record contains one.
///
std::string llvm::getQualifiedName(const Record *R) {
  std::string Namespace;
  if (R->getValue("Namespace"))
    Namespace = R->getValueAsString("Namespace").str();
  if (Namespace.empty())
    return R->getName().str();
  return Namespace + "::" + R->getName().str();
}

CodeGenTarget::CodeGenTarget(const RecordKeeper &records)
    : Records(records), CGH(records), Intrinsics(records) {
  ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");
  if (Targets.size() == 0)
    PrintFatalError("No 'Target' subclasses defined!");
  if (Targets.size() != 1)
    PrintFatalError("Multiple subclasses of Target defined!");
  TargetRec = Targets[0];
  MacroFusions = Records.getAllDerivedDefinitions("Fusion");
}

CodeGenTarget::~CodeGenTarget() = default;

StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }

/// getInstNamespace - Find and return the target machine's instruction
/// namespace. The namespace is cached because it is requested multiple times.
StringRef CodeGenTarget::getInstNamespace() const {
  if (InstNamespace.empty()) {
    for (const CodeGenInstruction *Inst : getInstructions()) {
      // We are not interested in the "TargetOpcode" namespace.
      if (Inst->Namespace != "TargetOpcode") {
        InstNamespace = Inst->Namespace;
        break;
      }
    }
  }

  return InstNamespace;
}

StringRef CodeGenTarget::getRegNamespace() const {
  auto &RegClasses = RegBank->getRegClasses();
  return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
}

const Record *CodeGenTarget::getInstructionSet() const {
  return TargetRec->getValueAsDef("InstructionSet");
}

bool CodeGenTarget::getAllowRegisterRenaming() const {
  return TargetRec->getValueAsInt("AllowRegisterRenaming");
}

/// getAsmParser - Return the AssemblyParser definition for this target.
///
const Record *CodeGenTarget::getAsmParser() const {
  std::vector<const Record *> LI =
      TargetRec->getValueAsListOfDefs("AssemblyParsers");
  if (AsmParserNum >= LI.size())
    PrintFatalError("Target does not have an AsmParser #" +
                    Twine(AsmParserNum) + "!");
  return LI[AsmParserNum];
}

/// getAsmParserVariant - Return the AssemblyParserVariant definition for
/// this target.
///
const Record *CodeGenTarget::getAsmParserVariant(unsigned Idx) const {
  std::vector<const Record *> LI =
      TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
  if (Idx >= LI.size())
    PrintFatalError("Target does not have an AsmParserVariant #" + Twine(Idx) +
                    "!");
  return LI[Idx];
}

/// getAsmParserVariantCount - Return the AssemblyParserVariant definition
/// available for this target.
///
unsigned CodeGenTarget::getAsmParserVariantCount() const {
  return TargetRec->getValueAsListOfDefs("AssemblyParserVariants").size();
}

/// getAsmWriter - Return the AssemblyWriter definition for this target.
///
const Record *CodeGenTarget::getAsmWriter() const {
  std::vector<const Record *> LI =
      TargetRec->getValueAsListOfDefs("AssemblyWriters");
  if (AsmWriterNum >= LI.size())
    PrintFatalError("Target does not have an AsmWriter #" +
                    Twine(AsmWriterNum) + "!");
  return LI[AsmWriterNum];
}

CodeGenRegBank &CodeGenTarget::getRegBank() const {
  if (!RegBank)
    RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());
  return *RegBank;
}

/// getRegisterByName - If there is a register with the specific AsmName,
/// return it.
const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
  return getRegBank().getRegistersByName().lookup(Name);
}

const CodeGenRegisterClass &
CodeGenTarget::getRegisterClass(const Record *R) const {
  return *getRegBank().getRegClass(R);
}

std::vector<ValueTypeByHwMode>
CodeGenTarget::getRegisterVTs(const Record *R) const {
  const CodeGenRegister *Reg = getRegBank().getReg(R);
  std::vector<ValueTypeByHwMode> Result;
  for (const auto &RC : getRegBank().getRegClasses()) {
    if (RC.contains(Reg)) {
      ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();
      llvm::append_range(Result, InVTs);
    }
  }

  // Remove duplicates.
  llvm::sort(Result);
  Result.erase(llvm::unique(Result), Result.end());
  return Result;
}

void CodeGenTarget::ReadLegalValueTypes() const {
  for (const auto &RC : getRegBank().getRegClasses())
    llvm::append_range(LegalValueTypes, RC.VTs);

  // Remove duplicates.
  llvm::sort(LegalValueTypes);
  LegalValueTypes.erase(llvm::unique(LegalValueTypes), LegalValueTypes.end());
}

const Record *CodeGenTarget::getInitValueAsRegClass(
    const Init *V, bool AssumeRegClassByHwModeIsDefault) const {
  const Record *RegClassLike = getInitValueAsRegClassLike(V);
  if (!RegClassLike || RegClassLike->isSubClassOf("RegisterClass"))
    return RegClassLike;

  // FIXME: We should figure out the hwmode and dispatch. But this interface
  // is broken, we should be returning a register class. The expected uses
  // will use the same RegBanks in all modes.
  if (AssumeRegClassByHwModeIsDefault &&
      RegClassLike->isSubClassOf("RegClassByHwMode")) {
    const HwModeSelect &ModeSelect = getHwModes().getHwModeSelect(RegClassLike);
    if (ModeSelect.Items.empty())
      return nullptr;
    return ModeSelect.Items.front().second;
  }

  return nullptr;
}

const Record *CodeGenTarget::getInitValueAsRegClassLike(const Init *V) const {
  const DefInit *VDefInit = dyn_cast<DefInit>(V);
  if (!VDefInit)
    return nullptr;

  const Record *RegClass = VDefInit->getDef();
  if (RegClass->isSubClassOf("RegisterOperand"))
    return RegClass->getValueAsDef("RegClass");

  return RegClass->isSubClassOf("RegisterClassLike") ? RegClass : nullptr;
}

CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
  if (!SchedModels)
    SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);
  return *SchedModels;
}

void CodeGenTarget::ReadInstructions() const {
  ArrayRef<const Record *> Insts =
      Records.getAllDerivedDefinitions("Instruction");
  if (Insts.size() <= 2)
    PrintFatalError("No 'Instruction' subclasses defined!");

  // Parse the instructions defined in the .td file.
  for (const Record *R : Insts) {
    auto [II, _] =
        InstructionMap.try_emplace(R, std::make_unique<CodeGenInstruction>(R));
    HasVariableLengthEncodings |= II->second->isVariableLengthEncoding();
  }
}

static const CodeGenInstruction *GetInstByName(
    StringRef Name,
    const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts,
    const RecordKeeper &Records) {
  const Record *Rec = Records.getDef(Name);

  const auto I = Insts.find(Rec);
  if (!Rec || I == Insts.end())
    PrintFatalError("Could not find '" + Name + "' instruction!");
  return I->second.get();
}

static const char *FixedInstrs[] = {
#define HANDLE_TARGET_OPCODE(OPC) #OPC,
#include "llvm/Support/TargetOpcodes.def"
};

unsigned CodeGenTarget::getNumFixedInstructions() {
  return std::size(FixedInstrs);
}

/// Return all of the instructions defined by the target, ordered by
/// their enum value.
void CodeGenTarget::ComputeInstrsByEnum() const {
  const auto &InstMap = getInstructionMap();
  for (const char *Name : FixedInstrs) {
    const CodeGenInstruction *Instr = GetInstByName(Name, InstMap, Records);
    assert(Instr && "Missing target independent instruction");
    assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
    InstrsByEnum.push_back(Instr);
  }
  unsigned EndOfPredefines = InstrsByEnum.size();
  assert(EndOfPredefines == getNumFixedInstructions() &&
         "Missing generic opcode");

  [[maybe_unused]] unsigned SkippedInsts = 0;

  for (const auto &[_, CGIUp] : InstMap) {
    const CodeGenInstruction *CGI = CGIUp.get();
    if (CGI->Namespace != "TargetOpcode") {

      if (CGI->TheDef->isSubClassOf(
              "TargetSpecializedStandardPseudoInstruction")) {
        ++SkippedInsts;
        continue;
      }

      InstrsByEnum.push_back(CGI);
      NumPseudoInstructions += CGI->TheDef->getValueAsBit("isPseudo");
    }
  }

  assert(InstrsByEnum.size() + SkippedInsts == InstMap.size() &&
         "Missing predefined instr");

  // All of the instructions are now in random order based on the map iteration.
  llvm::sort(
      InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
      [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
        const Record &D1 = *Rec1->TheDef;
        const Record &D2 = *Rec2->TheDef;
        // Sort all pseudo instructions before non-pseudo ones, and sort by name
        // within.
        return std::tuple(!Rec1->isPseudo, D1.getName()) <
               std::tuple(!Rec2->isPseudo, D2.getName());
      });

  // Assign an enum value to each instruction according to the sorted order.
  for (const auto &[Idx, Inst] : enumerate(InstrsByEnum))
    Inst->EnumVal = Idx;
}

/// isLittleEndianEncoding - Return whether this target encodes its instruction
/// in little-endian format, i.e. bits laid out in the order [0..n]
///
bool CodeGenTarget::isLittleEndianEncoding() const {
  return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
}

/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
/// encodings, reverse the bit order of all instructions.
void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
  if (!isLittleEndianEncoding())
    return;

  for (const Record *R :
       Records.getAllDerivedDefinitions("InstructionEncoding")) {
    if (R->getValueAsString("Namespace") == "TargetOpcode" ||
        R->getValueAsBit("isPseudo"))
      continue;

    const BitsInit *BI = R->getValueAsBitsInit("Inst");

    unsigned numBits = BI->getNumBits();

    SmallVector<const Init *, 16> NewBits(numBits);

    for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
      unsigned bitSwapIdx = numBits - bit - 1;
      const Init *OrigBit = BI->getBit(bit);
      const Init *BitSwap = BI->getBit(bitSwapIdx);
      NewBits[bit] = BitSwap;
      NewBits[bitSwapIdx] = OrigBit;
    }
    if (numBits % 2) {
      unsigned middle = (numBits + 1) / 2;
      NewBits[middle] = BI->getBit(middle);
    }

    RecordKeeper &MutableRC = const_cast<RecordKeeper &>(Records);
    const BitsInit *NewBI = BitsInit::get(MutableRC, NewBits);

    // Update the bits in reversed order so that emitters will get the correct
    // endianness.
    // FIXME: Eliminate mutation of TG records by creating a helper function
    // to reverse bits and maintain a cache instead of mutating records.
    Record *MutableR = const_cast<Record *>(R);
    MutableR->getValue("Inst")->setValue(NewBI);
  }
}

/// guessInstructionProperties - Return true if it's OK to guess instruction
/// properties instead of raising an error.
///
/// This is configurable as a temporary migration aid. It will eventually be
/// permanently false.
bool CodeGenTarget::guessInstructionProperties() const {
  return getInstructionSet()->getValueAsBit("guessInstructionProperties");
}

//===----------------------------------------------------------------------===//
// ComplexPattern implementation
//
ComplexPattern::ComplexPattern(const Record *R) {
  Ty = R->getValueAsDef("Ty");
  NumOperands = R->getValueAsInt("NumOperands");
  SelectFunc = R->getValueAsString("SelectFunc").str();
  RootNodes = R->getValueAsListOfDefs("RootNodes");

  // FIXME: This is a hack to statically increase the priority of patterns which
  // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
  // possible pattern match we'll need to dynamically calculate the complexity
  // of all patterns a dag can potentially map to.
  int64_t RawComplexity = R->getValueAsInt("Complexity");
  if (RawComplexity == -1)
    Complexity = NumOperands * 3;
  else
    Complexity = RawComplexity;

  // FIXME: Why is this different from parseSDPatternOperatorProperties?
  // Parse the properties.
  Properties = 0;
  for (const Record *Prop : R->getValueAsListOfDefs("Properties")) {
    if (Prop->getName() == "SDNPHasChain") {
      Properties |= 1 << SDNPHasChain;
    } else if (Prop->getName() == "SDNPOptInGlue") {
      Properties |= 1 << SDNPOptInGlue;
    } else if (Prop->getName() == "SDNPMayStore") {
      Properties |= 1 << SDNPMayStore;
    } else if (Prop->getName() == "SDNPMayLoad") {
      Properties |= 1 << SDNPMayLoad;
    } else if (Prop->getName() == "SDNPSideEffect") {
      Properties |= 1 << SDNPSideEffect;
    } else if (Prop->getName() == "SDNPMemOperand") {
      Properties |= 1 << SDNPMemOperand;
    } else if (Prop->getName() == "SDNPVariadic") {
      Properties |= 1 << SDNPVariadic;
    } else {
      PrintFatalError(R->getLoc(),
                      "Unsupported SD Node property '" + Prop->getName() +
                          "' on ComplexPattern '" + R->getName() + "'!");
    }
  }

  WantsRoot = R->getValueAsBit("WantsRoot");
  WantsParent = R->getValueAsBit("WantsParent");
}
