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

Instead of using a local variable for the PC, save it in `InterpState`. Only 
comparatively few opcodes care about it, but with exceptions, all calls ops can 
change the PC. Saving it in the `InterpState` makes it easier to have opcode 
implementation jump around in bytecode.



>From 6ec4d93ccb6b71d74dcb7ef0e1d172893d8e6dc0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 3 Jul 2026 13:01:35 +0200
Subject: [PATCH] PC

---
 clang/lib/AST/ByteCode/Interp.cpp            | 116 ++++++++-----------
 clang/lib/AST/ByteCode/Interp.h              |  19 ++-
 clang/lib/AST/ByteCode/InterpFrame.cpp       |  14 +--
 clang/lib/AST/ByteCode/InterpFrame.h         |  11 +-
 clang/lib/AST/ByteCode/InterpStack.cpp       |   6 +
 clang/lib/AST/ByteCode/InterpStack.h         |   1 +
 clang/lib/AST/ByteCode/InterpState.cpp       |   2 +-
 clang/lib/AST/ByteCode/InterpState.h         |   1 +
 clang/lib/AST/ByteCode/Opcodes.td            |   6 -
 clang/lib/AST/ByteCode/Source.h              |   2 +
 clang/utils/TableGen/ClangOpcodesEmitter.cpp |  41 ++++---
 11 files changed, 102 insertions(+), 117 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 4815828adb613..dc93cc4fd698c 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -49,7 +49,7 @@ using namespace clang::interp;
 #define USE_TAILCALLS 1
 #endif
 
