llvm.org GIT mirror llvm / 8a6db15
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366274 91177308-0d34-0410-b5e6-96231b3b80d8 Justin Bogner a month ago
2 changed file(s) with 97 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
0 // RUN: llvm-tblgen -gen-instr-info -I %p/../../include %s | FileCheck %s
1
2 // Check that getOperandType has the expected info in it
3
4 include "llvm/Target/Target.td"
5
6 def archInstrInfo : InstrInfo { }
7
8 def arch : Target {
9 let InstructionSet = archInstrInfo;
10 }
11
12 def Reg : Register<"reg">;
13 def RegClass : RegisterClass<"foo", [i32], 0, (add Reg)>;
14
15 def OpA : Operand;
16 def OpB : Operand;
17
18 def InstA : Instruction {
19 let Size = 1;
20 let OutOperandList = (outs OpA:$a);
21 let InOperandList = (ins OpB:$b, i32imm:$c);
22 field bits<8> Inst;
23 field bits<8> SoftFail = 0;
24 let Namespace = "MyNamespace";
25 }
26
27 def InstB : Instruction {
28 let Size = 1;
29 let OutOperandList = (outs i32imm:$d);
30 let InOperandList = (ins unknown:$x);
31 field bits<8> Inst;
32 field bits<8> SoftFail = 0;
33 let Namespace = "MyNamespace";
34 }
35
36 // CHECK: #ifdef GET_INSTRINFO_OPERAND_TYPE
37 // CHECK: { OpTypes::OpA, OpTypes::OpB, OpTypes::i32imm, }
38 // CHECK-NEXT: { OpTypes::i32imm, -1, }
39 // CHECK: #endif //GET_INSTRINFO_OPERAND_TYPE
7575 std::map, unsigned> &EL,
7676 const OperandInfoMapTy &OpInfo,
7777 raw_ostream &OS);
78 void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target);
78 void emitOperandTypeMappings(
79 raw_ostream &OS, const CodeGenTarget &Target,
80 ArrayRef NumberedInstructions);
7981 void initOperandMapData(
8082 ArrayRef NumberedInstructions,
8183 StringRef Namespace,
323325 /// Generate an enum for all the operand types for this target, under the
324326 /// llvm::TargetNamespace::OpTypes namespace.
325327 /// Operand types are all definitions derived of the Operand Target.td class.
326 void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
327 const CodeGenTarget &Target) {
328 void InstrInfoEmitter::emitOperandTypeMappings(
329 raw_ostream &OS, const CodeGenTarget &Target,
330 ArrayRef NumberedInstructions) {
328331
329332 StringRef Namespace = Target.getInstNamespace();
330333 std::vector Operands = Records.getAllDerivedDefinitions("Operand");
348351 OS << "} // end namespace " << Namespace << "\n";
349352 OS << "} // end namespace llvm\n";
350353 OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";
354
355 OS << "#ifdef GET_INSTRINFO_OPERAND_TYPE\n";
356 OS << "#undef GET_INSTRINFO_OPERAND_TYPE\n";
357 OS << "namespace llvm {\n";
358 OS << "namespace " << Namespace << " {\n";
359 OS << "LLVM_READONLY\n";
360 OS << "int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n";
361 if (!NumberedInstructions.empty()) {
362 OS << " static const std::initializer_list OpcodeOperandTypes[] = "
363 "{\n";
364 for (const CodeGenInstruction *Inst : NumberedInstructions) {
365 OS << " { ";
366 for (const auto &Op : Inst->Operands) {
367 // Handle aggregate operands and normal operands the same way by
368 // expanding either case into a list of operands for this op.
369 std::vector OperandList;
370
371 const DagInit *MIOI = Op.MIOperandInfo;
372 if (!MIOI || MIOI->getNumArgs() == 0) {
373 // Single, anonymous, operand.
374 OperandList.push_back(Op);
375 } else {
376 for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) {
377 OperandList.push_back(Op);
378
379 auto *OpR = cast(MIOI->getArg(j))->getDef();
380 OperandList.back().Rec = OpR;
381 }
382 }
383
384 for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
385 Record *OpR = OperandList[j].Rec;
386 if (OpR->isSubClassOf("Operand") && !OpR->isAnonymous())
387 OS << "OpTypes::" << OpR->getName();
388 else
389 OS << -1;
390 OS << ", ";
391 }
392 }
393 OS << "},\n";
394 }
395 OS << " };\n";
396 OS << " return OpcodeOperandTypes[Opcode].begin()[OpIdx];\n";
397 } else {
398 OS << " llvm_unreachable(\"No instructions defined\");\n";
399 }
400 OS << "}\n";
401 OS << "} // end namespace " << Namespace << "\n";
402 OS << "} // end namespace llvm\n";
403 OS << "#endif //GET_INSTRINFO_OPERAND_TYPE\n\n";
351404 }
352405
353406 void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS,
559612
560613 emitOperandNameMappings(OS, Target, NumberedInstructions);
561614
562 emitOperandTypesEnum(OS, Target);
615 emitOperandTypeMappings(OS, Target, NumberedInstructions);
563616
564617 emitMCIIHelperMethods(OS, TargetName);
565618 }