//===- 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/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 (MVT::SimpleValueType)Rec->getValueAsInt("Value");
}

StringRef llvm::getEnumName(MVT T) {
  // clang-format off
  switch (T.SimpleTy) {
#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy)   \
  case MVT::Ty: return "MVT::" # Ty;
#include "llvm/CodeGen/GenVT.inc"
  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");
}
