[llvm] [BPF] Emit proper error message for insns with tied operands (PR #146778)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 2 14:01:03 PDT 2025


https://github.com/yonghong-song created https://github.com/llvm/llvm-project/pull/146778

Jonathan Cottrill reported a crash in [1] with the following command line:
```
  $ echo 'r0 = atomic_fetch_add((u64*)(r2 + 0), r1)' | llvm-mc --arch bpf --filetype null
```

Note that in the above command, the insn specification requires that r0 and r1 must be the same register. Otherwise, the crash will happen.

Let us add a case Match_InvalidTiedOperand to handle such invalid insns. With this patch, the error message looks like below:
```
  <stdin>:1:39: error: operand is not the same as the dst register
  r0 = atomic_fetch_add((u64*)(r2 + 0), r1)
                                        ^
```
The error message is much better than the crash. Some other insns are also covered by this patch.
```
  $ echo 'w0 = xchg32_32(r2 + 0, w1)' | llvm-mc --arch bpf --filetype null
  <stdin>:1:24: error: operand is not the same as the dst register
  w0 = xchg32_32(r2 + 0, w1)
                         ^
```
  [1] https://github.com/llvm/llvm-project/issues/145180

>From ee3c91f0a324273db41d3b0b6230159a0ff58367 Mon Sep 17 00:00:00 2001
From: Yonghong Song <yonghong.song at linux.dev>
Date: Wed, 2 Jul 2025 13:00:36 -0700
Subject: [PATCH] [BPF] Emit proper error message for insns with tied operands

Jonathan Cottrill reported a crash in [1] with the following command line:
  $ echo 'r0 = atomic_fetch_add((u64*)(r2 + 0), r1)' | llvm-mc --arch bpf --filetype null

Note that in the above command, the insn specification requires that
r0 and r1 must be the same register. Otherwise, the crash will happen.

Let us add a case Match_InvalidTiedOperand to handle such invalid insns.
With this patch, the error message looks like below:
  <stdin>:1:39: error: operand is not the same as the dst register
  r0 = atomic_fetch_add((u64*)(r2 + 0), r1)
                                        ^
The error message is much better than the crash. Some other insns are also
covered by this patch.

  $ echo 'w0 = xchg32_32(r2 + 0, w1)' | llvm-mc --arch bpf --filetype null
  <stdin>:1:24: error: operand is not the same as the dst register
  w0 = xchg32_32(r2 + 0, w1)
                         ^

  [1] https://github.com/llvm/llvm-project/issues/145180
---
 llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp |  3 +++
 llvm/test/MC/BPF/bad-tied.s                    | 12 ++++++++++++
 2 files changed, 15 insertions(+)
 create mode 100644 llvm/test/MC/BPF/bad-tied.s

diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index 88c92da8e95b4..a347794a9a30c 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -348,6 +348,9 @@ bool BPFAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidSImm16:
     return Error(Operands[ErrorInfo]->getStartLoc(),
                  "operand is not a 16-bit signed integer");
+  case Match_InvalidTiedOperand:
+    return Error(Operands[ErrorInfo]->getStartLoc(),
+                 "operand is not the same as the dst register");
   }
 
   llvm_unreachable("Unknown match type detected!");
diff --git a/llvm/test/MC/BPF/bad-tied.s b/llvm/test/MC/BPF/bad-tied.s
new file mode 100644
index 0000000000000..9cd47896c3dd2
--- /dev/null
+++ b/llvm/test/MC/BPF/bad-tied.s
@@ -0,0 +1,12 @@
+# RUN: not llvm-mc -mcpu=v4 -triple bpfel < %s 2>&1 \
+# RUN:   | grep 'error: operand is not the same as the dst register' \
+# RUN:   | count 9
+        r0 = bswap16 r1
+        r0 = bswap32 r1
+        r0 = bswap64 r1
+        r0 = atomic_fetch_add((u64*)(r2 + 0), r1)
+        r0 = atomic_fetch_and((u64*)(r2 + 0), r1)
+        r0 = atomic_fetch_or((u64*)(r2 + 0), r1)
+        r0 = atomic_fetch_xor((u64*)(r2 + 0), r1)
+        w0 = xchg32_32(r2 + 0, w1)
+        r0 = xchg_64(r2 + 0, r1)



More information about the llvm-commits mailing list