[llvm] [BPF] Report an error if comparison imm operand cannot fit in 32bit (PR #142989)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 5 08:21:37 PDT 2025
https://github.com/yonghong-song updated https://github.com/llvm/llvm-project/pull/142989
>From 0ba6601909ea5129ab05762157c4894fc5e6c2a0 Mon Sep 17 00:00:00 2001
From: Yonghong Song <yonghong.song at linux.dev>
Date: Wed, 4 Jun 2025 16:22:53 -0700
Subject: [PATCH] [BPF] Report an error if comparison imm operand cannot fit in
32bit
Ihor Solodrai reported a case ([1]) where gcc reports an error but clang
ignores that error and proceeds to generate incorrect code. More
specifically, the problematic code looks like:
if r1 == 0xcafefeeddeadbeef goto <label>
Here, 0xcafefeeddeadbeef needs to be encoded in a 32-bit imm field
of the insns and the 32-bit imm allows sign extenstion to 64-bit imm.
Obviously, 0xcafefeeddeadbeef cannot encode properly.
The compilation failed for gcc with the following error:
Error: immediate out of range, shall fit in 32 bits
This patch added detection of such violation and will emit the error
error message the same as gcc.
[1] https://lore.kernel.org/bpf/f93ce37e-e155-4165-88e2-1a3cadee7c82@linux.dev/
---
.../BPF/MCTargetDesc/BPFMCCodeEmitter.cpp | 19 +++++++++++++------
llvm/test/CodeGen/BPF/warn-cmp.ll | 10 ++++++++++
2 files changed, 23 insertions(+), 6 deletions(-)
create mode 100644 llvm/test/CodeGen/BPF/warn-cmp.ll
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
index 10a46f100bbea..077522dbd46cb 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
@@ -14,6 +14,7 @@
#include "MCTargetDesc/BPFMCTargetDesc.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInst.h"
@@ -33,11 +34,12 @@ namespace {
class BPFMCCodeEmitter : public MCCodeEmitter {
const MCRegisterInfo &MRI;
bool IsLittleEndian;
+ MCContext &Ctx;
public:
BPFMCCodeEmitter(const MCInstrInfo &, const MCRegisterInfo &mri,
- bool IsLittleEndian)
- : MRI(mri), IsLittleEndian(IsLittleEndian) { }
+ bool IsLittleEndian, MCContext &ctx)
+ : MRI(mri), IsLittleEndian(IsLittleEndian), Ctx(ctx) { }
BPFMCCodeEmitter(const BPFMCCodeEmitter &) = delete;
void operator=(const BPFMCCodeEmitter &) = delete;
~BPFMCCodeEmitter() override = default;
@@ -67,12 +69,12 @@ class BPFMCCodeEmitter : public MCCodeEmitter {
MCCodeEmitter *llvm::createBPFMCCodeEmitter(const MCInstrInfo &MCII,
MCContext &Ctx) {
- return new BPFMCCodeEmitter(MCII, *Ctx.getRegisterInfo(), true);
+ return new BPFMCCodeEmitter(MCII, *Ctx.getRegisterInfo(), true, Ctx);
}
MCCodeEmitter *llvm::createBPFbeMCCodeEmitter(const MCInstrInfo &MCII,
MCContext &Ctx) {
- return new BPFMCCodeEmitter(MCII, *Ctx.getRegisterInfo(), false);
+ return new BPFMCCodeEmitter(MCII, *Ctx.getRegisterInfo(), false, Ctx);
}
unsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI,
@@ -81,8 +83,13 @@ unsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI,
const MCSubtargetInfo &STI) const {
if (MO.isReg())
return MRI.getEncodingValue(MO.getReg());
- if (MO.isImm())
- return static_cast<unsigned>(MO.getImm());
+ if (MO.isImm()) {
+ int64_t Imm = MO.getImm();
+ if (MI.getOpcode() != BPF::LD_imm64 && (Imm < INT_MIN || Imm > UINT_MAX))
+ Ctx.reportError(MI.getLoc(),
+ "immediate out of range, shall fit in 32 bits");
+ return static_cast<unsigned>(Imm);
+ }
assert(MO.isExpr());
diff --git a/llvm/test/CodeGen/BPF/warn-cmp.ll b/llvm/test/CodeGen/BPF/warn-cmp.ll
new file mode 100644
index 0000000000000..a58bb58c03f3c
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/warn-cmp.ll
@@ -0,0 +1,10 @@
+; RUN: not llc -mtriple=bpfel -filetype=obj < %s 2>&1 >/dev/null | FileCheck %s
+
+; CHECK: error: immediate out of range, shall fit in 32 bits
+
+define dso_local void @test() naked {
+ tail call void asm sideeffect
+ "call 7; r1 = r0; r1 <<= 32; call 7; r1 $|= r0; if r1 == 0x1deadbeef goto +1; r0 = 0; exit;",
+ "~{r0},~{r1}"()
+ unreachable
+}
More information about the llvm-commits
mailing list