//===- CodeGenMapTable.cpp - Instruction Mapping Table Generator ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// CodeGenMapTable provides functionality for the TabelGen to create
// relation mapping between instructions. Relation models are defined using
// InstrMapping as a base class. This file implements the functionality which
// parses these definitions and generates relation maps using the information
// specified there. These maps are emitted as tables in the XXXGenInstrInfo.inc
// file along with the functions to query them.
//
// A relationship model to relate non-predicate instructions with their
// predicated true/false forms can be defined as follows:
//
// def getPredOpcode : InstrMapping {
//  let FilterClass = "PredRel";
//  let RowFields = ["BaseOpcode"];
//  let ColFields = ["PredSense"];
//  let KeyCol = ["none"];
//  let ValueCols = [["true"], ["false"]]; }
//
// CodeGenMapTable parses this map and generates a table in XXXGenInstrInfo.inc
// file that contains the instructions modeling this relationship. This table
// is defined in the function
// "int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)"
// that can be used to retrieve the predicated form of the instruction by
// passing its opcode value and the predicate sense (true/false) of the desired
// instruction as arguments.
//
// Short description of the algorithm:
//
// 1) Iterate through all the records that derive from "InstrMapping" class.
// 2) For each record, filter out instructions based on the FilterClass value.
// 3) Iterate through this set of instructions and insert them into
// RowInstrMap map based on their RowFields values. RowInstrMap is keyed by the
// vector of RowFields values and contains vectors of Records (instructions) as
// values. RowFields is a list of fields that are required to have the same
// values for all the instructions appearing in the same row of the relation
// table. All the instructions in a given row of the relation table have some
// sort of relationship with the key instruction defined by the corresponding
// relationship model.
//
// Ex: RowInstrMap(RowVal1, RowVal2, ...) -> [Instr1, Instr2, Instr3, ... ]
// Here Instr1, Instr2, Instr3 have same values (RowVal1, RowVal2) for
// RowFields. These groups of instructions are later matched against ValueCols
// to determine the column they belong to, if any.
//
// While building the RowInstrMap map, collect all the key instructions in
// KeyInstrVec. These are the instructions having the same values as KeyCol
// for all the fields listed in ColFields.
//
// For Example:
//
// Relate non-predicate instructions with their predicated true/false forms.
//
// def getPredOpcode : InstrMapping {
//  let FilterClass = "PredRel";
//  let RowFields = ["BaseOpcode"];
//  let ColFields = ["PredSense"];
//  let KeyCol = ["none"];
//  let ValueCols = [["true"], ["false"]]; }
//
// Here, only instructions that have "none" as PredSense will be selected as key
// instructions.
//
// 4) For each key instruction, get the group of instructions that share the
// same key-value as the key instruction from RowInstrMap. Iterate over the list
// of columns in ValueCols (it is defined as a list<list<string> >. Therefore,
// it can specify multi-column relationships). For each column, find the
// instruction from the group that matches all the values for the column.
// Multiple matches are not allowed.
//
//===----------------------------------------------------------------------===//

#include "CodeGenTarget.h"
#include "llvm/Support/Format.h"
#include "llvm/TableGen/Error.h"
using namespace llvm;
typedef std::map<std::string, std::vector<Record*> > InstrRelMapTy;

typedef std::map<std::vector<Init*>, std::vector<Record*> > RowInstrMapTy;

namespace {

//===----------------------------------------------------------------------===//
// This class is used to represent InstrMapping class defined in Target.td file.
class InstrMap {
private:
  std::string Name;
  std::string FilterClass;
  ListInit *RowFields;
  ListInit *ColFields;
  ListInit *KeyCol;
  std::vector<ListInit*> ValueCols;

public:
  InstrMap(Record* MapRec) {
    Name = MapRec->getName();

    // FilterClass - It's used to reduce the search space only to the
    // instructions that define the kind of relationship modeled by
    // this InstrMapping object/record.
    const RecordVal *Filter = MapRec->getValue("FilterClass");
    FilterClass = Filter->getValue()->getAsUnquotedString();

    // List of fields/attributes that need to be same across all the
    // instructions in a row of the relation table.
    RowFields = MapRec->getValueAsListInit("RowFields");

    // List of fields/attributes that are constant across all the instruction
    // in a column of the relation table. Ex: ColFields = 'predSense'
    ColFields = MapRec->getValueAsListInit("ColFields");

    // Values for the fields/attributes listed in 'ColFields'.
    // Ex: KeyCol = 'noPred' -- key instruction is non-predicated
    KeyCol = MapRec->getValueAsListInit("KeyCol");

    // List of values for the fields/attributes listed in 'ColFields', one for
    // each column in the relation table.
    //
    // Ex: ValueCols = [['true'],['false']] -- it results two columns in the
    // table. First column requires all the instructions to have predSense
    // set to 'true' and second column requires it to be 'false'.
    ListInit *ColValList = MapRec->getValueAsListInit("ValueCols");

    // Each instruction map must specify at least one column for it to be valid.
    if (ColValList->empty())
      PrintFatalError(MapRec->getLoc(), "InstrMapping record `" +
        MapRec->getName() + "' has empty " + "`ValueCols' field!");

    for (Init *I : ColValList->getValues()) {
      auto *ColI = cast<ListInit>(I);

      // Make sure that all the sub-lists in 'ValueCols' have same number of
      // elements as the fields in 'ColFields'.
      if (ColI->size() != ColFields->size())
        PrintFatalError(MapRec->getLoc(), "Record `" + MapRec->getName() +
          "', field `ValueCols' entries don't match with " +
          " the entries in 'ColFields'!");
      ValueCols.push_back(ColI);
    }
  }

