[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