-PRESERVE_NONE static bool RetValue(InterpState &S, CodePtr &Ptr) {
+PRESERVE_NONE static bool RetValue(InterpState &S) {
   llvm::report_fatal_error("Interpreter cannot return values");
 }
 
@@ -57,23 +57,23 @@ PRESERVE_NONE static bool RetValue(InterpState &S, CodePtr 
&Ptr) {
 // Jmp, Jt, Jf
 
//===----------------------------------------------------------------------===//
 
-static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset) {
-  PC += Offset;
-  return S.noteStep(PC);
+static bool Jmp(InterpState &S, CodePtr OpPC, int32_t Offset) {
+  S.PC += Offset;
+  return S.noteStep(OpPC);
 }
 
-static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
+static bool Jt(InterpState &S, CodePtr OpPC, int32_t Offset) {
   if (S.Stk.pop<bool>()) {
-    PC += Offset;
-    return S.noteStep(PC);
+    S.PC += Offset;
+    return S.noteStep(OpPC);
   }
   return true;
 }
 
-static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
+static bool Jf(InterpState &S, CodePtr OpPC, int32_t Offset) {
   if (!S.Stk.pop<bool>()) {
-    PC += Offset;
-    return S.noteStep(PC);
+    S.PC += Offset;
+    return S.noteStep(OpPC);
   }
   return true;
 }
@@ -234,43 +234,20 @@ static bool CheckGlobal(InterpState &S, CodePtr OpPC, 
const Pointer &Ptr) {
 
 namespace clang {
 namespace interp {
-PRESERVE_NONE static bool BCP(InterpState &S, CodePtr &RealPC, int32_t Offset,
+PRESERVE_NONE static bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset,
                               PrimType PT);
 
-static void popArg(InterpState &S, const Expr *Arg) {
-  PrimType Ty = S.getContext().classify(Arg).value_or(PT_Ptr);
-  TYPE_SWITCH(Ty, S.Stk.discard<T>());
-}
-
-void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
-                              const Function *Func) {
+void cleanupAfterFunctionCall(InterpState &S, const Function *Func) {
   assert(S.Current);
   assert(Func);
 
+  // Pop variadic parameter values from the stack.
   if (S.Current->Caller && Func->isVariadic()) {
-    // CallExpr we're look for is at the return PC of the current function, 
i.e.
-    // in the caller.
-    // This code path should be executed very rarely.
-    unsigned NumVarArgs;
-    const Expr *const *Args = nullptr;
-    unsigned NumArgs = 0;
-    const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
-    if (const auto *CE = dyn_cast<CallExpr>(CallSite)) {
-      Args = CE->getArgs();
-      NumArgs = CE->getNumArgs();
-    } else if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite)) {
-      Args = CE->getArgs();
-      NumArgs = CE->getNumArgs();
-    } else
-      assert(false && "Can't get arguments from that expression type");
-
-    assert(NumArgs >= Func->getNumWrittenParams());
-    NumVarArgs = NumArgs - (Func->getNumWrittenParams() +
-                            (isa<CXXOperatorCallExpr>(CallSite) &&
-                             Func->hasImplicitThisParam()));
-    for (unsigned I = 0; I != NumVarArgs; ++I) {
-      const Expr *A = Args[NumArgs - 1 - I];
-      popArg(S, A);
+    unsigned VariadicArgSize =
+        S.Current->getArgSize() - S.Current->getFunction()->getArgSize();
+    unsigned TargetStackSize = S.Stk.size() - VariadicArgSize;
+    while (S.Stk.size() != TargetStackSize) {
+      S.Stk.discardSlow();
     }
   }
 
@@ -1847,7 +1824,7 @@ bool CallVar(InterpState &S, CodePtr OpPC, const Function 
*Func,
     return false;
 
   auto Memory = new char[InterpFrame::allocSize(Func)];
-  auto NewFrame = new (Memory) InterpFrame(S, Func, OpPC, VarArgSize);
+  auto NewFrame = new (Memory) InterpFrame(S, Func, S.PC, VarArgSize);
   InterpFrame *FrameBefore = S.Current;
   S.Current = NewFrame;
 
@@ -1872,7 +1849,7 @@ bool Call(InterpState &S, CodePtr OpPC, const Function 
*Func,
 
   assert(Func);
   auto cleanup = [&]() -> bool {
-    cleanupAfterFunctionCall(S, OpPC, Func);
+    cleanupAfterFunctionCall(S, Func);
     return false;
   };
 
@@ -1940,7 +1917,7 @@ bool Call(InterpState &S, CodePtr OpPC, const Function 
*Func,
     return cleanup();
 
   auto Memory = new char[InterpFrame::allocSize(Func)];
-  auto NewFrame = new (Memory) InterpFrame(S, Func, OpPC, VarArgSize);
+  auto NewFrame = new (Memory) InterpFrame(S, Func, S.PC, VarArgSize);
   InterpFrame *FrameBefore = S.Current;
   S.Current = NewFrame;
 
@@ -3124,7 +3101,7 @@ constexpr bool OpReturns(Opcode Op) {
 }
 
 #if USE_TAILCALLS
-PRESERVE_NONE static bool InterpNext(InterpState &S, CodePtr &PC);
+PRESERVE_NONE static bool InterpNext(InterpState &S);
 #endif
 
 // The dispatcher functions read the opcode arguments from the
@@ -3133,7 +3110,7 @@ PRESERVE_NONE static bool InterpNext(InterpState &S, 
CodePtr &PC);
 #include "Opcodes.inc"
 #undef GET_INTERPFN_DISPATCHERS
 
-using InterpFn = bool (*)(InterpState &, CodePtr &PC) PRESERVE_NONE;
+using InterpFn = bool (*)(InterpState &) PRESERVE_NONE;
 // Array of the dispatcher functions defined above.
 const InterpFn InterpFunctions[] = {
 #define GET_INTERPFN_LIST
@@ -3143,10 +3120,10 @@ const InterpFn InterpFunctions[] = {
 
 #if USE_TAILCALLS
 // Read the next opcode and call the dispatcher function.
-PRESERVE_NONE static bool InterpNext(InterpState &S, CodePtr &PC) {
-  auto Op = PC.read<Opcode>();
+PRESERVE_NONE static bool InterpNext(InterpState &S) {
+  auto Op = S.PC.read<Opcode>();
   auto Fn = InterpFunctions[Op];
-  MUSTTAIL return Fn(S, PC);
+  MUSTTAIL return Fn(S);
 }
 #endif
 
@@ -3156,16 +3133,17 @@ bool Interpret(InterpState &S) {
   // to return from this function and thus terminate
   // interpretation.
   assert(!S.Current->isRoot());
-  CodePtr PC = S.Current->getPC();
+
+  S.PC = S.Current->getFunction()->getCodeBegin();
 
 #if USE_TAILCALLS
-  return InterpNext(S, PC);
+  return InterpNext(S);
 #else
   while (true) {
-    auto Op = PC.read<Opcode>();
+    auto Op = S.PC.read<Opcode>();
     auto Fn = InterpFunctions[Op];
 
-    if (!Fn(S, PC))
+    if (!Fn(S))
       return false;
     if (OpReturns(Op))
       break;
@@ -3184,9 +3162,10 @@ bool Interpret(InterpState &S) {
 /// This way, we return back to this function when we see an EndSpeculation,
 /// OR (of course), when we encounter an error and one of the opcodes
 /// returns false.
-PRESERVE_NONE static bool BCP(InterpState &S, CodePtr &RealPC, int32_t Offset,
+PRESERVE_NONE static bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset,
                               PrimType PT) {
-  [[maybe_unused]] CodePtr PCBefore = RealPC;
+  // PC after reading the BCP opcode and both Offset/PT arguments.
+  [[maybe_unused]] CodePtr PCBefore = S.PC;
   size_t StackSizeBefore = S.Stk.size();
 
   // Speculation depth must be at least 1 here, since we must have
@@ -3196,22 +3175,21 @@ PRESERVE_NONE static bool BCP(InterpState &S, CodePtr 
&RealPC, int32_t Offset,
   assert(DepthBefore >= 1);
 #endif
 
-  CodePtr PC = RealPC;
-  auto SpeculativeInterp = [&S, &PC]() -> bool {
+  auto SpeculativeInterp = [&S, OpPC]() -> bool {
     // Ignore diagnostics during speculative execution.
-    PushIgnoreDiags(S, PC);
-    auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S, PC); });
+    PushIgnoreDiags(S, OpPC);
+    auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S, OpPC); });
 
 #if USE_TAILCALLS
-    auto Op = PC.read<Opcode>();
+    auto Op = S.PC.read<Opcode>();
     auto Fn = InterpFunctions[Op];
-    return Fn(S, PC);
+    return Fn(S);
 #else
     while (true) {
-      auto Op = PC.read<Opcode>();
+      auto Op = S.PC.read<Opcode>();
       auto Fn = InterpFunctions[Op];
 
-      if (!Fn(S, PC))
+      if (!Fn(S))
         return false;
       if (OpReturns(Op))
         break;
@@ -3235,20 +3213,21 @@ PRESERVE_NONE static bool BCP(InterpState &S, CodePtr 
&RealPC, int32_t Offset,
       S.Stk.push<Integral<32, true>>(Integral<32, true>::from(1));
     }
   } else {
+    // Jump to the end of the speculation, just after the actual EndSpeculation
+    // op.
+    S.PC = PCBefore + Offset - align(sizeof(Opcode));
+
     // End the speculation manually since we didn't call EndSpeculation
     // naturally.
-    EndSpeculation(S, RealPC);
+    EndSpeculation(S);
 
     if (!S.inConstantContext())
-      return Invalid(S, RealPC);
+      return Invalid(S, OpPC);
 
     S.Stk.clearTo(StackSizeBefore);
     S.Stk.push<Integral<32, true>>(Integral<32, true>::from(0));
   }
 
-  // RealPC should not have been modified.
-  assert(*RealPC == *PCBefore);
-
   // We have already evaluated this speculation's EndSpeculation opcode.
   assert(S.SpeculationDepth == DepthBefore - 1);
 
@@ -3258,7 +3237,6 @@ PRESERVE_NONE static bool BCP(InterpState &S, CodePtr 
&RealPC, int32_t Offset,
   // bool and PrimType arguments again.
   int32_t ParamSize = align(sizeof(PrimType));
   assert(Offset >= ParamSize);
-  RealPC += Offset - ParamSize;
 
   return true;
 }
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 84564d0a33cff..61c2b0a5e5960 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -254,11 +254,10 @@ enum class ArithOp { Add, Sub };
 // Returning values
 
//===----------------------------------------------------------------------===//
 
-void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
-                              const Function *Func);
+void cleanupAfterFunctionCall(InterpState &S, const Function *Func);
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC) {
+PRESERVE_NONE bool Ret(InterpState &S) {
   const T &Ret = S.Stk.pop<T>();
 
   assert(S.Current);
@@ -266,11 +265,12 @@ PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC) {
 #ifndef NDEBUG
   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
 #endif
+
   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
-    cleanupAfterFunctionCall(S, PC, S.Current->getFunction());
+    cleanupAfterFunctionCall(S, S.Current->getFunction());
 
   if (InterpFrame *Caller = S.Current->Caller) {
-    PC = S.Current->getRetPC();
+    S.PC = S.Current->getRetPC();
     InterpFrame::free(S.Current);
     S.Current = Caller;
     S.Stk.push<T>(Ret);
@@ -284,17 +284,16 @@ PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC) {
   return true;
 }
 
-PRESERVE_NONE inline bool RetVoid(InterpState &S, CodePtr &PC) {
-
+PRESERVE_NONE inline bool RetVoid(InterpState &S) {
 #ifndef NDEBUG
   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
 #endif
 
   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
-    cleanupAfterFunctionCall(S, PC, S.Current->getFunction());
+    cleanupAfterFunctionCall(S, S.Current->getFunction());
 
   if (InterpFrame *Caller = S.Current->Caller) {
-    PC = S.Current->getRetPC();
+    S.PC = S.Current->getRetPC();
     InterpFrame::free(S.Current);
     S.Current = Caller;
   } else {
@@ -3699,7 +3698,7 @@ inline bool EndInit(InterpState &S, CodePtr OpPC) {
 // This is special-cased in the tablegen opcode emitter.
 // Its dispatch function will NOT call InterpNext
 // and instead simply return true.
-PRESERVE_NONE inline bool EndSpeculation(InterpState &S, CodePtr &OpPC) {
+PRESERVE_NONE inline bool EndSpeculation(InterpState &S) {
 #ifndef NDEBUG
   assert(S.SpeculationDepth != 0);
   --S.SpeculationDepth;
diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp 
b/clang/lib/AST/ByteCode/InterpFrame.cpp
index 7366aca114ca0..64bad66b9b6c8 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -160,7 +160,7 @@ void InterpFrame::describe(llvm::raw_ostream &OS) const {
     return;
 
   const ASTContext &ASTCtx = S.getASTContext();
-  const Expr *CallExpr = Caller->getExpr(getRetPC());
+  const Expr *CallExpr = Caller->getExpr(getRetOpPC());
   const FunctionDecl *F = getCallee();
   auto PrintingPolicy = ASTCtx.getPrintingPolicy();
   PrintingPolicy.SuppressLambdaBody = true;
@@ -227,7 +227,7 @@ SourceRange InterpFrame::getCallRange() const {
     if (!C->RetPC)
       continue;
     SourceRange CallRange =
-        S.getRange(C->Caller->Func, C->RetPC - sizeof(uintptr_t));
+        S.getRange(C->Caller->Func, C->getRetOpPC() - sizeof(uintptr_t));
     if (CallRange.isValid())
       return CallRange;
   }
@@ -280,34 +280,34 @@ SourceInfo InterpFrame::getSource(CodePtr PC) const {
   // Implicitly created functions don't have any code we could point at,
   // so return the call site.
   if (Func && !funcHasUsableBody(Func) && Caller)
-    return Caller->getSource(RetPC);
+    return Caller->getSource(getRetOpPC());
 
   // Similarly, if the resulting source location is invalid anyway,
   // point to the caller instead.
   SourceInfo Result = S.getSource(Func, PC);
   if (Result.getLoc().isInvalid() && Caller)
-    return Caller->getSource(RetPC);
+    return Caller->getSource(getRetOpPC());
 
   return Result;
 }
 
 const Expr *InterpFrame::getExpr(CodePtr PC) const {
   if (Func && !funcHasUsableBody(Func) && Caller)
-    return Caller->getExpr(RetPC);
+    return Caller->getExpr(getRetOpPC());
 
   return S.getExpr(Func, PC);
 }
 
 SourceLocation InterpFrame::getLocation(CodePtr PC) const {
   if (Func && !funcHasUsableBody(Func) && Caller)
-    return Caller->getLocation(RetPC);
+    return Caller->getLocation(getRetOpPC());
 
   return S.getLocation(Func, PC);
 }
 
 SourceRange InterpFrame::getRange(CodePtr PC) const {
   if (Func && !funcHasUsableBody(Func) && Caller)
-    return Caller->getRange(RetPC);
+    return Caller->getRange(getRetOpPC());
 
   return S.getRange(Func, PC);
 }
diff --git a/clang/lib/AST/ByteCode/InterpFrame.h 
b/clang/lib/AST/ByteCode/InterpFrame.h
index 731ffddc5a68d..9498a911f2892 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.h
+++ b/clang/lib/AST/ByteCode/InterpFrame.h
@@ -149,11 +149,15 @@ class InterpFrame final : public Frame {
   /// Checks if the frame is a root frame - return should quit the interpreter.
   bool isRoot() const { return !Func; }
 
-  /// Returns the PC of the frame's code start.
-  CodePtr getPC() const { return Func->getCodeBegin(); }
-
   /// Returns the return address of the frame.
   CodePtr getRetPC() const { return RetPC; }
+  /// Returns the return address of the opcode in the caller frame.
+  CodePtr getRetOpPC() const {
+    // All the Call ops we have take a Function* and an unsigned.
+    if (RetPC)
+      return RetPC - align(sizeof(void *)) - align(sizeof(unsigned));
+    return RetPC;
+  }
 
   /// Map a location to a source.
   SourceInfo getSource(CodePtr PC) const;
@@ -162,6 +166,7 @@ class InterpFrame final : public Frame {
   SourceRange getRange(CodePtr PC) const;
 
   unsigned getDepth() const { return Depth; }
+  unsigned getArgSize() const { return ArgSize; }
 
   bool isStdFunction() const;
 
diff --git a/clang/lib/AST/ByteCode/InterpStack.cpp 
b/clang/lib/AST/ByteCode/InterpStack.cpp
index 461bc35979247..839540a7912f8 100644
--- a/clang/lib/AST/ByteCode/InterpStack.cpp
+++ b/clang/lib/AST/ByteCode/InterpStack.cpp
@@ -118,3 +118,9 @@ void InterpStack::dump() const {
     ++Index;
   }
 }
+
+void InterpStack::discardSlow() {
+  assert(!empty());
+
+  TYPE_SWITCH(ItemTypes.back(), { discard<T>(); });
+}
diff --git a/clang/lib/AST/ByteCode/InterpStack.h 
b/clang/lib/AST/ByteCode/InterpStack.h
index 6d58f5a24bd77..2c02979ee6eec 100644
--- a/clang/lib/AST/ByteCode/InterpStack.h
+++ b/clang/lib/AST/ByteCode/InterpStack.h
@@ -57,6 +57,7 @@ class InterpStack final {
     }
     shrink(aligned_size<T>());
   }
+  void discardSlow();
 
   /// Returns a reference to the value on the top of the stack.
   template <typename T> T &peek() const {
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp 
b/clang/lib/AST/ByteCode/InterpState.cpp
index 2d6ed98e6b52c..f6338cda56e34 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -149,7 +149,7 @@ StdAllocatorCaller 
InterpState::getStdAllocatorCaller(StringRef Name) const {
     if (CTSD->isInStdNamespace() && ClassII && ClassII->isStr("allocator") &&
         TAL.size() >= 1 && TAL[0].getKind() == TemplateArgument::Type) {
       QualType ElemType = TAL[0].getAsType();
-      const auto *NewCall = cast<CallExpr>(F->Caller->getExpr(F->getRetPC()));
+      const auto *NewCall = 
cast<CallExpr>(F->Caller->getExpr(F->getRetOpPC()));
       return {NewCall, ElemType};
     }
   }
diff --git a/clang/lib/AST/ByteCode/InterpState.h 
b/clang/lib/AST/ByteCode/InterpState.h
index 4e4a053d6bbed..050fa4c77cd2f 100644
--- a/clang/lib/AST/ByteCode/InterpState.h
+++ b/clang/lib/AST/ByteCode/InterpState.h
@@ -177,6 +177,7 @@ class InterpState final : public State, public SourceMapper 
{
   mutable std::optional<llvm::BumpPtrAllocator> Allocator;
 
 public:
+  CodePtr PC;
   /// Reference to the module containing all bytecode.
   Program &P;
   /// Temporary stack.
diff --git a/clang/lib/AST/ByteCode/Opcodes.td 
b/clang/lib/AST/ByteCode/Opcodes.td
index 7cda124b40e24..8123ca7497335 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -141,7 +141,6 @@ class Opcode {
   list<ArgType> Args = [];
   string Name = "";
   bit CanReturn = 0;
-  bit ChangesPC = 0;
   bit HasCustomLink = 0;
   bit HasCustomEval = 0;
   bit HasGroup = 0;
@@ -172,7 +171,6 @@ class IntegerOpcode : Opcode {
 
 class JumpOpcode : Opcode {
   let Args = [ArgSint32];
-  let ChangesPC = 1;
   let HasCustomEval = 1;
 }
 
@@ -192,7 +190,6 @@ def EndInit : SuccessOpcode;
 def StartSpeculation : SuccessOpcode;
 def EndSpeculation : SuccessOpcode;
 def BCP : Opcode {
-  let ChangesPC = 1;
   let HasCustomEval = 1;
   let Args = [ArgSint32, ArgPrimType];
 }
@@ -204,7 +201,6 @@ def BCP : Opcode {
 // [Value] -> []
 def Ret : Opcode {
   let Types = [AllTypeClass];
-  let ChangesPC = 1;
   let CanReturn = 1;
   let HasGroup = 1;
   let HasCustomEval = 1;
@@ -213,14 +209,12 @@ def Ret : Opcode {
 // [] -> []
 def RetVoid : Opcode {
   let CanReturn = 1;
-  let ChangesPC = 1;
   let HasCustomEval = 1;
   let CanFail = 0;
 }
 // [Value] -> []
 def RetValue : Opcode {
   let CanReturn = 1;
-  let ChangesPC = 1;
   let HasCustomEval = 1;
 }
 // [] -> EXIT
diff --git a/clang/lib/AST/ByteCode/Source.h b/clang/lib/AST/ByteCode/Source.h
index 56ca197e66473..464c1c8bc9811 100644
--- a/clang/lib/AST/ByteCode/Source.h
+++ b/clang/lib/AST/ByteCode/Source.h
@@ -36,6 +36,8 @@ class CodePtr final {
     return *this;
   }
 
+  CodePtr operator+(int32_t Offset) { return CodePtr(Ptr + Offset); }
+
   int32_t operator-(const CodePtr &RHS) const {
     assert(Ptr != nullptr && RHS.Ptr != nullptr && "Invalid code pointer");
     return Ptr - RHS.Ptr;
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp 
b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index 7fef309e127ef..13a99900bc9ec 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -115,25 +115,23 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
   OS << "#ifdef GET_INTERPFN_DISPATCHERS\n";
   // PRESERVE NONE static bool Interp_* (InterpState &S, CodePtr &PC) {
   Enumerate(R, N, [&](ArrayRef<const Record *> TS, const Twine &ID) {
-    OS << "PRESERVE_NONE\nstatic bool Interp_" << ID
-       << "(InterpState &S, CodePtr &PC) {\n";
+    OS << "PRESERVE_NONE\nstatic bool Interp_" << ID << "(InterpState &S) {\n";
 
     if (ID.str() == "EndSpeculation") {
-      OS << "    MUSTTAIL return EndSpeculation(S, PC);\n";
+      OS << "    MUSTTAIL return EndSpeculation(S);\n";
       OS << "}\n";
       return;
     }
 
     bool CanReturn = R->getValueAsBit("CanReturn");
     const auto &Args = R->getValueAsListOfDefs("Args");
-    bool ChangesPC = R->getValueAsBit("ChangesPC");
     bool CanFail = R->getValueAsBit("CanFail");
 
     if (Args.empty()) {
       if (CanReturn) {
         OS << " MUSTTAIL return " << N;
         PrintTypes(OS, TS);
-        OS << "(S, PC);\n";
+        OS << "(S);\n";
         OS << "}\n";
         return;
       }
@@ -144,7 +142,7 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
 
       OS << N;
       PrintTypes(OS, TS);
-      OS << "(S, PC)";
+      OS << "(S, S.PC)";
 
       if (CanFail)
         OS << ") return false";
@@ -152,7 +150,7 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
       OS << ";\n";
 
       OS << "#if USE_TAILCALLS\n";
-      OS << "  MUSTTAIL return InterpNext(S, PC);\n";
+      OS << "  MUSTTAIL return InterpNext(S);\n";
       OS << "#else\n";
       OS << "  return true;\n";
       OS << "#endif\n";
@@ -162,8 +160,7 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
 
     OS << "  {\n";
 
-    if (!ChangesPC)
-      OS << "    CodePtr OpPC = PC;\n";
+    OS << "    CodePtr OpPC = S.PC;\n";
 
     // Emit calls to read arguments.
     for (size_t I = 0, N = Args.size(); I < N; ++I) {
@@ -175,7 +172,7 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
       else
         OS << "    const auto V" << I;
       OS << " = ";
-      OS << "ReadArg<" << Arg->getValueAsString("Name") << ">(S, PC);\n";
+      OS << "ReadArg<" << Arg->getValueAsString("Name") << ">(S, S.PC);\n";
     }
 
     OS << "    ";
@@ -185,10 +182,7 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
     OS << N;
     PrintTypes(OS, TS);
     OS << "(S";
-    if (ChangesPC)
-      OS << ", PC";
-    else
-      OS << ", OpPC";
+    OS << ", OpPC";
     for (size_t I = 0, N = Args.size(); I < N; ++I)
       OS << ", V" << I;
 
@@ -202,7 +196,7 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
 
     if (!CanReturn) {
       OS << "#if USE_TAILCALLS\n";
-      OS << "  MUSTTAIL return InterpNext(S, PC);\n";
+      OS << "  MUSTTAIL return InterpNext(S);\n";
       OS << "#else\n";
       OS << "  return true;\n";
       OS << "#endif\n";
@@ -434,12 +428,17 @@ void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, 
StringRef N,
               OS << "  if (!isActive()) return true;\n";
               OS << "  CurrentSource = L;\n";
 
-              OS << "  return " << N;
-              PrintTypes(OS, TS);
-              OS << "(S, OpPC";
-              for (size_t I = 0, N = Args.size(); I < N; ++I)
-                OS << ", A" << I;
-              OS << ");\n";
+              if (N == "EndSpeculation") {
+                OS << "return EndSpeculation(S);\n";
+              } else {
+
+                OS << "  return " << N;
+                PrintTypes(OS, TS);
+                OS << "(S, OpPC";
+                for (size_t I = 0, N = Args.size(); I < N; ++I)
+                  OS << ", A" << I;
+                OS << ");\n";
+              }
               OS << "}\n";
             });
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to