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; }
void MapTableEmitter::buildRowInstrMap() { for (Record *CurInstr : InstrDefs) { std::vector<Init*> KeyValue; ListInit *RowFields = InstrMapDesc.getRowFields(); for (Init *RowField : RowFields->getValues()) { Init *CurInstrVal = CurInstr->getValue(RowField)->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); } }
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); }