[llvm] r366274 - [TableGen] Add "getOperandType" to get operand types from opcode/opidx

Justin Bogner via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 16 15:10:17 PDT 2019


Author: bogner
Date: Tue Jul 16 15:10:16 2019
New Revision: 366274

URL: http://llvm.org/viewvc/llvm-project?rev=366274&view=rev
Log:
[TableGen] Add "getOperandType" to get operand types from opcode/opidx

The InstrInfoEmitter outputs an enum called "OperandType" which gives
numerical IDs to each operand type. This patch makes use of this enum
to define a function called "getOperandType", which allows looking up
the type of an operand given its opcode and operand index.

Patch by Nicolas Guillemot. Thanks!

Differential Revision: https://reviews.llvm.org/D63320

Added:
    llvm/trunk/test/TableGen/get-operand-type.td
Modified:
    llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp

Added: llvm/trunk/test/TableGen/get-operand-type.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/get-operand-type.td?rev=366274&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/get-operand-type.td (added)
+++ llvm/trunk/test/TableGen/get-operand-type.td Tue Jul 16 15:10:16 2019
@@ -0,0 +1,40 @@
+// RUN: llvm-tblgen -gen-instr-info -I %p/../../include %s | FileCheck %s
+
+// Check that getOperandType has the expected info in it
+
+include "llvm/Target/Target.td"
+
+def archInstrInfo : InstrInfo { }
+
+def arch : Target {
+  let InstructionSet = archInstrInfo;
+}
+
+def Reg : Register<"reg">;
+def RegClass : RegisterClass<"foo", [i32], 0, (add Reg)>;
+
+def OpA : Operand<i32>;
+def OpB : Operand<i32>;
+
+def InstA : Instruction {
+  let Size = 1;
+  let OutOperandList = (outs OpA:$a);
+  let InOperandList = (ins OpB:$b, i32imm:$c);
+  field bits<8> Inst;
+  field bits<8> SoftFail = 0;
+  let Namespace = "MyNamespace";
+}
+
+def InstB : Instruction {
+  let Size = 1;
+  let OutOperandList = (outs i32imm:$d);
+  let InOperandList = (ins unknown:$x);
+  field bits<8> Inst;
+  field bits<8> SoftFail = 0;
+  let Namespace = "MyNamespace";
+}
+
+// CHECK: #ifdef GET_INSTRINFO_OPERAND_TYPE
+// CHECK: { OpTypes::OpA, OpTypes::OpB, OpTypes::i32imm, }
+// CHECK-NEXT: { OpTypes::i32imm, -1, }
+// CHECK: #endif //GET_INSTRINFO_OPERAND_TYPE

Modified: llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp?rev=366274&r1=366273&r2=366274&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp Tue Jul 16 15:10:16 2019
@@ -76,7 +76,9 @@ private:
                   std::map<std::vector<Record*>, unsigned> &EL,
                   const OperandInfoMapTy &OpInfo,
                   raw_ostream &OS);
-  void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target);
+  void emitOperandTypeMappings(
+      raw_ostream &OS, const CodeGenTarget &Target,
+      ArrayRef<const CodeGenInstruction *> NumberedInstructions);
   void initOperandMapData(
             ArrayRef<const CodeGenInstruction *> NumberedInstructions,
             StringRef Namespace,
@@ -324,8 +326,9 @@ void InstrInfoEmitter::emitOperandNameMa
 /// Generate an enum for all the operand types for this target, under the
 /// llvm::TargetNamespace::OpTypes namespace.
 /// Operand types are all definitions derived of the Operand Target.td class.
-void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
-                                            const CodeGenTarget &Target) {
+void InstrInfoEmitter::emitOperandTypeMappings(
+    raw_ostream &OS, const CodeGenTarget &Target,
+    ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
 
   StringRef Namespace = Target.getInstNamespace();
   std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand");
@@ -349,6 +352,56 @@ void InstrInfoEmitter::emitOperandTypesE
   OS << "} // end namespace " << Namespace << "\n";
   OS << "} // end namespace llvm\n";
   OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";
+
+  OS << "#ifdef GET_INSTRINFO_OPERAND_TYPE\n";
+  OS << "#undef GET_INSTRINFO_OPERAND_TYPE\n";
+  OS << "namespace llvm {\n";
+  OS << "namespace " << Namespace << " {\n";
+  OS << "LLVM_READONLY\n";
+  OS << "int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n";
+  if (!NumberedInstructions.empty()) {
+    OS << "  static const std::initializer_list<int> OpcodeOperandTypes[] = "
+          "{\n";
+    for (const CodeGenInstruction *Inst : NumberedInstructions) {
+      OS << "    { ";
+      for (const auto &Op : Inst->Operands) {
+        // Handle aggregate operands and normal operands the same way by
+        // expanding either case into a list of operands for this op.
+        std::vector<CGIOperandList::OperandInfo> OperandList;
+
+        const DagInit *MIOI = Op.MIOperandInfo;
+        if (!MIOI || MIOI->getNumArgs() == 0) {
+          // Single, anonymous, operand.
+          OperandList.push_back(Op);
+        } else {
+          for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) {
+            OperandList.push_back(Op);
+
+            auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef();
+            OperandList.back().Rec = OpR;
+          }
+        }
+
+        for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
+          Record *OpR = OperandList[j].Rec;
+          if (OpR->isSubClassOf("Operand") && !OpR->isAnonymous())
+            OS << "OpTypes::" << OpR->getName();
+          else
+            OS << -1;
+          OS << ", ";
+        }
+      }
+      OS << "},\n";
+    }
+    OS << "  };\n";
+    OS << "  return OpcodeOperandTypes[Opcode].begin()[OpIdx];\n";
+  } else {
+    OS << "  llvm_unreachable(\"No instructions defined\");\n";
+  }
+  OS << "}\n";
+  OS << "} // end namespace " << Namespace << "\n";
+  OS << "} // end namespace llvm\n";
+  OS << "#endif //GET_INSTRINFO_OPERAND_TYPE\n\n";
 }
 
 void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,
@@ -560,7 +613,7 @@ void InstrInfoEmitter::run(raw_ostream &
 
   emitOperandNameMappings(OS, Target, NumberedInstructions);
 
-  emitOperandTypesEnum(OS, Target);
+  emitOperandTypeMappings(OS, Target, NumberedInstructions);
 
   emitMCIIHelperMethods(OS, TargetName);
 }




More information about the llvm-commits mailing list