[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