Index: llvm/lib/Target/SystemZ/SystemZInstrInfo.h =================================================================== --- llvm/lib/Target/SystemZ/SystemZInstrInfo.h +++ llvm/lib/Target/SystemZ/SystemZInstrInfo.h @@ -322,6 +322,10 @@ MachineBasicBlock::iterator MBBI, unsigned Reg, uint64_t Value) const; + // Perform target specific instruction verification. + bool verifyInstruction(const MachineInstr &MI, + StringRef &ErrInfo) const override; + // Sometimes, it is possible for the target to tell, even without // aliasing information, that two MIs access different memory // addresses. This function returns true if two MIs access different Index: llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -1748,6 +1748,28 @@ BuildMI(MBB, MBBI, DL, get(Opcode), Reg).addImm(Value); } +bool SystemZInstrInfo::verifyInstruction(const MachineInstr &MI, + StringRef &ErrInfo) const { + const MCInstrDesc &MCID = MI.getDesc(); + for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { + if (I >= MCID.getNumOperands()) + break; + const MachineOperand &Op = MI.getOperand(I); + const MCOperandInfo &MCOI = MCID.OpInfo[I]; + // Addressing modes have register and immediate operands. Op should be a + // register (or frame index) operand if MCOI.RegClass contains a valid + // register class, or an immediate otherwise. + if (MCOI.OperandType == MCOI::OPERAND_MEMORY && + ((MCOI.RegClass != -1 && !Op.isReg() && !Op.isFI()) || + (MCOI.RegClass == -1 && !Op.isImm()))) { + ErrInfo = "Addressing mode operands corrupt!"; + return false; + } + } + + return true; +} + bool SystemZInstrInfo:: areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const { Index: llvm/lib/Target/SystemZ/SystemZOperands.td =================================================================== --- llvm/lib/Target/SystemZ/SystemZOperands.td +++ llvm/lib/Target/SystemZ/SystemZOperands.td @@ -25,6 +25,7 @@ let PrintMethod = "print"##asmop##"Operand"; let DecoderMethod = "decode"##asmop##"Operand"; let ParserMatchClass = !cast(asmop); + let OperandType = "OPERAND_IMMEDIATE"; } class ImmOpWithPattern : Operand { - let PrintMethod = "printPCRelOperand"; - let ParserMatchClass = asmop; -} -class PCRelTLSOperand : Operand { - let PrintMethod = "printPCRelTLSOperand"; - let ParserMatchClass = asmop; +let OperandType = "OPERAND_PCREL" in { + class PCRelOperand : Operand { + let PrintMethod = "printPCRelOperand"; + let ParserMatchClass = asmop; + } + class PCRelTLSOperand : Operand { + let PrintMethod = "printPCRelTLSOperand"; + let ParserMatchClass = asmop; + } } // Constructs both a DAG pattern and instruction operand for a PC-relative @@ -105,6 +108,7 @@ let EncoderMethod = "get"##format##dispsize##length##"Encoding"; let DecoderMethod = "decode"##format##bitsize##"Disp"##dispsize##length##"Operand"; + let OperandType = "OPERAND_MEMORY"; let MIOperandInfo = operands; let ParserMatchClass = !cast(format##bitsize##"Disp"##dispsize##length); @@ -508,7 +512,8 @@ return isUInt<64>(N->getZExtValue()); }], UIMM48, "U48Imm">; -def imm64 : ImmLeaf, Operand; +let OperandType = "OPERAND_IMMEDIATE" in + def imm64 : ImmLeaf, Operand; //===----------------------------------------------------------------------===// // Floating-point immediates @@ -657,4 +662,5 @@ def cond4 : PatLeaf<(i32 timm), [{ return (N->getZExtValue() < 16); }]>, Operand { let PrintMethod = "printCond4Operand"; + let OperandType = "OPERAND_IMMEDIATE"; } Index: llvm/test/CodeGen/SystemZ/mverify-optypes.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/mverify-optypes.mir @@ -0,0 +1,72 @@ +# RUN: not llc -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass=none -o - %s \ +# RUN: 2>&1 | FileCheck %s +# REQUIRES: asserts +# +# Test that the machine verifier catches wrong operand types. + +--- | + define anyregcc i64 @fun() { ret i64 0 } + @gsrc = global i16 2 +... +--- +name: fun +alignment: 16 +tracksRegLiveness: true +registers: + - { id: 0, class: gr64bit } +frameInfo: + maxAlignment: 1 +machineFunctionInfo: {} +body: | + bb.0 (%ir-block.0): + liveins: $r2l + %0:gr64bit = LGHI $r2l + %1:addr64bit = LLILL $r2l + %2:addr64bit = LGFI $r2l + %3:addr64bit = LGFI 0 + + %3:addr64bit = AG %3, %1, 0, %2, implicit-def dead $cc + %3:addr64bit = AG %3, %1, %0, %2, implicit-def dead $cc + %3:addr64bit = AG %3, %1, 0, 2, implicit-def dead $cc + + %4:addr64bit = LARL @gsrc + %4:addr64bit = LARL $r2l + + MVCLoop %4, 0, %3, 0, 1680, %0, implicit-def $cc + MVCLoop %4, 0, %3, 0, %1, %0, implicit-def $cc + + BCR 0, 0, $r2d, implicit $cc + BCR 0, $r2d, $r2d, implicit $cc + Return implicit $r2d + +... + +# CHECK: *** Bad machine code: Expected a non-register operand. *** +# CHECK: - instruction: %0:gr64bit = LGHI $r2l +# CHECK: - operand 1: $r2l + +# CHECK: *** Bad machine code: Expected a non-register operand. *** +# CHECK: - instruction: %1:addr64bit = LLILL $r2l +# CHECK: - operand 1: $r2l + +# CHECK: *** Bad machine code: Expected a non-register operand. *** +# CHECK: - instruction: %2:addr64bit = LGFI $r2l +# CHECK: - operand 1: $r2l + +# CHECK: *** Bad machine code: Addressing mode operands corrupt! *** +# CHECK: - instruction: %3:addr64bit = AG %3:addr64bit(tied-def 0), %1:addr64bit, %0:gr64bit, %2:addr64bit, implicit-def dead $cc + +# CHECK: *** Bad machine code: Addressing mode operands corrupt! *** +# CHECK: - instruction: %3:addr64bit = AG %3:addr64bit(tied-def 0), %1:addr64bit, 0, 2, implicit-def dead $cc + +# CHECK: *** Bad machine code: Expected a non-register operand. *** +# CHECK: - instruction: %4:addr64bit = LARL $r2l +# CHECK: - operand 1: $r2l + +# CHECK: *** Bad machine code: Expected a non-register operand. *** +# CHECK: - instruction: MVCLoop %4:addr64bit, 0, %3:addr64bit, 0, %1:addr64bit, %0:gr64bit, implicit-def $cc +# CHECK: - operand 4: %1:addr64bit + +# CHECK: *** Bad machine code: Expected a non-register operand. *** +# CHECK: - instruction: BCR 0, $r2d, $r2d, implicit $cc +# CHECK: - operand 1: $r2d