From dc6a85256bcd2421e99129dc7f991c0c5c80352e Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Wed, 23 Jun 2021 13:26:56 +0700 Subject: [PATCH] [TableGen] Fix printing second PC-relative operand If an instruction has several operands and a PC-relative one is not the first of them, the generator may produce the code that does not pass the 'Address' parameter to the printout method. For example, for an Arm instruction 'LE LR, $imm', it reuses the same code as for other instructions where the second operand is not PC-relative: void ARMInstPrinter::printInstruction(...) { ... case 11: // BF16VDOTI_VDOTD, BF16VDOTI_VDOTQ, BF16VDOTS_VDOTD, ... printOperand(MI, 1, STI, O); O << ", "; printOperand(MI, 2, STI, O); break; ... The patch fixes that by considering 'PCRel' when comparing 'AsmWriterOperand' values. Differential Revision: https://reviews.llvm.org/D104698 --- test/TableGen/AsmWriterPCRelOp.td | 38 +++++++++++++++++++++++++++++++ utils/TableGen/AsmWriterInst.h | 3 ++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test/TableGen/AsmWriterPCRelOp.td diff --git a/test/TableGen/AsmWriterPCRelOp.td b/test/TableGen/AsmWriterPCRelOp.td new file mode 100644 index 00000000000..301f228aa9f --- /dev/null +++ b/test/TableGen/AsmWriterPCRelOp.td @@ -0,0 +1,38 @@ +// RUN: llvm-tblgen -gen-asm-writer -I %p/../../include %s | FileCheck %s + +include "llvm/Target/Target.td" + +def ArchInstrInfo : InstrInfo { } + +def Arch : Target { + let InstructionSet = ArchInstrInfo; +} + +def R0 : Register<"r0">; +def Reg : RegisterClass<"Reg", [i32], 0, (add R0)>; + +def IntOperand: Operand; + +def PCRelOperand : Operand { + let OperandType = "OPERAND_PCREL"; +} + +def foo : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins Reg:$reg, IntOperand:$imm); + let AsmString = "foo $reg, $imm"; +} + +def bar : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins Reg:$reg, PCRelOperand:$imm); + let AsmString = "bar $reg, $imm"; +} + +// CHECK: ArchInstPrinter::printInstruction( +// CHECK: // bar, foo +// CHECK-NEXT: printOperand(MI, 0, O); +// CHECK: // foo +// CHECK-NEXT: printOperand(MI, 1, O); +// CHECK: // bar +// CHECK-NEXT: printOperand(MI, Address, 1, O); diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h index 366c9eca664..fe2b934e266 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -66,7 +66,8 @@ namespace llvm { bool operator!=(const AsmWriterOperand &Other) const { if (OperandType != Other.OperandType || Str != Other.Str) return true; if (OperandType == isMachineInstrOperand) - return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier; + return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier || + PCRel != Other.PCRel; return false; } bool operator==(const AsmWriterOperand &Other) const {