[llvm] [TableGen] Implement getOperandIdxName (PR #154944)
Rahul Joshi via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 22 13:16:30 PDT 2025
================
@@ -223,17 +223,104 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
}
}
+static void emitGetInstructionIndexForOpLookup(
+ raw_ostream &OS, const MapVector<SmallVector<int>, unsigned> &OperandMap,
+ ArrayRef<unsigned> InstructionIndex) {
+ StringRef Type = OperandMap.size() <= UINT8_MAX + 1 ? "uint8_t" : "uint16_t";
+ OS << "LLVM_READONLY\n";
+ OS << "static " << Type
+ << " getInstructionIndexForOpLookup(uint16_t Opcode) {\n";
+ OS << " static constexpr " << Type << " InstructionIndex[] = {";
+ for (auto [TableIndex, Entry] : enumerate(InstructionIndex))
+ OS << (TableIndex % 16 == 0 ? "\n " : " ") << Entry << ',';
+ OS << "\n };\n";
+ OS << " return InstructionIndex[Opcode];\n";
+ OS << "}\n";
+}
+
+static void
+emitGetNamedOperandIdx(raw_ostream &OS, StringRef Namespace,
+ const MapVector<StringRef, unsigned> &OperandNameToID,
+ const MapVector<SmallVector<int>, unsigned> &OperandMap,
+ unsigned MaxOperandNo, unsigned NumOperandNames) {
+ OS << "LLVM_READONLY\n";
+ OS << "int16_t getNamedOperandIdx(uint16_t Opcode, OpName Name) {\n";
+ OS << " assert(Name != OpName::NUM_OPERAND_NAMES);\n";
+ if (!NumOperandNames) {
+ // There are no operands, so no need to emit anything
+ OS << " return -1;\n}\n";
+ return;
+ }
+ assert(MaxOperandNo <= INT16_MAX &&
+ "Too many operands for the operand name -> index table");
+ StringRef Type = MaxOperandNo <= INT8_MAX ? "int8_t" : "int16_t";
+ OS << " static constexpr " << Type << " OperandMap[][" << NumOperandNames
+ << "] = {\n";
+ for (const auto &[OpList, _] : OperandMap) {
+ // Emit a row of the OperandMap table.
+ OS << " {";
+ for (unsigned ID = 0; ID < NumOperandNames; ++ID)
+ OS << (ID < OpList.size() ? OpList[ID] : -1) << ", ";
+ OS << "},\n";
+ }
+ OS << " };\n";
+
+ OS << " unsigned InstrIdx = getInstructionIndexForOpLookup(Opcode);\n";
+ OS << " return OperandMap[InstrIdx][(unsigned)Name];\n";
+ OS << "}\n";
+}
+
+static void
+emitGetOperandIdxName(raw_ostream &OS, StringRef Namespace,
+ const MapVector<StringRef, unsigned> &OperandNameToID,
+ const MapVector<SmallVector<int>, unsigned> &OperandMap,
+ unsigned MaxOperandNo, unsigned NumOperandNames) {
+ OS << "LLVM_READONLY\n";
+ OS << "OpName getOperandIdxName(uint16_t Opcode, int16_t Idx) {\n";
+ OS << " assert(Idx >= 0 && Idx < " << MaxOperandNo << ");\n";
+ if (!MaxOperandNo) {
+ // There are no operands, so no need to emit anything
+ OS << " return -1;\n}\n";
+ return;
+ }
+ assert(NumOperandNames <= UINT16_MAX &&
+ "Too many operands for the operand index -> name table");
+ StringRef Type = NumOperandNames <= UINT8_MAX ? "uint8_t" : "uint16_t";
+ OS << " static constexpr " << Type << " OperandMap[][" << MaxOperandNo
+ << "] = {\n";
+ for (const auto &[OpList, _] : OperandMap) {
+ SmallVector<unsigned> IDs(MaxOperandNo, NumOperandNames);
+ for (const auto &[ID, Idx] : enumerate(OpList)) {
+ if (Idx >= 0)
+ IDs[Idx] = ID;
+ }
+ // Emit a row of the OperandMap table. Map operand indices to enum values.
+ OS << " {";
+ for (unsigned ID : IDs)
+ OS << ID << ", ";
----------------
jurahul wrote:
Would be nice to emit enum names as opposed to raw IDs so if you need to read the generated code you can understand it better. Also, if we make the table use the enum type, it may be more natural to use the names as opposed to `static_cast<OpName>(6)`.
https://github.com/llvm/llvm-project/pull/154944
More information about the llvm-commits
mailing list