  std::string getName() const {
    return Name;
  }

  std::string getFilterClass() {
    return FilterClass;
  }

  ListInit *getRowFields() const {
    return RowFields;
  }

  ListInit *getColFields() const {
    return ColFields;
  }

  ListInit *getKeyCol() const {
    return KeyCol;
  }

  const std::vector<ListInit*> &getValueCols() const {
    return ValueCols;
  }
};
} // end anonymous namespace


//===----------------------------------------------------------------------===//
// class MapTableEmitter : It builds the instruction relation maps using
// the information provided in InstrMapping records. It outputs these
// relationship maps as tables into XXXGenInstrInfo.inc file along with the
// functions to query them.

namespace {
class MapTableEmitter {
private:
//  std::string TargetName;
  const CodeGenTarget &Target;
  // InstrMapDesc - InstrMapping record to be processed.
  InstrMap InstrMapDesc;

  // InstrDefs - list of instructions filtered using FilterClass defined
  // in InstrMapDesc.
  std::vector<Record*> InstrDefs;

  // RowInstrMap - maps RowFields values to the instructions. It's keyed by the
  // values of the row fields and contains vector of records as values.
  RowInstrMapTy RowInstrMap;

  // KeyInstrVec - list of key instructions.
  std::vector<Record*> KeyInstrVec;
  DenseMap<Record*, std::vector<Record*> > MapTable;

public:
  MapTableEmitter(CodeGenTarget &Target, RecordKeeper &Records, Record *IMRec):
                  Target(Target), InstrMapDesc(IMRec) {
    const std::string FilterClass = InstrMapDesc.getFilterClass();
    InstrDefs = Records.getAllDerivedDefinitions(FilterClass);
  }

  void buildRowInstrMap();

  // Returns true if an instruction is a key instruction, i.e., its ColFields
  // have same values as KeyCol.
  bool isKeyColInstr(Record* CurInstr);

  // Find column instruction corresponding to a key instruction based on the
  // constraints for that column.
  Record *getInstrForColumn(Record *KeyInstr, ListInit *CurValueCol);

  // Find column instructions for each key instruction based
  // on ValueCols and store them into MapTable.
  void buildMapTable();

  void emitBinSearch(raw_ostream &OS, unsigned TableSize);
  void emitTablesWithFunc(raw_ostream &OS);
  unsigned emitBinSearchTable(raw_ostream &OS);

  // Lookup functions to query binary search tables.
  void emitMapFuncBody(raw_ostream &OS, unsigned TableSize);

};
} // end anonymous namespace


//===----------------------------------------------------------------------===//
// Process all the instructions that model this relation (alreday present in
// InstrDefs) and insert them into RowInstrMap which is keyed by the values of
// the fields listed as RowFields. It stores vectors of records as values.
// All the related instructions have the same values for the RowFields thus are
// part of the same key-value pair.
//===----------------------------------------------------------------------===//

