[ARM] Fix Decode of tsb csync
There is a crash in the ARM backend when attempting to decode a "tsb csync" instruction using `llvm-objdump --triple=armv8.4a -d`. The crash was in `ARMMCInstrAnalysis::evaluateBranch` where the number of operands in the decoded instruction (0) did not match the number of operands in the instruction description (1). This is becuase `tsb csync` looks like it has an operand during assembly, but there is only one valid operand (csync), so there is no encoding space in the instruction for the operand, so the decoder never has a field to decode that represents `csync`. The fix is to add a custom decode method, which ensures that this instruction does have the right number of operands after decoding. This method merely adds the only available operand value, `ARM_TSB::CSYNC`. Reviewed By: tmatheson Differential Revision: https://reviews.llvm.org/D121479
This commit is contained in:
parent
9b3af5e7b7
commit
f496330f97
|
@ -5129,6 +5129,7 @@ let hasNoSchedulingInfo = 1 in
|
|||
def TSB : AInoP<(outs), (ins tsb_opt:$opt), MiscFrm, NoItinerary,
|
||||
"tsb", "\t$opt", []>, Requires<[IsARM, HasV8_4a]> {
|
||||
let Inst{31-0} = 0xe320f012;
|
||||
let DecoderMethod = "DecodeTSBInstruction";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3561,6 +3561,7 @@ let hasNoSchedulingInfo = 1 in
|
|||
def t2TSB : T2I<(outs), (ins tsb_opt:$opt), NoItinerary,
|
||||
"tsb", "\t$opt", []>, Requires<[IsThumb, HasV8_4a]> {
|
||||
let Inst{31-0} = 0xf3af8012;
|
||||
let DecoderMethod = "DecodeTSBInstruction";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -265,6 +265,8 @@ static DecodeStatus DecodeSORegMemOperand(MCInst &Inst, unsigned Insn,
|
|||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeAddrMode3Instruction(MCInst &Inst,unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeTSBInstruction(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
static DecodeStatus DecodeSORegRegOperand(MCInst &Inst, unsigned Insn,
|
||||
|
@ -2013,6 +2015,19 @@ static DecodeStatus DecodeSORegMemOperand(MCInst &Inst, unsigned Val,
|
|||
return S;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeTSBInstruction(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
if (Inst.getOpcode() != ARM::TSB && Inst.getOpcode() != ARM::t2TSB)
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
// The "csync" operand is not encoded into the "tsb" instruction (as this is
|
||||
// the only available operand), but LLVM expects the instruction to have one
|
||||
// operand, so we need to add the csync when decoding.
|
||||
Inst.addOperand(MCOperand::createImm(ARM_TSB::CSYNC));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus
|
||||
DecodeAddrMode3Instruction(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
|
|
|
@ -2,10 +2,18 @@
|
|||
// RUN: llvm-mc -triple thumb -mattr=+v8.4a -show-encoding < %s | FileCheck %s --check-prefix=CHECK-T32
|
||||
// RUN: not llvm-mc -triple arm -mattr=-v8.4a -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-V84
|
||||
|
||||
// RUN: llvm-mc -filetype=obj -triple arm -mattr=+v8.4a < %s \
|
||||
// RUN: | llvm-objdump --triple=arm --mattr=+v8.4a -r -d - \
|
||||
// RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP %s
|
||||
// RUN: llvm-mc -filetype=obj -triple thumb -mattr=+v8.4a < %s \
|
||||
// RUN: | llvm-objdump --triple=thumb --mattr=+v8.4a -r -d - \
|
||||
// RUN: | FileCheck -check-prefixes=CHECK-OBJDUMP %s
|
||||
|
||||
tsb csync
|
||||
|
||||
//CHECK-A32: tsb csync @ encoding: [0x12,0xf0,0x20,0xe3]
|
||||
//CHECK-T32: tsb csync @ encoding: [0xaf,0xf3,0x12,0x80]
|
||||
//CHECK-OBJDUMP: tsb csync
|
||||
|
||||
//CHECK-NO-V84: error: invalid instruction
|
||||
//CHECK-NO-V84: tsb csync
|
||||
|
|
Loading…
Reference in New Issue