[llvm] [ARM][Disassembler] Advance IT State when instruction is unknown (PR #154531)

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 20 06:13:08 PDT 2025


https://github.com/smithp35 created https://github.com/llvm/llvm-project/pull/154531

When an instruction that the disassembler does not recognize is in an IT block, we should still advance the IT state otherwise the IT state spills over into the next recognized instruction, which is incorrect.

We want to avoid disassembly like:
it eq
<unknown> // Often because disassembler has insufficient target info. 
addeq r0,r0,r0 // eq spills over into add.

Fixes #150569

>From a979f0e3f55013f1f9e9f26391b65a52e49be6ff Mon Sep 17 00:00:00 2001
From: Peter Smith <peter.smith at arm.com>
Date: Wed, 20 Aug 2025 13:59:08 +0100
Subject: [PATCH] [ARM][Disassembler] Advance IT State when instruction is
 unknown

When an instruction that the disassembler does not recognize is in an
IT block, we should still advance the IT state otherwise the IT state
spills over into the next recognized instruction, which is incorrect.

We want to avoid disassembly like:
it eq
<unknown> // Often because disassembler has insufficient target info.
addeq r0,r0,r0 // eq spills over into add.

Fixes #150569
---
 .../ARM/Disassembler/ARMDisassembler.cpp      |  4 ++
 .../llvm-objdump/ELF/ARM/undefined-in-it.s    | 45 +++++++++++++++++++
 2 files changed, 49 insertions(+)
 create mode 100644 llvm/test/tools/llvm-objdump/ELF/ARM/undefined-in-it.s

diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 2e47ceeca96b8..cbd31beab8299 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -1264,6 +1264,10 @@ DecodeStatus ARMDisassembler::getThumbInstruction(MCInst &MI, uint64_t &Size,
     return Result;
   }
 
+  // Advance IT state to prevent next instruction inheriting
+  // the wrong IT state.
+  if (ITBlock.instrInITBlock())
+    ITBlock.advanceITState();
   Size = 0;
   return MCDisassembler::Fail;
 }
diff --git a/llvm/test/tools/llvm-objdump/ELF/ARM/undefined-in-it.s b/llvm/test/tools/llvm-objdump/ELF/ARM/undefined-in-it.s
new file mode 100644
index 0000000000000..c5dc5cb248744
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/ARM/undefined-in-it.s
@@ -0,0 +1,45 @@
+ at RUN: llvm-mc -triple arm-none-eabi -mcpu=cortex-m33 -filetype=obj %s | llvm-objdump -d --mcpu=cortex-m3 - | FileCheck %s
+
+@ Check that instructions that are disassembled as <undefined> within an IT
+@ block advance the IT state. This prevents the IT state spilling over into
+@ the next instruction.
+
+@ The vldmiaeq instruction is disassembled as <undefined> with
+@ -mcpu=cortex-m3 as this does not have a fpu.
+.text
+.fpu fp-armv8
+.thumb
+ ite eq
+ vldmiaeq r0!, {s16-s31}
+ addne    r0, r0, r0
+ add      r1, r1, r1
+
+ itet eq
+ vldmiaeq r0!, {s16-s31}
+ vldmiane r0!, {s16-s31}
+ vldmiaeq r0!, {s16-s31}
+ add      r0, r0, r0
+ add      r1, r1, r1
+ add      r2, r2, r2
+
+ it eq
+ vldmiaeq r0!, {s16-s31}
+
+ it ne
+ addne      r0, r0, r0
+
+@ CHECK:             0: bf0c          ite     eq
+@ CHECK-NEXT:        2: ecb0 8a10     <unknown>
+@ CHECK-NEXT:        6: 1800          addne   r0, r0, r0
+@ CHECK-NEXT:        8: 4409          add     r1, r1
+@ CHECK-NEXT:        a: bf0a          itet    eq
+@ CHECK-NEXT:        c: ecb0 8a10     <unknown>
+@ CHECK-NEXT:       10: ecb0 8a10     <unknown>
+@ CHECK-NEXT:       14: ecb0 8a10     <unknown>
+@ CHECK-NEXT:       18: 4400          add     r0, r0
+@ CHECK-NEXT:       1a: 4409          add     r1, r1
+@ CHECK-NEXT:       1c: 4412          add     r2, r2
+@ CHECK-NEXT:       1e: bf08          it      eq
+@ CHECK-NEXT:       20: ecb0 8a10     <unknown>
+@ CHECK-NEXT:       24: bf18          it      ne
+@ CHECK-NEXT:       26: 1800          addne   r0, r0, r0



More information about the llvm-commits mailing list