void MapTableEmitter::buildRowInstrMap() {
  for (Record *CurInstr : InstrDefs) {
    std::vector<Init*> KeyValue;
    ListInit *RowFields = InstrMapDesc.getRowFields();
    for (Init *RowField : RowFields->getValues()) {
      RecordVal *RecVal = CurInstr->getValue(RowField);
      if (RecVal == nullptr)
        PrintFatalError(CurInstr->getLoc(), "No value " +
                        RowField->getAsString() + " found in \"" +
                        CurInstr->getName() + "\" instruction description.");
      Init *CurInstrVal = RecVal->getValue();
      KeyValue.push_back(CurInstrVal);
    }

    // Collect key instructions into KeyInstrVec. Later, these instructions are
    // processed to assign column position to the instructions sharing
    // their KeyValue in RowInstrMap.
    if (isKeyColInstr(CurInstr))
      KeyInstrVec.push_back(CurInstr);

    RowInstrMap[KeyValue].push_back(CurInstr);
  }
}

//===----------------------------------------------------------------------===//
// Return true if an instruction is a KeyCol instruction.
//===----------------------------------------------------------------------===//

bool MapTableEmitter::isKeyColInstr(Record* CurInstr) {
  ListInit *ColFields = InstrMapDesc.getColFields();
  ListInit *KeyCol = InstrMapDesc.getKeyCol();

  // Check if the instruction is a KeyCol instruction.
  bool MatchFound = true;
  for (unsigned j = 0, endCF = ColFields->size();
      (j < endCF) && MatchFound; j++) {
    RecordVal *ColFieldName = CurInstr->getValue(ColFields->getElement(j));
    std::string CurInstrVal = ColFieldName->getValue()->getAsUnquotedString();
    std::string KeyColValue = KeyCol->getElement(j)->getAsUnquotedString();
    MatchFound = (CurInstrVal == KeyColValue);
  }
  return MatchFound;
}

//===----------------------------------------------------------------------===//
// Build a map to link key instructions with the column instructions arranged
// according to their column positions.
//===----------------------------------------------------------------------===//

void MapTableEmitter::buildMapTable() {
  // Find column instructions for a given key based on the ColField
  // constraints.
  const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
  unsigned NumOfCols = ValueCols.size();
  for (Record *CurKeyInstr : KeyInstrVec) {
    std::vector<Record*> ColInstrVec(NumOfCols);

    // Find the column instruction based on the constraints for the column.
    for (unsigned ColIdx = 0; ColIdx < NumOfCols; ColIdx++) {
      ListInit *CurValueCol = ValueCols[ColIdx];
      Record *ColInstr = getInstrForColumn(CurKeyInstr, CurValueCol);
      ColInstrVec[ColIdx] = ColInstr;
    }
    MapTable[CurKeyInstr] = ColInstrVec;
  }
}

//===----------------------------------------------------------------------===//
// Find column instruction based on the constraints for that column.
//===----------------------------------------------------------------------===//

Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
                                           ListInit *CurValueCol) {
  ListInit *RowFields = InstrMapDesc.getRowFields();
  std::vector<Init*> KeyValue;

  // Construct KeyValue using KeyInstr's values for RowFields.
  for (Init *RowField : RowFields->getValues()) {
    Init *KeyInstrVal = KeyInstr->getValue(RowField)->getValue();
    KeyValue.push_back(KeyInstrVal);
  }

  // Get all the instructions that share the same KeyValue as the KeyInstr
  // in RowInstrMap. We search through these instructions to find a match
  // for the current column, i.e., the instruction which has the same values
  // as CurValueCol for all the fields in ColFields.
  const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue];

  ListInit *ColFields = InstrMapDesc.getColFields();
  Record *MatchInstr = nullptr;

  for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) {
    bool MatchFound = true;
    Record *CurInstr = RelatedInstrVec[i];
    for (unsigned j = 0, endCF = ColFields->size();
        (j < endCF) && MatchFound; j++) {
      Init *ColFieldJ = ColFields->getElement(j);
      Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue();
      std::string CurInstrVal = CurInstrInit->getAsUnquotedString();
      Init *ColFieldJVallue = CurValueCol->getElement(j);
      MatchFound = (CurInstrVal == ColFieldJVallue->getAsUnquotedString());
    }

    if (MatchFound) {
      if (MatchInstr) {
        // Already had a match
        // Error if multiple matches are found for a column.
        std::string KeyValueStr;
        for (Init *Value : KeyValue) {
          if (!KeyValueStr.empty())
            KeyValueStr += ", ";
          KeyValueStr += Value->getAsString();
        }

        PrintFatalError("Multiple matches found for `" + KeyInstr->getName() +
              "', for the relation `" + InstrMapDesc.getName() + "', row fields [" +
              KeyValueStr + "], column `" + CurValueCol->getAsString() + "'");
      }
      MatchInstr = CurInstr;
    }
  }
  return MatchInstr;
}

