mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[SystemZ] Improve verification of MachineOperands.
Now that the machine verifier will check for cases of register/immediate MachineOperands and their correspondence to the MC instruction descriptor, this patch adds the operand types to the descriptors where they were previously missing. All MCOI::OPERAND_UNKNOWN operand types have been handled to get a known type, except for G_... (global isel) instructions. Review: Ulrich Weigand https://reviews.llvm.org/D71494
This commit is contained in:
parent
a5cec65225
commit
5bfbf50961
@ -1748,6 +1748,28 @@ void SystemZInstrInfo::loadImmediate(MachineBasicBlock &MBB,
|
|||||||
BuildMI(MBB, MBBI, DL, get(Opcode), Reg).addImm(Value);
|
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::
|
bool SystemZInstrInfo::
|
||||||
areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
|
areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
|
||||||
const MachineInstr &MIb) const {
|
const MachineInstr &MIb) const {
|
||||||
|
@ -322,6 +322,10 @@ public:
|
|||||||
MachineBasicBlock::iterator MBBI,
|
MachineBasicBlock::iterator MBBI,
|
||||||
unsigned Reg, uint64_t Value) const;
|
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
|
// Sometimes, it is possible for the target to tell, even without
|
||||||
// aliasing information, that two MIs access different memory
|
// aliasing information, that two MIs access different memory
|
||||||
// addresses. This function returns true if two MIs access different
|
// addresses. This function returns true if two MIs access different
|
||||||
|
@ -25,6 +25,7 @@ class ImmediateOp<ValueType vt, string asmop> : Operand<vt> {
|
|||||||
let PrintMethod = "print"##asmop##"Operand";
|
let PrintMethod = "print"##asmop##"Operand";
|
||||||
let DecoderMethod = "decode"##asmop##"Operand";
|
let DecoderMethod = "decode"##asmop##"Operand";
|
||||||
let ParserMatchClass = !cast<AsmOperandClass>(asmop);
|
let ParserMatchClass = !cast<AsmOperandClass>(asmop);
|
||||||
|
let OperandType = "OPERAND_IMMEDIATE";
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImmOpWithPattern<ValueType vt, string asmop, code pred, SDNodeXForm xform,
|
class ImmOpWithPattern<ValueType vt, string asmop, code pred, SDNodeXForm xform,
|
||||||
@ -63,13 +64,15 @@ class PCRelTLSAsmOperand<string size>
|
|||||||
|
|
||||||
// Constructs an operand for a PC-relative address with address type VT.
|
// Constructs an operand for a PC-relative address with address type VT.
|
||||||
// ASMOP is the associated asm operand.
|
// ASMOP is the associated asm operand.
|
||||||
class PCRelOperand<ValueType vt, AsmOperandClass asmop> : Operand<vt> {
|
let OperandType = "OPERAND_PCREL" in {
|
||||||
let PrintMethod = "printPCRelOperand";
|
class PCRelOperand<ValueType vt, AsmOperandClass asmop> : Operand<vt> {
|
||||||
let ParserMatchClass = asmop;
|
let PrintMethod = "printPCRelOperand";
|
||||||
}
|
let ParserMatchClass = asmop;
|
||||||
class PCRelTLSOperand<ValueType vt, AsmOperandClass asmop> : Operand<vt> {
|
}
|
||||||
let PrintMethod = "printPCRelTLSOperand";
|
class PCRelTLSOperand<ValueType vt, AsmOperandClass asmop> : Operand<vt> {
|
||||||
let ParserMatchClass = asmop;
|
let PrintMethod = "printPCRelTLSOperand";
|
||||||
|
let ParserMatchClass = asmop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs both a DAG pattern and instruction operand for a PC-relative
|
// Constructs both a DAG pattern and instruction operand for a PC-relative
|
||||||
@ -105,6 +108,7 @@ class AddressOperand<string bitsize, string dispsize, string length,
|
|||||||
let EncoderMethod = "get"##format##dispsize##length##"Encoding";
|
let EncoderMethod = "get"##format##dispsize##length##"Encoding";
|
||||||
let DecoderMethod =
|
let DecoderMethod =
|
||||||
"decode"##format##bitsize##"Disp"##dispsize##length##"Operand";
|
"decode"##format##bitsize##"Disp"##dispsize##length##"Operand";
|
||||||
|
let OperandType = "OPERAND_MEMORY";
|
||||||
let MIOperandInfo = operands;
|
let MIOperandInfo = operands;
|
||||||
let ParserMatchClass =
|
let ParserMatchClass =
|
||||||
!cast<AddressAsmOperand>(format##bitsize##"Disp"##dispsize##length);
|
!cast<AddressAsmOperand>(format##bitsize##"Disp"##dispsize##length);
|
||||||
@ -508,7 +512,8 @@ defm imm64zx48 : Immediate<i64, [{
|
|||||||
return isUInt<64>(N->getZExtValue());
|
return isUInt<64>(N->getZExtValue());
|
||||||
}], UIMM48, "U48Imm">;
|
}], UIMM48, "U48Imm">;
|
||||||
|
|
||||||
def imm64 : ImmLeaf<i64, [{}]>, Operand<i64>;
|
let OperandType = "OPERAND_IMMEDIATE" in
|
||||||
|
def imm64 : ImmLeaf<i64, [{}]>, Operand<i64>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Floating-point immediates
|
// Floating-point immediates
|
||||||
@ -657,4 +662,5 @@ def bdvaddr12only : BDVMode< "64", "12">;
|
|||||||
def cond4 : PatLeaf<(i32 timm), [{ return (N->getZExtValue() < 16); }]>,
|
def cond4 : PatLeaf<(i32 timm), [{ return (N->getZExtValue() < 16); }]>,
|
||||||
Operand<i32> {
|
Operand<i32> {
|
||||||
let PrintMethod = "printCond4Operand";
|
let PrintMethod = "printCond4Operand";
|
||||||
|
let OperandType = "OPERAND_IMMEDIATE";
|
||||||
}
|
}
|
||||||
|
72
test/CodeGen/SystemZ/mverify-optypes.mir
Normal file
72
test/CodeGen/SystemZ/mverify-optypes.mir
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user