[llvm] [llubi] Return void for `InstExecutor::visit*` methods (PR #181421)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 13 13:16:52 PST 2026
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/181421
The status is now maintained inside of `setResult` and other helper functions. So we don't need to propagate the error.
This patch was part of https://github.com/llvm/llvm-project/pull/181393.
>From c0cfff1ffbac8ee0083bbb8ca23ce66d3c0bac61 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 14 Feb 2026 05:12:07 +0800
Subject: [PATCH] [llubi] Return void for InstExecutor::visit* methods
---
llvm/tools/llubi/lib/Interpreter.cpp | 404 +++++++++++++--------------
1 file changed, 196 insertions(+), 208 deletions(-)
diff --git a/llvm/tools/llubi/lib/Interpreter.cpp b/llvm/tools/llubi/lib/Interpreter.cpp
index ba4119d7b970a..d4acb0ffcf489 100644
--- a/llvm/tools/llubi/lib/Interpreter.cpp
+++ b/llvm/tools/llubi/lib/Interpreter.cpp
@@ -113,10 +113,9 @@ static AnyValue mulNoWrap(const APInt &LHS, const APInt &RHS, bool HasNSW,
}
/// Instruction executor using the visitor pattern.
-/// visit* methods return true on success, false on error.
/// Unlike the Context class that manages the global state,
/// InstExecutor only maintains the state for call frames.
-class InstExecutor : public InstVisitor<InstExecutor, bool> {
+class InstExecutor : public InstVisitor<InstExecutor, void> {
Context &Ctx;
EventHandler &Handler;
std::list<Frame> CallStack;
@@ -140,11 +139,10 @@ class InstExecutor : public InstVisitor<InstExecutor, bool> {
return CurrentFrame->ValueMap.at(V);
}
- bool setResult(Instruction &I, AnyValue V) {
+ void setResult(Instruction &I, AnyValue V) {
if (Status)
- Handler.onInstructionExecuted(I, V);
+ Status &= Handler.onInstructionExecuted(I, V);
CurrentFrame->ValueMap.insert_or_assign(&I, std::move(V));
- return true;
}
AnyValue computeUnOp(Type *Ty, const AnyValue &Operand,
@@ -160,15 +158,14 @@ class InstExecutor : public InstVisitor<InstExecutor, bool> {
return ScalarFn(Operand);
}
- bool visitUnOp(Instruction &I,
+ void visitUnOp(Instruction &I,
function_ref<AnyValue(const AnyValue &)> ScalarFn) {
- return setResult(
- I, computeUnOp(I.getType(), getValue(I.getOperand(0)), ScalarFn));
+ setResult(I, computeUnOp(I.getType(), getValue(I.getOperand(0)), ScalarFn));
}
- bool visitIntUnOp(Instruction &I,
+ void visitIntUnOp(Instruction &I,
function_ref<AnyValue(const APInt &)> ScalarFn) {
- return visitUnOp(I, [&](const AnyValue &Operand) -> AnyValue {
+ visitUnOp(I, [&](const AnyValue &Operand) -> AnyValue {
if (Operand.isPoison())
return AnyValue::poison();
return ScalarFn(Operand.asInteger());
@@ -190,22 +187,21 @@ class InstExecutor : public InstVisitor<InstExecutor, bool> {
return ScalarFn(LHS, RHS);
}
- bool visitBinOp(
+ void visitBinOp(
Instruction &I,
function_ref<AnyValue(const AnyValue &, const AnyValue &)> ScalarFn) {
- return setResult(I, computeBinOp(I.getType(), getValue(I.getOperand(0)),
- getValue(I.getOperand(1)), ScalarFn));
+ setResult(I, computeBinOp(I.getType(), getValue(I.getOperand(0)),
+ getValue(I.getOperand(1)), ScalarFn));
}
- bool
+ void
visitIntBinOp(Instruction &I,
function_ref<AnyValue(const APInt &, const APInt &)> ScalarFn) {
- return visitBinOp(
- I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
- if (LHS.isPoison() || RHS.isPoison())
- return AnyValue::poison();
- return ScalarFn(LHS.asInteger(), RHS.asInteger());
- });
+ visitBinOp(I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
+ if (LHS.isPoison() || RHS.isPoison())
+ return AnyValue::poison();
+ return ScalarFn(LHS.asInteger(), RHS.asInteger());
+ });
}
public:
@@ -216,148 +212,144 @@ class InstExecutor : public InstVisitor<InstExecutor, bool> {
RetVal, Ctx.getTLIImpl());
}
- bool visitReturnInst(ReturnInst &RI) {
+ void visitReturnInst(ReturnInst &RI) {
if (auto *RV = RI.getReturnValue())
CurrentFrame->RetVal = getValue(RV);
CurrentFrame->State = FrameState::Exit;
- return Handler.onInstructionExecuted(RI, None);
+ Status &= Handler.onInstructionExecuted(RI, None);
}
- bool visitAdd(BinaryOperator &I) {
- return visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) {
+ void visitAdd(BinaryOperator &I) {
+ visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) {
return addNoWrap(LHS, RHS, I.hasNoSignedWrap(), I.hasNoUnsignedWrap());
});
}
- bool visitSub(BinaryOperator &I) {
- return visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) {
+ void visitSub(BinaryOperator &I) {
+ visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) {
return subNoWrap(LHS, RHS, I.hasNoSignedWrap(), I.hasNoUnsignedWrap());
});
}
- bool visitMul(BinaryOperator &I) {
- return visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) {
+ void visitMul(BinaryOperator &I) {
+ visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) {
return mulNoWrap(LHS, RHS, I.hasNoSignedWrap(), I.hasNoUnsignedWrap());
});
}
- bool visitSDiv(BinaryOperator &I) {
- return visitBinOp(
- I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
- // Priority: Immediate UB > poison > normal value
- if (RHS.isPoison()) {
- reportImmediateUB("Division by zero (refine RHS to 0).");
- return AnyValue::poison();
- }
- const APInt &RHSVal = RHS.asInteger();
- if (RHSVal.isZero()) {
- reportImmediateUB("Division by zero.");
- return AnyValue::poison();
- }
- if (LHS.isPoison()) {
- if (RHSVal.isAllOnes())
- reportImmediateUB(
- "Signed division overflow (refine LHS to INT_MIN).");
- return AnyValue::poison();
- }
- const APInt &LHSVal = LHS.asInteger();
- if (LHSVal.isMinSignedValue() && RHSVal.isAllOnes()) {
- reportImmediateUB("Signed division overflow.");
- return AnyValue::poison();
- }
-
- if (I.isExact()) {
- APInt Q, R;
- APInt::sdivrem(LHSVal, RHSVal, Q, R);
- if (!R.isZero())
- return AnyValue::poison();
- return Q;
- } else {
- return LHSVal.sdiv(RHSVal);
- }
- });
- }
-
- bool visitSRem(BinaryOperator &I) {
- return visitBinOp(
- I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
- // Priority: Immediate UB > poison > normal value
- if (RHS.isPoison()) {
- reportImmediateUB("Division by zero (refine RHS to 0).");
- return AnyValue::poison();
- }
- const APInt &RHSVal = RHS.asInteger();
- if (RHSVal.isZero()) {
- reportImmediateUB("Division by zero.");
- return AnyValue::poison();
- }
- if (LHS.isPoison()) {
- if (RHSVal.isAllOnes())
- reportImmediateUB(
- "Signed division overflow (refine LHS to INT_MIN).");
- return AnyValue::poison();
- }
- const APInt &LHSVal = LHS.asInteger();
- if (LHSVal.isMinSignedValue() && RHSVal.isAllOnes()) {
- reportImmediateUB("Signed division overflow.");
- return AnyValue::poison();
- }
-
- return LHSVal.srem(RHSVal);
- });
- }
-
- bool visitUDiv(BinaryOperator &I) {
- return visitBinOp(
- I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
- // Priority: Immediate UB > poison > normal value
- if (RHS.isPoison()) {
- reportImmediateUB("Division by zero (refine RHS to 0).");
- return AnyValue::poison();
- }
- const APInt &RHSVal = RHS.asInteger();
- if (RHSVal.isZero()) {
- reportImmediateUB("Division by zero.");
- return AnyValue::poison();
- }
- if (LHS.isPoison())
- return AnyValue::poison();
- const APInt &LHSVal = LHS.asInteger();
-
- if (I.isExact()) {
- APInt Q, R;
- APInt::udivrem(LHSVal, RHSVal, Q, R);
- if (!R.isZero())
- return AnyValue::poison();
- return Q;
- } else {
- return LHSVal.udiv(RHSVal);
- }
- });
- }
-
- bool visitURem(BinaryOperator &I) {
- return visitBinOp(
- I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
- // Priority: Immediate UB > poison > normal value
- if (RHS.isPoison()) {
- reportImmediateUB("Division by zero (refine RHS to 0).");
- return AnyValue::poison();
- }
- const APInt &RHSVal = RHS.asInteger();
- if (RHSVal.isZero()) {
- reportImmediateUB("Division by zero.");
- return AnyValue::poison();
- }
- if (LHS.isPoison())
- return AnyValue::poison();
- const APInt &LHSVal = LHS.asInteger();
- return LHSVal.urem(RHSVal);
- });
- }
-
- bool visitTruncInst(TruncInst &Trunc) {
- return visitIntUnOp(Trunc, [&](const APInt &Operand) -> AnyValue {
+ void visitSDiv(BinaryOperator &I) {
+ visitBinOp(I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
+ // Priority: Immediate UB > poison > normal value
+ if (RHS.isPoison()) {
+ reportImmediateUB("Division by zero (refine RHS to 0).");
+ return AnyValue::poison();
+ }
+ const APInt &RHSVal = RHS.asInteger();
+ if (RHSVal.isZero()) {
+ reportImmediateUB("Division by zero.");
+ return AnyValue::poison();
+ }
+ if (LHS.isPoison()) {
+ if (RHSVal.isAllOnes())
+ reportImmediateUB(
+ "Signed division overflow (refine LHS to INT_MIN).");
+ return AnyValue::poison();
+ }
+ const APInt &LHSVal = LHS.asInteger();
+ if (LHSVal.isMinSignedValue() && RHSVal.isAllOnes()) {
+ reportImmediateUB("Signed division overflow.");
+ return AnyValue::poison();
+ }
+
+ if (I.isExact()) {
+ APInt Q, R;
+ APInt::sdivrem(LHSVal, RHSVal, Q, R);
+ if (!R.isZero())
+ return AnyValue::poison();
+ return Q;
+ } else {
+ return LHSVal.sdiv(RHSVal);
+ }
+ });
+ }
+
+ void visitSRem(BinaryOperator &I) {
+ visitBinOp(I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
+ // Priority: Immediate UB > poison > normal value
+ if (RHS.isPoison()) {
+ reportImmediateUB("Division by zero (refine RHS to 0).");
+ return AnyValue::poison();
+ }
+ const APInt &RHSVal = RHS.asInteger();
+ if (RHSVal.isZero()) {
+ reportImmediateUB("Division by zero.");
+ return AnyValue::poison();
+ }
+ if (LHS.isPoison()) {
+ if (RHSVal.isAllOnes())
+ reportImmediateUB(
+ "Signed division overflow (refine LHS to INT_MIN).");
+ return AnyValue::poison();
+ }
+ const APInt &LHSVal = LHS.asInteger();
+ if (LHSVal.isMinSignedValue() && RHSVal.isAllOnes()) {
+ reportImmediateUB("Signed division overflow.");
+ return AnyValue::poison();
+ }
+
+ return LHSVal.srem(RHSVal);
+ });
+ }
+
+ void visitUDiv(BinaryOperator &I) {
+ visitBinOp(I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
+ // Priority: Immediate UB > poison > normal value
+ if (RHS.isPoison()) {
+ reportImmediateUB("Division by zero (refine RHS to 0).");
+ return AnyValue::poison();
+ }
+ const APInt &RHSVal = RHS.asInteger();
+ if (RHSVal.isZero()) {
+ reportImmediateUB("Division by zero.");
+ return AnyValue::poison();
+ }
+ if (LHS.isPoison())
+ return AnyValue::poison();
+ const APInt &LHSVal = LHS.asInteger();
+
+ if (I.isExact()) {
+ APInt Q, R;
+ APInt::udivrem(LHSVal, RHSVal, Q, R);
+ if (!R.isZero())
+ return AnyValue::poison();
+ return Q;
+ } else {
+ return LHSVal.udiv(RHSVal);
+ }
+ });
+ }
+
+ void visitURem(BinaryOperator &I) {
+ visitBinOp(I, [&](const AnyValue &LHS, const AnyValue &RHS) -> AnyValue {
+ // Priority: Immediate UB > poison > normal value
+ if (RHS.isPoison()) {
+ reportImmediateUB("Division by zero (refine RHS to 0).");
+ return AnyValue::poison();
+ }
+ const APInt &RHSVal = RHS.asInteger();
+ if (RHSVal.isZero()) {
+ reportImmediateUB("Division by zero.");
+ return AnyValue::poison();
+ }
+ if (LHS.isPoison())
+ return AnyValue::poison();
+ const APInt &LHSVal = LHS.asInteger();
+ return LHSVal.urem(RHSVal);
+ });
+ }
+
+ void visitTruncInst(TruncInst &Trunc) {
+ visitIntUnOp(Trunc, [&](const APInt &Operand) -> AnyValue {
unsigned DestBW = Trunc.getType()->getScalarSizeInBits();
if (Trunc.hasNoSignedWrap() && Operand.getSignificantBits() > DestBW)
return AnyValue::poison();
@@ -367,8 +359,8 @@ class InstExecutor : public InstVisitor<InstExecutor, bool> {
});
}
- bool visitZExtInst(ZExtInst &ZExt) {
- return visitIntUnOp(ZExt, [&](const APInt &Operand) -> AnyValue {
+ void visitZExtInst(ZExtInst &ZExt) {
+ visitIntUnOp(ZExt, [&](const APInt &Operand) -> AnyValue {
uint32_t DestBW = ZExt.getDestTy()->getScalarSizeInBits();
if (ZExt.hasNonNeg() && Operand.isNegative())
return AnyValue::poison();
@@ -376,79 +368,78 @@ class InstExecutor : public InstVisitor<InstExecutor, bool> {
});
}
- bool visitSExtInst(SExtInst &SExt) {
- return visitIntUnOp(SExt, [&](const APInt &Operand) -> AnyValue {
+ void visitSExtInst(SExtInst &SExt) {
+ visitIntUnOp(SExt, [&](const APInt &Operand) -> AnyValue {
uint32_t DestBW = SExt.getDestTy()->getScalarSizeInBits();
return Operand.sext(DestBW);
});
}
- bool visitAnd(BinaryOperator &I) {
- return visitIntBinOp(I, [](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ void visitAnd(BinaryOperator &I) {
+ visitIntBinOp(I, [](const APInt &LHS, const APInt &RHS) -> AnyValue {
return LHS & RHS;
});
}
- bool visitXor(BinaryOperator &I) {
- return visitIntBinOp(I, [](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ void visitXor(BinaryOperator &I) {
+ visitIntBinOp(I, [](const APInt &LHS, const APInt &RHS) -> AnyValue {
return LHS ^ RHS;
});
}
- bool visitOr(BinaryOperator &I) {
- return visitIntBinOp(
- I, [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
- if (cast<PossiblyDisjointInst>(I).isDisjoint() && LHS.intersects(RHS))
- return AnyValue::poison();
- return LHS | RHS;
- });
- }
-
- bool visitShl(BinaryOperator &I) {
- return visitIntBinOp(
- I, [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
- if (RHS.uge(LHS.getBitWidth()))
- return AnyValue::poison();
- if (I.hasNoSignedWrap() && RHS.uge(LHS.getNumSignBits()))
- return AnyValue::poison();
- if (I.hasNoUnsignedWrap() && RHS.ugt(LHS.countl_zero()))
- return AnyValue::poison();
- return LHS.shl(RHS);
- });
- }
-
- bool visitLShr(BinaryOperator &I) {
- return visitIntBinOp(I,
- [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
- if (RHS.uge(cast<PossiblyExactOperator>(I).isExact()
- ? LHS.countr_zero() + 1
- : LHS.getBitWidth()))
- return AnyValue::poison();
- return LHS.lshr(RHS);
- });
- }
-
- bool visitAShr(BinaryOperator &I) {
- return visitIntBinOp(I,
- [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
- if (RHS.uge(cast<PossiblyExactOperator>(I).isExact()
- ? LHS.countr_zero() + 1
- : LHS.getBitWidth()))
- return AnyValue::poison();
- return LHS.ashr(RHS);
- });
- }
-
- bool visitSelect(SelectInst &SI) {
+ void visitOr(BinaryOperator &I) {
+ visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ if (cast<PossiblyDisjointInst>(I).isDisjoint() && LHS.intersects(RHS))
+ return AnyValue::poison();
+ return LHS | RHS;
+ });
+ }
+
+ void visitShl(BinaryOperator &I) {
+ visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ if (RHS.uge(LHS.getBitWidth()))
+ return AnyValue::poison();
+ if (I.hasNoSignedWrap() && RHS.uge(LHS.getNumSignBits()))
+ return AnyValue::poison();
+ if (I.hasNoUnsignedWrap() && RHS.ugt(LHS.countl_zero()))
+ return AnyValue::poison();
+ return LHS.shl(RHS);
+ });
+ }
+
+ void visitLShr(BinaryOperator &I) {
+ visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ if (RHS.uge(cast<PossiblyExactOperator>(I).isExact()
+ ? LHS.countr_zero() + 1
+ : LHS.getBitWidth()))
+ return AnyValue::poison();
+ return LHS.lshr(RHS);
+ });
+ }
+
+ void visitAShr(BinaryOperator &I) {
+ visitIntBinOp(I, [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ if (RHS.uge(cast<PossiblyExactOperator>(I).isExact()
+ ? LHS.countr_zero() + 1
+ : LHS.getBitWidth()))
+ return AnyValue::poison();
+ return LHS.ashr(RHS);
+ });
+ }
+
+ void visitSelect(SelectInst &SI) {
// TODO: handle fast-math flags.
if (SI.getCondition()->getType()->isIntegerTy(1)) {
switch (getValue(SI.getCondition()).asBoolean()) {
case BooleanKind::True:
- return setResult(SI, getValue(SI.getTrueValue()));
+ setResult(SI, getValue(SI.getTrueValue()));
+ return;
case BooleanKind::False:
- return setResult(SI, getValue(SI.getFalseValue()));
+ setResult(SI, getValue(SI.getFalseValue()));
+ return;
case BooleanKind::Poison:
- return setResult(SI, AnyValue::getPoisonValue(Ctx, SI.getType()));
+ setResult(SI, AnyValue::getPoisonValue(Ctx, SI.getType()));
+ return;
}
}
@@ -471,12 +462,12 @@ class InstExecutor : public InstVisitor<InstExecutor, bool> {
break;
}
}
- return setResult(SI, std::move(Res));
+ setResult(SI, std::move(Res));
}
- bool visitInstruction(Instruction &I) {
+ void visitInstruction(Instruction &I) {
Handler.onUnrecognizedInstruction(I);
- return false;
+ Status = false;
}
/// This function implements the main interpreter loop.
@@ -508,10 +499,7 @@ class InstExecutor : public InstVisitor<InstExecutor, bool> {
++Steps;
Instruction &I = *Top.PC;
- if (!visit(&I)) {
- Status = false;
- break;
- }
+ visit(&I);
if (!Status)
break;
More information about the llvm-commits
mailing list