//===----------------------------------------------------------------------===//
// Emit one table per relation. Only instructions with a valid relation of a
// given type are included in the table sorted by their enum values (opcodes).
// Binary search is used for locating instructions in the table.
//===----------------------------------------------------------------------===//

unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) {

  ArrayRef<const CodeGenInstruction*> NumberedInstructions =
                                            Target.getInstructionsByEnumValue();
  StringRef Namespace = Target.getInstNamespace();
  const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
  unsigned NumCol = ValueCols.size();
  unsigned TotalNumInstr = NumberedInstructions.size();
  unsigned TableSize = 0;

  OS << "static const uint16_t "<<InstrMapDesc.getName();
  // Number of columns in the table are NumCol+1 because key instructions are
  // emitted as first column.
  OS << "Table[]["<< NumCol+1 << "] = {\n";
  for (unsigned i = 0; i < TotalNumInstr; i++) {
    Record *CurInstr = NumberedInstructions[i]->TheDef;
    std::vector<Record*> ColInstrs = MapTable[CurInstr];
    std::string OutStr("");
    unsigned RelExists = 0;
    if (!ColInstrs.empty()) {
      for (unsigned j = 0; j < NumCol; j++) {
        if (ColInstrs[j] != nullptr) {
          RelExists = 1;
          OutStr += ", ";
          OutStr += Namespace;
          OutStr += "::";
          OutStr += ColInstrs[j]->getName();
        } else { OutStr += ", (uint16_t)-1U";}
      }

      if (RelExists) {
        OS << "  { " << Namespace << "::" << CurInstr->getName();
        OS << OutStr <<" },\n";
        TableSize++;
      }
    }
  }
  if (!TableSize) {
    OS << "  { " << Namespace << "::" << "INSTRUCTION_LIST_END, ";
    OS << Namespace << "::" << "INSTRUCTION_LIST_END }";
  }
  OS << "}; // End of " << InstrMapDesc.getName() << "Table\n\n";
  return TableSize;
}

//===----------------------------------------------------------------------===//
// Emit binary search algorithm as part of the functions used to query
// relation tables.
//===----------------------------------------------------------------------===//

void MapTableEmitter::emitBinSearch(raw_ostream &OS, unsigned TableSize) {
  OS << "  unsigned mid;\n";
  OS << "  unsigned start = 0;\n";
  OS << "  unsigned end = " << TableSize << ";\n";
  OS << "  while (start < end) {\n";
  OS << "    mid = start + (end - start)/2;\n";
  OS << "    if (Opcode == " << InstrMapDesc.getName() << "Table[mid][0]) {\n";
  OS << "      break;\n";
  OS << "    }\n";
  OS << "    if (Opcode < " << InstrMapDesc.getName() << "Table[mid][0])\n";
  OS << "      end = mid;\n";
  OS << "    else\n";
  OS << "      start = mid + 1;\n";
  OS << "  }\n";
  OS << "  if (start == end)\n";
  OS << "    return -1; // Instruction doesn't exist in this table.\n\n";
}

//===----------------------------------------------------------------------===//
// Emit functions to query relation tables.
//===----------------------------------------------------------------------===//

void MapTableEmitter::emitMapFuncBody(raw_ostream &OS,
                                           unsigned TableSize) {

  ListInit *ColFields = InstrMapDesc.getColFields();
  const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();

  // Emit binary search algorithm to locate instructions in the
  // relation table. If found, return opcode value from the appropriate column
  // of the table.
  emitBinSearch(OS, TableSize);

  if (ValueCols.size() > 1) {
    for (unsigned i = 0, e = ValueCols.size(); i < e; i++) {
      ListInit *ColumnI = ValueCols[i];
      for (unsigned j = 0, ColSize = ColumnI->size(); j < ColSize; ++j) {
        std::string ColName = ColFields->getElement(j)->getAsUnquotedString();
        OS << "  if (in" << ColName;
        OS << " == ";
        OS << ColName << "_" << ColumnI->getElement(j)->getAsUnquotedString();
        if (j < ColumnI->size() - 1) OS << " && ";
        else OS << ")\n";
      }
      OS << "    return " << InstrMapDesc.getName();
      OS << "Table[mid]["<<i+1<<"];\n";
    }
    OS << "  return -1;";
  }
  else
    OS << "  return " << InstrMapDesc.getName() << "Table[mid][1];\n";

  OS <<"}\n\n";
}

//===----------------------------------------------------------------------===//
// Emit relation tables and the functions to query them.
//===----------------------------------------------------------------------===//

