| //===- 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()) { |
| ListInit *ColI = dyn_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++) { |
| ListInit *ListJ = dyn_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 llvm namespace\n"; |
| OS << "#endif // GET_INSTRMAP_INFO\n\n"; |
| } |
| |
| } // End llvm namespace |