[llvm] f496330 - [ARM] Fix Decode of tsb csync

Archibald Elliott via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 17 10:30:19 PDT 2022


Author: Archibald Elliott
Date: 2022-03-17T17:29:31Z
New Revision: f496330f9719ddce4b9e769c7fa49d0fcad643b8

URL: https://github.com/llvm/llvm-project/commit/f496330f9719ddce4b9e769c7fa49d0fcad643b8
DIFF: https://github.com/llvm/llvm-project/commit/f496330f9719ddce4b9e769c7fa49d0fcad643b8.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/Target/ARM/ARMInstrInfo.td
    llvm/lib/Target/ARM/ARMInstrThumb2.td
    llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
    llvm/test/MC/ARM/armv8.4a-trace.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index acf0fa9ac79db..359df97043cad 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -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";
 }
 
 }

diff  --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index c75c3d3901021..0119a80505774 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -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";
 }
 }
 

diff  --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index c3df7dc88d791..32ba9592857d9 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -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) {

diff  --git a/llvm/test/MC/ARM/armv8.4a-trace.s b/llvm/test/MC/ARM/armv8.4a-trace.s
index 254f776f39f3d..7fc29bc85bbbe 100644
--- a/llvm/test/MC/ARM/armv8.4a-trace.s
+++ b/llvm/test/MC/ARM/armv8.4a-trace.s
@@ -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


        


More information about the llvm-commits mailing list