void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) {

  // Emit function name and the input parameters : mostly opcode value of the
  // current instruction. However, if a table has multiple columns (more than 2
  // since first column is used for the key instructions), then we also need
  // to pass another input to indicate the column to be selected.

  ListInit *ColFields = InstrMapDesc.getColFields();
  const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
  OS << "// "<< InstrMapDesc.getName() << "\nLLVM_READONLY\n";
  OS << "int "<< InstrMapDesc.getName() << "(uint16_t Opcode";
  if (ValueCols.size() > 1) {
    for (Init *CF : ColFields->getValues()) {
      std::string ColName = CF->getAsUnquotedString();
      OS << ", enum " << ColName << " in" << ColName << ") {\n";
    }
  } else { OS << ") {\n"; }

  // Emit map table.
  unsigned TableSize = emitBinSearchTable(OS);

  // Emit rest of the function body.
  emitMapFuncBody(OS, TableSize);
}

//===----------------------------------------------------------------------===//
// Emit enums for the column fields across all the instruction maps.
//===----------------------------------------------------------------------===//

static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {

  std::vector<Record*> InstrMapVec;
  InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
  std::map<std::string, std::vector<Init*> > ColFieldValueMap;

  // Iterate over all InstrMapping records and create a map between column
  // fields and their possible values across all records.
  for (Record *CurMap : InstrMapVec) {
    ListInit *ColFields;
    ColFields = CurMap->getValueAsListInit("ColFields");
    ListInit *List = CurMap->getValueAsListInit("ValueCols");
    std::vector<ListInit*> ValueCols;
    unsigned ListSize = List->size();

    for (unsigned j = 0; j < ListSize; j++) {
      auto *ListJ = cast<ListInit>(List->getElement(j));

      if (ListJ->size() != ColFields->size())
        PrintFatalError("Record `" + CurMap->getName() + "', field "
          "`ValueCols' entries don't match with the entries in 'ColFields' !");
      ValueCols.push_back(ListJ);
    }

    for (unsigned j = 0, endCF = ColFields->size(); j < endCF; j++) {
      for (unsigned k = 0; k < ListSize; k++){
        std::string ColName = ColFields->getElement(j)->getAsUnquotedString();
        ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j));
      }
    }
  }

  for (auto &Entry : ColFieldValueMap) {
    std::vector<Init*> FieldValues = Entry.second;

    // Delete duplicate entries from ColFieldValueMap
    for (unsigned i = 0; i < FieldValues.size() - 1; i++) {
      Init *CurVal = FieldValues[i];
      for (unsigned j = i+1; j < FieldValues.size(); j++) {
        if (CurVal == FieldValues[j]) {
          FieldValues.erase(FieldValues.begin()+j);
          --j;
        }
      }
    }

    // Emit enumerated values for the column fields.
    OS << "enum " << Entry.first << " {\n";
    for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) {
      OS << "\t" << Entry.first << "_" << FieldValues[i]->getAsUnquotedString();
      if (i != endFV - 1)
        OS << ",\n";
      else
        OS << "\n};\n\n";
    }
  }
}

namespace llvm {
//===----------------------------------------------------------------------===//
// Parse 'InstrMapping' records and use the information to form relationship
// between instructions. These relations are emitted as a tables along with the
// functions to query them.
//===----------------------------------------------------------------------===//
void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) {
  CodeGenTarget Target(Records);
  StringRef NameSpace = Target.getInstNamespace();
  std::vector<Record*> InstrMapVec;
  InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");

  if (InstrMapVec.empty())
    return;

  OS << "#ifdef GET_INSTRMAP_INFO\n";
  OS << "#undef GET_INSTRMAP_INFO\n";
  OS << "namespace llvm {\n\n";
  OS << "namespace " << NameSpace << " {\n\n";

  // Emit coulumn field names and their values as enums.
  emitEnums(OS, Records);

  // Iterate over all instruction mapping records and construct relationship
  // maps based on the information specified there.
  //
  for (Record *CurMap : InstrMapVec) {
    MapTableEmitter IMap(Target, Records, CurMap);

    // Build RowInstrMap to group instructions based on their values for
    // RowFields. In the process, also collect key instructions into
    // KeyInstrVec.
    IMap.buildRowInstrMap();

    // Build MapTable to map key instructions with the corresponding column
    // instructions.
    IMap.buildMapTable();

    // Emit map tables and the functions to query them.
    IMap.emitTablesWithFunc(OS);
  }
  OS << "} // end namespace " << NameSpace << "\n";
  OS << "} // end namespace llvm\n";
  OS << "#endif // GET_INSTRMAP_INFO\n\n";
}

} // End llvm namespace
