[clang] [clang][bytecode] Remove the !Caller case in Ret opcodes (PR #215226)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 10 02:25:21 PDT 2026


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/215226

The bottom frame is always created via an `EvalEmitter`, which has its own implementation of the `Ret` opcode. The exception is `Context::Run`/`isPotentialConstantExpr`.

>From 1157fff92e4ffb2844a91f02088e5b0d8b5fd8cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 10 Aug 2026 11:23:03 +0200
Subject: [PATCH] [clang][bytecode] Remove the !Caller case in Ret opcodes

---
 clang/lib/AST/ByteCode/Context.cpp |  2 +-
 clang/lib/AST/ByteCode/Interp.h    | 35 ++++++++++++++----------------
 2 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index 9f1d9b899052d..ce7a95ed49c06 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -555,8 +555,8 @@ const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
 }
 
 bool Context::Run(State &Parent, const Function *Func) {
-  InterpState State(Parent, *P, Stk, *this, Func);
   auto Memory = std::make_unique<char[]>(InterpFrame::allocSize(Func));
+  InterpState State(Parent, *P, Stk, *this, Func);
   InterpFrame *Frame = new (Memory.get()) InterpFrame(
       State, Func, /*Caller=*/nullptr, CodePtr(), Func->getArgSize());
   State.Current = Frame;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 582cb108f5816..0af1610181aac 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -298,18 +298,16 @@ PRESERVE_NONE bool Ret(InterpState &S) {
   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
     cleanupAfterFunctionCall(S, S.Current->getFunction());
 
-  if (InterpFrame *Caller = S.Current->Caller) {
-    S.PC = S.Current->getRetPC();
-    InterpFrame::free(S.Current);
-    S.Current = Caller;
-    S.Stk.push<T>(Ret);
-  } else {
-    InterpFrame::free(S.Current);
-    S.Current = nullptr;
-    // The topmost frame should come from an EvalEmitter,
-    // which has its own implementation of the Ret<> instruction.
-  }
+  InterpFrame *Caller = S.Current->Caller;
+
+  // This only happens via Context::Run().
+  if (!Caller)
+    return true;
 
+  S.PC = S.Current->getRetPC();
+  InterpFrame::free(S.Current);
+  S.Current = Caller;
+  S.Stk.push<T>(Ret);
   return true;
 }
 
@@ -321,15 +319,14 @@ PRESERVE_NONE inline bool RetVoid(InterpState &S) {
   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
     cleanupAfterFunctionCall(S, S.Current->getFunction());
 
-  if (InterpFrame *Caller = S.Current->Caller) {
-    S.PC = S.Current->getRetPC();
-    InterpFrame::free(S.Current);
-    S.Current = Caller;
-  } else {
-    InterpFrame::free(S.Current);
-    S.Current = nullptr;
-  }
+  InterpFrame *Caller = S.Current->Caller;
+  // This only happens via Context::Run().
+  if (!Caller)
+    return true;
 
+  S.PC = S.Current->getRetPC();
+  InterpFrame::free(S.Current);
+  S.Current = Caller;
   return true;
 }
 



More information about the cfe-commits mailing list