[llvm] [AArch64] Range-check the ext byte index (PR #214468)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 6 05:30:09 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Zane Hambly (Zaneham)
<details>
<summary>Changes</summary>
`llvm-mc` asserts on an `ext` byte index given as a symbol:
```asm
ext v0.8b, v1.8b, v2.8b, f0
```
```
Assertion failed: MO.isImm() && "did not expect relocated expression",
AArch64MCCodeEmitter.cpp:239
```
`BaseSIMDBitwiseExtract` takes the index as a bare `i32imm`, so nothing requires it to be a constant and it goes straight to the generic encoder. Unlike the FPCLASS comment printer, this one does affect the encoding. With assertions off `getImm()` returns whatever occupies the `MCOperand` union, which for an expression operand is the `MCExpr *`, so the four-bit field ends up holding pointer bits rather than the zero the issue describes.
The same missing constraint silently truncates out-of-range literals, which I don't think has been reported. Before this patch:
```
ext v0.8b, v1.8b, v2.8b, #<!-- -->12 encoding: [0x20,0x20,0x02,0x2e]
ext v0.8b, v1.8b, v2.8b, #<!-- -->4 encoding: [0x20,0x20,0x02,0x2e]
ext v0.16b, v1.16b, v2.16b, #<!-- -->20 encoding: [0x20,0x20,0x02,0x6e]
ext v0.16b, v1.16b, v2.16b, #<!-- -->4 encoding: [0x20,0x20,0x02,0x6e]
```
Index 12 assembles as index 4 on the 64-bit form because the class forces `imm{3}` to 0, and 20 becomes 4 on the 128-bit form. No diagnostic in either case.
Both forms now take a constrained operand, `imm32_0_7` and `imm32_0_15`, which already exist with the parser match classes this wants. The operand stays i32 so the selection pattern is untouched. Symbolic and out-of-range indices both get the usual range diagnostic, and valid indices assemble exactly as before.
`let imm{3} = 0;` on the 64-bit form is redundant now that the operand cannot exceed 7. I left it to keep the diff small, but happy to drop it if you'd rather.
This also covers the `ext` part of #<!-- -->185358, including the Apple `ext.8b v0, v1, v2` syntax. The `scvtf`/`ucvtf` half of that one asserts elsewhere and I'll send it separately.
Fixes #<!-- -->185361
---
Full diff: https://github.com/llvm/llvm-project/pull/214468.diff
3 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64InstrFormats.td (+4-4)
- (modified) llvm/test/MC/AArch64/neon-diagnostics.s (+30)
- (modified) llvm/test/MC/AArch64/neon-extract.s (+13)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 58fc5ec063c15..cbe57d033e178 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -7684,8 +7684,8 @@ multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
//----------------------------------------------------------------------------
class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
- string asm, string kind>
- : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
+ Operand immtype, string asm, string kind>
+ : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, immtype:$imm), asm,
"{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
"|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
[(set (vty regtype:$Rd),
@@ -7708,10 +7708,10 @@ class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
multiclass SIMDBitwiseExtract<string asm> {
- def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
+ def v8i8 : BaseSIMDBitwiseExtract<0, V64, v8i8, imm32_0_7, asm, ".8b"> {
let imm{3} = 0;
}
- def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
+ def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, imm32_0_15, asm, ".16b">;
}
//----------------------------------------------------------------------------
diff --git a/llvm/test/MC/AArch64/neon-diagnostics.s b/llvm/test/MC/AArch64/neon-diagnostics.s
index 2610f4acf383b..3f9073b792646 100644
--- a/llvm/test/MC/AArch64/neon-diagnostics.s
+++ b/llvm/test/MC/AArch64/neon-diagnostics.s
@@ -7151,3 +7151,33 @@
// CHECK-ERROR: error: invalid operand for instruction
// CHECK-ERROR: fabd d29, s24, d20
// CHECK-ERROR: ^
+
+//----------------------------------------------------------------------
+// Vector Bitwise Extract
+//----------------------------------------------------------------------
+
+ ext v0.8b, v1.8b, v2.8b, #8
+ ext v0.8b, v1.8b, v2.8b, #12
+ ext v0.16b, v1.16b, v2.16b, #16
+ ext v0.16b, v1.16b, v2.16b, #20
+ ext v0.8b, v1.8b, v2.8b, sym
+ ext v0.16b, v1.16b, v2.16b, sym
+
+// CHECK-ERROR: error: immediate must be an integer in range [0, 7].
+// CHECK-ERROR: ext v0.8b, v1.8b, v2.8b, #8
+// CHECK-ERROR: ^
+// CHECK-ERROR: error: immediate must be an integer in range [0, 7].
+// CHECK-ERROR: ext v0.8b, v1.8b, v2.8b, #12
+// CHECK-ERROR: ^
+// CHECK-ERROR: error: immediate must be an integer in range [0, 15].
+// CHECK-ERROR: ext v0.16b, v1.16b, v2.16b, #16
+// CHECK-ERROR: ^
+// CHECK-ERROR: error: immediate must be an integer in range [0, 15].
+// CHECK-ERROR: ext v0.16b, v1.16b, v2.16b, #20
+// CHECK-ERROR: ^
+// CHECK-ERROR: error: immediate must be an integer in range [0, 7].
+// CHECK-ERROR: ext v0.8b, v1.8b, v2.8b, sym
+// CHECK-ERROR: ^
+// CHECK-ERROR: error: immediate must be an integer in range [0, 15].
+// CHECK-ERROR: ext v0.16b, v1.16b, v2.16b, sym
+// CHECK-ERROR: ^
diff --git a/llvm/test/MC/AArch64/neon-extract.s b/llvm/test/MC/AArch64/neon-extract.s
index 1daa46d096eee..c92b98f43da26 100644
--- a/llvm/test/MC/AArch64/neon-extract.s
+++ b/llvm/test/MC/AArch64/neon-extract.s
@@ -11,3 +11,16 @@
// CHECK: ext v0.8b, v1.8b, v2.8b, #{{0x3|3}} // encoding: [0x20,0x18,0x02,0x2e]
// CHECK: ext v0.16b, v1.16b, v2.16b, #{{0x3|3}} // encoding: [0x20,0x18,0x02,0x6e]
+
+// The index is four bits wide, but only three of them are available on the
+// 64-bit form. Check both ends of each range.
+
+ ext v0.8b, v1.8b, v2.8b, #0
+ ext v0.8b, v1.8b, v2.8b, #7
+ ext v0.16b, v1.16b, v2.16b, #0
+ ext v0.16b, v1.16b, v2.16b, #15
+
+// CHECK: ext v0.8b, v1.8b, v2.8b, #{{0x0|0}} // encoding: [0x20,0x00,0x02,0x2e]
+// CHECK: ext v0.8b, v1.8b, v2.8b, #{{0x7|7}} // encoding: [0x20,0x38,0x02,0x2e]
+// CHECK: ext v0.16b, v1.16b, v2.16b, #{{0x0|0}} // encoding: [0x20,0x00,0x02,0x6e]
+// CHECK: ext v0.16b, v1.16b, v2.16b, #{{0xf|15}} // encoding: [0x20,0x78,0x02,0x6e]
``````````
</details>
https://github.com/llvm/llvm-project/pull/214468
More information about the llvm-commits
mailing list