[clang] 7a3767e - [clang][bytecode] Only pass OpPC if needed (#207479)

via cfe-commits cfe-commits at lists.llvm.org
Sat Jul 4 10:56:57 PDT 2026


Author: Timm Baeder
Date: 2026-07-04T19:56:52+02:00
New Revision: 7a3767e361cc0d6acc8e1568727a54d9b0d0b525

URL: https://github.com/llvm/llvm-project/commit/7a3767e361cc0d6acc8e1568727a54d9b0d0b525
DIFF: https://github.com/llvm/llvm-project/commit/7a3767e361cc0d6acc8e1568727a54d9b0d0b525.diff

LOG: [clang][bytecode] Only pass OpPC if needed (#207479)

Quite a few opcode implementations don't ever report a diagnostic, so
they don't need the `OpPC` at all. Add a tablegen bit to disable passing
`OpPC` altogether.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/EvalEmitter.cpp
    clang/lib/AST/ByteCode/Interp.cpp
    clang/lib/AST/ByteCode/Interp.h
    clang/lib/AST/ByteCode/Opcodes.td
    clang/utils/TableGen/ClangOpcodesEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index dbec700c80d44..34c85c7c66bdd 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -209,8 +209,8 @@ bool EvalEmitter::speculate(const CallExpr *E, const LabelTy &EndLabel) {
   if (!isActive())
     return true;
 
-  PushIgnoreDiags(S, OpPC);
-  auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S, OpPC); });
+  PushIgnoreDiags(S);
+  auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S); });
 
   size_t StackSizeBefore = S.Stk.size();
   const Expr *Arg = E->getArg(0);

diff  --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 4a7259b91a7f9..7884aa5b5b745 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -2365,7 +2365,7 @@ static void startLifetimeRecurse(PtrView Ptr) {
   Ptr.startLifetime();
 }
 
-bool StartThisLifetime(InterpState &S, CodePtr OpPC) {
+bool StartThisLifetime(InterpState &S) {
   if (S.checkingPotentialConstantExpression())
     return true;
 
@@ -2376,7 +2376,7 @@ bool StartThisLifetime(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-bool StartThisLifetime1(InterpState &S, CodePtr OpPC) {
+bool StartThisLifetime1(InterpState &S) {
   if (S.checkingPotentialConstantExpression())
     return true;
 
@@ -2695,8 +2695,7 @@ bool handleReference(InterpState &S, CodePtr OpPC, Block *B) {
   return true;
 }
 
-bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr,
-               const Type *TypeInfoType) {
+bool GetTypeid(InterpState &S, const Type *TypePtr, const Type *TypeInfoType) {
   S.Stk.push<Pointer>(TypePtr, TypeInfoType);
   return true;
 }
@@ -2891,7 +2890,7 @@ static void finishGlobalRecurse(InterpState &S, const Pointer &Ptr) {
   }
 }
 
-bool FinishInitGlobal(InterpState &S, CodePtr OpPC) {
+bool FinishInitGlobal(InterpState &S) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
 
   finishGlobalRecurse(S, Ptr);
@@ -3006,7 +3005,7 @@ static bool appendToMemberPointer(InterpState &S,
 }
 
 /// DerivedToBaseMemberPointer
-bool CastMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off,
+bool CastMemberPtrBasePop(InterpState &S, int32_t Off,
                           const RecordDecl *BaseDecl) {
   const auto &Ptr = S.Stk.pop<MemberPointer>();
 
@@ -3018,7 +3017,7 @@ bool CastMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off,
 }
 
 /// BaseToDerivedMemberPointer
-bool CastMemberPtrDerivedPop(InterpState &S, CodePtr OpPC, int32_t Off,
+bool CastMemberPtrDerivedPop(InterpState &S, int32_t Off,
                              const RecordDecl *BaseDecl) {
   const auto &Ptr = S.Stk.pop<MemberPointer>();
 
@@ -3031,12 +3030,12 @@ bool CastMemberPtrDerivedPop(InterpState &S, CodePtr OpPC, int32_t Off,
   return castBackMemberPointer(S, Ptr, Off, BaseDecl);
 }
 
-bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D) {
+bool GetMemberPtr(InterpState &S, const ValueDecl *D) {
   S.Stk.push<MemberPointer>(D);
   return true;
 }
 
-bool GetMemberPtrBase(InterpState &S, CodePtr OpPC) {
+bool GetMemberPtrBase(InterpState &S) {
   const auto &MP = S.Stk.pop<MemberPointer>();
 
   if (!MP.isBaseCastPossible())
@@ -3046,7 +3045,7 @@ bool GetMemberPtrBase(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC) {
+bool GetMemberPtrDecl(InterpState &S) {
   const auto &MP = S.Stk.pop<MemberPointer>();
 
   const ValueDecl *D = MP.getDecl();
@@ -3073,7 +3072,7 @@ bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC) {
 
 /// Just append the given Entry to the MemberPointer's path.
 /// This is used to re-inject APValues into the bytecode interpreter.
-bool CopyMemberPtrPath(InterpState &S, CodePtr OpPC, const RecordDecl *Entry,
+bool CopyMemberPtrPath(InterpState &S, const RecordDecl *Entry,
                        bool IsDerived) {
   const auto &MemberPtr = S.Stk.pop<MemberPointer>();
 
@@ -3175,10 +3174,10 @@ PRESERVE_NONE static bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset,
   assert(DepthBefore >= 1);
 #endif
 
-  auto SpeculativeInterp = [&S, OpPC]() -> bool {
+  auto SpeculativeInterp = [&S]() -> bool {
     // Ignore diagnostics during speculative execution.
-    PushIgnoreDiags(S, OpPC);
-    auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S, OpPC); });
+    PushIgnoreDiags(S);
+    auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S); });
 
 #if USE_TAILCALLS
     auto Op = S.PC.read<Opcode>();

diff  --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 61c2b0a5e5960..13e7798fcf365 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -243,10 +243,10 @@ bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR,
                     bool InitializerFailed);
 
 /// DerivedToBaseMemberPointer
-bool CastMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off,
+bool CastMemberPtrBasePop(InterpState &S, int32_t Off,
                           const RecordDecl *BaseDecl);
 /// BaseToDerivedMemberPointer
-bool CastMemberPtrDerivedPop(InterpState &S, CodePtr OpPC, int32_t Off,
+bool CastMemberPtrDerivedPop(InterpState &S, int32_t Off,
                              const RecordDecl *BaseDecl);
 enum class ArithOp { Add, Sub };
 
@@ -502,7 +502,7 @@ inline bool Mulf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool Mulc(InterpState &S, CodePtr OpPC) {
+inline bool Mulc(InterpState &S) {
   const Pointer &RHS = S.Stk.pop<Pointer>();
   const Pointer &LHS = S.Stk.pop<Pointer>();
   const Pointer &Result = S.Stk.peek<Pointer>();
@@ -668,7 +668,7 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {
 /// 2) Pops the LHS from the stack.
 /// 3) Pushes 'LHS & RHS' on the stack
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool BitAnd(InterpState &S, CodePtr OpPC) {
+bool BitAnd(InterpState &S) {
   const T &RHS = S.Stk.pop<T>();
   const T &LHS = S.Stk.pop<T>();
   unsigned Bits = RHS.bitWidth();
@@ -693,7 +693,7 @@ bool BitAnd(InterpState &S, CodePtr OpPC) {
 /// 2) Pops the LHS from the stack.
 /// 3) Pushes 'LHS | RHS' on the stack
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool BitOr(InterpState &S, CodePtr OpPC) {
+bool BitOr(InterpState &S) {
   const T &RHS = S.Stk.pop<T>();
   const T &LHS = S.Stk.pop<T>();
   unsigned Bits = RHS.bitWidth();
@@ -718,7 +718,7 @@ bool BitOr(InterpState &S, CodePtr OpPC) {
 /// 2) Pops the LHS from the stack.
 /// 3) Pushes 'LHS ^ RHS' on the stack
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool BitXor(InterpState &S, CodePtr OpPC) {
+bool BitXor(InterpState &S) {
   const T &RHS = S.Stk.pop<T>();
   const T &LHS = S.Stk.pop<T>();
   unsigned Bits = RHS.bitWidth();
@@ -812,7 +812,7 @@ inline bool Divf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
 // Inv
 //===----------------------------------------------------------------------===//
 
-inline bool Inv(InterpState &S, CodePtr OpPC) {
+inline bool Inv(InterpState &S) {
   const auto &Val = S.Stk.pop<Boolean>();
   S.Stk.push<Boolean>(!Val);
   return true;
@@ -1176,7 +1176,7 @@ inline bool DecfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
 /// 1) Pops the value from the stack.
 /// 2) Pushes the bitwise complemented value on the stack (~V).
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool Comp(InterpState &S, CodePtr OpPC) {
+bool Comp(InterpState &S) {
   const T &Val = S.Stk.pop<T>();
 
   T Result;
@@ -1537,20 +1537,19 @@ bool GE(InterpState &S, CodePtr OpPC) {
 //===----------------------------------------------------------------------===//
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool Dup(InterpState &S, CodePtr OpPC) {
+bool Dup(InterpState &S) {
   S.Stk.push<T>(S.Stk.peek<T>());
   return true;
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool Pop(InterpState &S, CodePtr OpPC) {
+bool Pop(InterpState &S) {
   S.Stk.discard<T>();
   return true;
 }
 
 /// [Value1, Value2] -> [Value2, Value1]
-template <PrimType TopName, PrimType BottomName>
-bool Flip(InterpState &S, CodePtr OpPC) {
+template <PrimType TopName, PrimType BottomName> bool Flip(InterpState &S) {
   using TopT = typename PrimConv<TopName>::T;
   using BottomT = typename PrimConv<BottomName>::T;
 
@@ -1568,7 +1567,7 @@ bool Flip(InterpState &S, CodePtr OpPC) {
 //===----------------------------------------------------------------------===//
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
+bool Const(InterpState &S, const T &Arg) {
   if constexpr (needsAlloc<T>()) {
     T Result = S.allocAP<T>(Arg.bitWidth());
     Result.copy(Arg.toAPSInt());
@@ -1596,7 +1595,7 @@ bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
   return true;
 }
 
-inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) {
+inline bool ConstFloat(InterpState &S, const Floating &F) {
   Floating Result = S.allocFloat(F.getSemantics());
   Result.copy(F.getAPFloat());
   S.Stk.push<Floating>(Result);
@@ -1618,21 +1617,21 @@ bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
 
 bool EndLifetime(InterpState &S, CodePtr OpPC);
 bool EndLifetimePop(InterpState &S, CodePtr OpPC);
-bool StartThisLifetime(InterpState &S, CodePtr OpPC);
-bool StartThisLifetime1(InterpState &S, CodePtr OpPC);
+bool StartThisLifetime(InterpState &S);
+bool StartThisLifetime1(InterpState &S);
 bool MarkDestroyed(InterpState &S, CodePtr OpPC);
 
 /// 1) Pops the value from the stack.
 /// 2) Writes the value to the local variable with the
 ///    given offset.
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
+bool SetLocal(InterpState &S, uint32_t I) {
   S.Current->setLocal<T>(I, S.Stk.pop<T>());
   return true;
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool GetParam(InterpState &S, CodePtr OpPC, uint32_t Index) {
+bool GetParam(InterpState &S, uint32_t Index) {
   if (S.checkingPotentialConstantExpression()) {
     return false;
   }
@@ -1641,7 +1640,7 @@ bool GetParam(InterpState &S, CodePtr OpPC, uint32_t Index) {
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
+bool SetParam(InterpState &S, uint32_t I) {
   S.Current->setParam<T>(I, S.Stk.pop<T>());
   return true;
 }
@@ -1767,7 +1766,7 @@ bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
+bool InitGlobal(InterpState &S, uint32_t I) {
   const Pointer &P = S.P.getGlobal(I);
 
   P.deref<T>() = S.Stk.pop<T>();
@@ -1803,7 +1802,7 @@ bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
 /// 2) Sets that APValue on \Temp
 /// 3) Initializes global with index \I with that
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I,
+bool InitGlobalTemp(InterpState &S, uint32_t I,
                     const LifetimeExtendedTemporaryDecl *Temp) {
   if (S.EvalMode == EvaluationMode::ConstantFold)
     return false;
@@ -1822,7 +1821,7 @@ bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I,
 /// 1) Converts the value on top of the stack to an APValue
 /// 2) Sets that APValue on \Temp
 /// 3) Initialized global with index \I with that
-inline bool InitGlobalTempComp(InterpState &S, CodePtr OpPC,
+inline bool InitGlobalTempComp(InterpState &S,
                                const LifetimeExtendedTemporaryDecl *Temp) {
   if (S.EvalMode == EvaluationMode::ConstantFold)
     return false;
@@ -2038,7 +2037,7 @@ bool InitBitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t FieldOffset,
 // GetPtr Local/Param/Global/Field/This
 //===----------------------------------------------------------------------===//
 
-inline bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
+inline bool GetPtrLocal(InterpState &S, uint32_t I) {
   S.Stk.push<Pointer>(S.Current->getLocalPointer(I));
   return true;
 }
@@ -2077,14 +2076,14 @@ inline bool CheckRefInit(InterpState &S, CodePtr OpPC) {
   return CheckRange(S, OpPC, Ptr, AK_Read);
 }
 
-inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t Index) {
+inline bool GetPtrParam(InterpState &S, uint32_t Index) {
   if (S.Current->isBottomFrame())
     return false;
   S.Stk.push<Pointer>(S.Current->getParamPointer(Index));
   return true;
 }
 
-inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
+inline bool GetPtrGlobal(InterpState &S, uint32_t I) {
   S.Stk.push<Pointer>(S.P.getPtrGlobal(I));
   return true;
 }
@@ -2120,21 +2119,21 @@ inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
   return true;
 }
 
-inline bool FinishInitPop(InterpState &S, CodePtr OpPC) {
+inline bool FinishInitPop(InterpState &S) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   if (Ptr.canBeInitialized())
     Ptr.initialize();
   return true;
 }
 
-inline bool FinishInit(InterpState &S, CodePtr OpPC) {
+inline bool FinishInit(InterpState &S) {
   const Pointer &Ptr = S.Stk.peek<Pointer>();
   if (Ptr.canBeInitialized())
     Ptr.initialize();
   return true;
 }
 
-inline bool FinishInitActivate(InterpState &S, CodePtr OpPC) {
+inline bool FinishInitActivate(InterpState &S) {
   const Pointer &Ptr = S.Stk.peek<Pointer>();
   if (Ptr.canBeInitialized()) {
     Ptr.initialize();
@@ -2143,7 +2142,7 @@ inline bool FinishInitActivate(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-inline bool FinishInitActivatePop(InterpState &S, CodePtr OpPC) {
+inline bool FinishInitActivatePop(InterpState &S) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   if (Ptr.canBeInitialized()) {
     Ptr.initialize();
@@ -2152,9 +2151,9 @@ inline bool FinishInitActivatePop(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-bool FinishInitGlobal(InterpState &S, CodePtr OpPC);
+bool FinishInitGlobal(InterpState &S);
 
-inline bool Dump(InterpState &S, CodePtr OpPC) {
+inline bool Dump(InterpState &S) {
   S.Stk.dump();
   return true;
 }
@@ -2169,7 +2168,7 @@ inline bool CheckNull(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
+inline bool VirtBaseHelper(InterpState &S, const RecordDecl *Decl,
                            const Pointer &Ptr) {
   if (!Ptr.isBlockPointer())
     return false;
@@ -2189,7 +2188,7 @@ inline bool GetPtrVirtBasePop(InterpState &S, CodePtr OpPC,
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
     return false;
-  return VirtBaseHelper(S, OpPC, D, Ptr);
+  return VirtBaseHelper(S, D, Ptr);
 }
 
 inline bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC,
@@ -2200,7 +2199,7 @@ inline bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC,
   if (!CheckThis(S, OpPC))
     return false;
   const Pointer &This = S.Current->getThis();
-  return VirtBaseHelper(S, OpPC, D, This);
+  return VirtBaseHelper(S, D, This);
 }
 
 //===----------------------------------------------------------------------===//
@@ -2261,14 +2260,14 @@ bool StorePop(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-static inline bool Activate(InterpState &S, CodePtr OpPC) {
+static inline bool Activate(InterpState &S) {
   const Pointer &Ptr = S.Stk.peek<Pointer>();
   if (Ptr.canBeInitialized())
     Ptr.activate();
   return true;
 }
 
-static inline bool ActivateThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
+static inline bool ActivateThisField(InterpState &S, uint32_t I) {
   if (S.checkingPotentialConstantExpression())
     return false;
   if (!S.Current->hasThisPointer())
@@ -2487,7 +2486,7 @@ inline bool Memcpy(InterpState &S, CodePtr OpPC) {
   return DoMemcpy(S, OpPC, Src, Dest);
 }
 
-inline bool ToMemberPtr(InterpState &S, CodePtr OpPC) {
+inline bool ToMemberPtr(InterpState &S) {
   const auto &Member = S.Stk.pop<MemberPointer>();
   const auto &Base = S.Stk.pop<Pointer>();
 
@@ -2769,18 +2768,18 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC, uint32_t ElemSize) {
   return true;
 }
 
-inline bool InitScope(InterpState &S, CodePtr OpPC, uint32_t I) {
+inline bool InitScope(InterpState &S, uint32_t I) {
   S.Current->initScope(I);
   return true;
 }
 
-inline bool EnableLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
+inline bool EnableLocal(InterpState &S, uint32_t I) {
   assert(!S.Current->isLocalEnabled(I));
   S.Current->enableLocal(I);
   return true;
 }
 
-inline bool GetLocalEnabled(InterpState &S, CodePtr OpPC, uint32_t I) {
+inline bool GetLocalEnabled(InterpState &S, uint32_t I) {
   assert(S.Current);
   S.Stk.push<bool>(S.Current->isLocalEnabled(I));
   return true;
@@ -2819,7 +2818,7 @@ template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) {
 
 /// 1) Pops a Floating from the stack.
 /// 2) Pushes a new floating on the stack that uses the given semantics.
-inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem,
+inline bool CastFP(InterpState &S, const llvm::fltSemantics *Sem,
                    llvm::RoundingMode RM) {
   Floating F = S.Stk.pop<Floating>();
   Floating Result = S.allocFloat(*Sem);
@@ -2846,7 +2845,7 @@ inline bool CastFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS) {
 /// Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need
 /// to know what bitwidth the result should be.
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
+bool CastAP(InterpState &S, uint32_t BitWidth) {
   T Source = S.Stk.pop<T>();
 
   if constexpr (isIntegralOrPointer<T>()) {
@@ -2865,7 +2864,7 @@ bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
+bool CastAPS(InterpState &S, uint32_t BitWidth) {
   T Source = S.Stk.pop<T>();
 
   if constexpr (isIntegralOrPointer<T>()) {
@@ -3068,7 +3067,7 @@ static inline bool CastFloatingFixedPoint(InterpState &S, CodePtr OpPC,
   return true;
 }
 
-static inline bool CastFixedPointFloating(InterpState &S, CodePtr OpPC,
+static inline bool CastFixedPointFloating(InterpState &S,
                                           const llvm::fltSemantics *Sem) {
   const auto &Fixed = S.Stk.pop<FixedPoint>();
   Floating Result = S.allocFloat(*Sem);
@@ -3139,12 +3138,12 @@ static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) {
 //===----------------------------------------------------------------------===//
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool Zero(InterpState &S, CodePtr OpPC) {
+bool Zero(InterpState &S) {
   S.Stk.push<T>(T::zero());
   return true;
 }
 
-static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
+static inline bool ZeroIntAP(InterpState &S, uint32_t BitWidth) {
   auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
   if (!Result.singleWord())
     std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t));
@@ -3152,7 +3151,7 @@ static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
   return true;
 }
 
-static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
+static inline bool ZeroIntAPS(InterpState &S, uint32_t BitWidth) {
   auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
   if (!Result.singleWord())
     std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t));
@@ -3161,7 +3160,7 @@ static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Type *Ty) {
+inline bool Null(InterpState &S, uint64_t Value, const Type *Ty) {
   // FIXME(perf): This is a somewhat often-used function and the value of a
   // null pointer is almost always 0.
   S.Stk.push<T>(Value, Ty);
@@ -3169,7 +3168,7 @@ inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Type *Ty) {
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool IsNonNull(InterpState &S, CodePtr OpPC) {
+inline bool IsNonNull(InterpState &S) {
   const auto &P = S.Stk.pop<T>();
   if (P.isWeak())
     return false;
@@ -3208,7 +3207,7 @@ inline bool This(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
+inline bool RVOPtr(InterpState &S) {
   assert(S.Current->getFunction()->hasRVO());
   if (S.checkingPotentialConstantExpression())
     return false;
@@ -3423,7 +3422,7 @@ static inline bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left) {
 //===----------------------------------------------------------------------===//
 // NoRet
 //===----------------------------------------------------------------------===//
-PRESERVE_NONE inline bool NoRet(InterpState &S, CodePtr OpPC) {
+PRESERVE_NONE inline bool NoRet(InterpState &S) {
   SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
   S.FFDiag(EndLoc, diag::note_constexpr_no_return);
   return false;
@@ -3433,13 +3432,13 @@ PRESERVE_NONE inline bool NoRet(InterpState &S, CodePtr OpPC) {
 // NarrowPtr, ExpandPtr
 //===----------------------------------------------------------------------===//
 
-inline bool NarrowPtr(InterpState &S, CodePtr OpPC) {
+inline bool NarrowPtr(InterpState &S) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   S.Stk.push<Pointer>(Ptr.narrow());
   return true;
 }
 
-inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
+inline bool ExpandPtr(InterpState &S) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
   if (Ptr.isBlockPointer())
     S.Stk.push<Pointer>(Ptr.expand());
@@ -3597,7 +3596,7 @@ inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
   return false;
 }
 
-inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) {
+inline bool GetFnPtr(InterpState &S, const Function *Func) {
   assert(Func);
   S.Stk.push<Pointer>(Func);
   return true;
@@ -3638,11 +3637,10 @@ inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Type *Ty) {
   return true;
 }
 
-bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D);
-bool GetMemberPtrBase(InterpState &S, CodePtr OpPC);
-bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC);
-bool CopyMemberPtrPath(InterpState &S, CodePtr OpPC, const RecordDecl *Entry,
-                       bool IsDerived);
+bool GetMemberPtr(InterpState &S, const ValueDecl *D);
+bool GetMemberPtrBase(InterpState &S);
+bool GetMemberPtrDecl(InterpState &S);
+bool CopyMemberPtrPath(InterpState &S, const RecordDecl *Entry, bool IsDerived);
 
 /// Just emit a diagnostic. The expression that caused emission of this
 /// op is not valid in a constant context.
@@ -3654,7 +3652,7 @@ inline bool Unsupported(InterpState &S, CodePtr OpPC) {
   return false;
 }
 
-inline bool PushIgnoreDiags(InterpState &S, CodePtr OpPC) {
+inline bool PushIgnoreDiags(InterpState &S) {
   ++S.DiagIgnoreDepth;
   if (S.DiagIgnoreDepth != 1)
     return true;
@@ -3666,7 +3664,7 @@ inline bool PushIgnoreDiags(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-inline bool PopIgnoreDiags(InterpState &S, CodePtr OpPC) {
+inline bool PopIgnoreDiags(InterpState &S) {
   assert(S.DiagIgnoreDepth != 0);
   --S.DiagIgnoreDepth;
   if (S.DiagIgnoreDepth == 0) {
@@ -3677,20 +3675,20 @@ inline bool PopIgnoreDiags(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-inline bool StartSpeculation(InterpState &S, CodePtr OpPC) {
+inline bool StartSpeculation(InterpState &S) {
 #ifndef NDEBUG
   ++S.SpeculationDepth;
 #endif
   return true;
 }
 
-inline bool StartInit(InterpState &S, CodePtr OpPC) {
+inline bool StartInit(InterpState &S) {
   const Pointer &Ptr = S.Stk.peek<Pointer>();
   S.InitializingPtrs.push_back(Ptr.view());
   return true;
 }
 
-inline bool EndInit(InterpState &S, CodePtr OpPC) {
+inline bool EndInit(InterpState &S) {
   S.InitializingPtrs.pop_back();
   return true;
 }
@@ -3706,22 +3704,22 @@ PRESERVE_NONE inline bool EndSpeculation(InterpState &S) {
   return true;
 }
 
-inline bool PushCC(InterpState &S, CodePtr OpPC, bool Value) {
+inline bool PushCC(InterpState &S, bool Value) {
   S.ConstantContextOverride = Value;
   return true;
 }
-inline bool PopCC(InterpState &S, CodePtr OpPC) {
+inline bool PopCC(InterpState &S) {
   S.ConstantContextOverride = std::nullopt;
   return true;
 }
 
-inline bool PushMSVCCE(InterpState &S, CodePtr OpPC) {
+inline bool PushMSVCCE(InterpState &S) {
   // This is a per-frame property.
   ++S.Current->MSVCConstexprAllowed;
   return true;
 }
 
-inline bool PopMSVCCE(InterpState &S, CodePtr OpPC) {
+inline bool PopMSVCCE(InterpState &S) {
   assert(S.Current->MSVCConstexprAllowed >= 1);
   // This is a per-frame property.
   --S.Current->MSVCConstexprAllowed;
@@ -3729,17 +3727,15 @@ inline bool PopMSVCCE(InterpState &S, CodePtr OpPC) {
 }
 
 /// Do nothing and just abort execution.
-inline bool Error(InterpState &S, CodePtr OpPC) { return false; }
+inline bool Error(InterpState &S) { return false; }
 
-inline bool SideEffect(InterpState &S, CodePtr OpPC) {
-  return S.noteSideEffect();
-}
+inline bool SideEffect(InterpState &S) { return S.noteSideEffect(); }
 
 /// Abort without a diagnostic if we're checking for a potential constant
 /// expression and this is not the bottom frame. This is used in constructors to
 /// allow evaluating their initializers but abort if we encounter anything in
 /// their body.
-inline bool CtorCheck(InterpState &S, CodePtr OpPC) {
+inline bool CtorCheck(InterpState &S) {
   if (S.checkingPotentialConstantExpression() && !S.Current->isBottomFrame())
     return false;
   return true;
@@ -3829,8 +3825,7 @@ inline bool CheckEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED) {
 }
 
 /// OldPtr -> Integer -> NewPtr.
-template <PrimType TIn, PrimType TOut>
-inline bool DecayPtr(InterpState &S, CodePtr OpPC) {
+template <PrimType TIn, PrimType TOut> inline bool DecayPtr(InterpState &S) {
   static_assert(isPtrType(TIn) && isPtrType(TOut));
   using FromT = typename PrimConv<TIn>::T;
   using ToT = typename PrimConv<TOut>::T;
@@ -3854,7 +3849,7 @@ inline bool DecayPtr(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-inline bool CheckDecl(InterpState &S, CodePtr OpPC, const VarDecl *VD) {
+inline bool CheckDecl(InterpState &S, const VarDecl *VD) {
   // An expression E is a core constant expression unless the evaluation of E
   // would evaluate one of the following: [C++23] - a control flow that passes
   // through a declaration of a variable with static or thread storage duration
@@ -3989,12 +3984,12 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc,
 bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
           bool IsGlobalDelete);
 
-static inline bool IsConstantContext(InterpState &S, CodePtr OpPC) {
+static inline bool IsConstantContext(InterpState &S) {
   S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
   return true;
 }
 
-static inline bool CheckAllocations(InterpState &S, CodePtr OpPC) {
+static inline bool CheckAllocations(InterpState &S) {
   return S.maybeDiagnoseDanglingAllocations();
 }
 
@@ -4102,8 +4097,7 @@ inline bool BitCast(InterpState &S, CodePtr OpPC) {
 }
 
 /// Typeid support.
-bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr,
-               const Type *TypeInfoType);
+bool GetTypeid(InterpState &S, const Type *TypePtr, const Type *TypeInfoType);
 bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType);
 bool DiagTypeid(InterpState &S, CodePtr OpPC);
 

diff  --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 8123ca7497335..577c8523ab6c3 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -145,10 +145,12 @@ class Opcode {
   bit HasCustomEval = 0;
   bit HasGroup = 0;
   bit CanFail = 1;
+  bit NeedsOpPC = 1;
 }
 
 class SuccessOpcode : Opcode {
   let CanFail = 0;
+  let NeedsOpPC = 0;
 }
 
 class AluOpcode : Opcode {
@@ -218,7 +220,9 @@ def RetValue : Opcode {
   let HasCustomEval = 1;
 }
 // [] -> EXIT
-def NoRet : Opcode {}
+def NoRet : Opcode {
+  let NeedsOpPC = 0;
+}
 
 
 def Call : Opcode {
@@ -254,16 +258,16 @@ def Destroy : Opcode {
   let Args = [ArgUint32];
   let HasCustomEval = 1;
 }
-def InitScope : Opcode {
+def InitScope : SuccessOpcode {
   let Args = [ArgUint32];
 }
 
-def GetLocalEnabled : Opcode {
+def GetLocalEnabled : SuccessOpcode {
   let Args = [ArgUint32];
   let HasCustomEval = 1;
 }
 
-def EnableLocal : Opcode {
+def EnableLocal : SuccessOpcode {
   let Args = [ArgUint32];
   let HasCustomEval = 1;
 }
@@ -272,11 +276,10 @@ def EnableLocal : Opcode {
 // Constants
 //===----------------------------------------------------------------------===//
 
-class ConstOpcode<Type Ty, ArgType ArgTy> : Opcode {
+class ConstOpcode<Type Ty, ArgType ArgTy> : SuccessOpcode {
   let Types = [SingletonTypeClass<Ty>];
   let Args = [ArgTy];
   let Name = "Const";
-  let CanFail = 0;
 }
 
 // [] -> [Integer]
@@ -293,35 +296,29 @@ def ConstIntAPS : ConstOpcode<IntAPS, ArgIntAPS>;
 def ConstBool : ConstOpcode<Bool, ArgBool>;
 def ConstFixedPoint : ConstOpcode<FixedPoint, ArgFixedPoint>;
 
-def ConstFloat : Opcode {
+def ConstFloat : SuccessOpcode {
   let Args = [ArgFloat];
-  let CanFail = 0;
 }
 
 // [] -> [Integer]
-def Zero : Opcode {
+def Zero : SuccessOpcode {
   let Types = [FixedSizeIntegralTypeClass];
   let HasGroup = 1;
-  let CanFail = 0;
-
 }
 
-def ZeroIntAP : Opcode {
+def ZeroIntAP : SuccessOpcode {
   let Args = [ArgUint32];
-  let CanFail = 0;
 }
 
-def ZeroIntAPS : Opcode {
+def ZeroIntAPS : SuccessOpcode {
   let Args = [ArgUint32];
-  let CanFail = 0;
 }
 
 // [] -> [Pointer]
-def Null : Opcode {
+def Null : SuccessOpcode {
   let Types = [PtrTypeClass];
   let Args = [ArgUint64, ArgTypePtr];
   let HasGroup = 1;
-  let CanFail = 0;
 }
 
 //===----------------------------------------------------------------------===//
@@ -334,6 +331,7 @@ class OffsetOpcode : Opcode {
 // [] -> [Pointer]
 def GetPtrLocal : OffsetOpcode {
   bit HasCustomEval = 1;
+  let NeedsOpPC = 0;
 }
 def GetRefLocal : OffsetOpcode {
   bit HasCustomEval = 1;
@@ -343,9 +341,13 @@ def GetRefGlobal : OffsetOpcode;
 def CheckRefInit : Opcode {}
 
 // [] -> [Pointer]
-def GetPtrParam : OffsetOpcode;
+def GetPtrParam : OffsetOpcode {
+  let NeedsOpPC = 0;
+}
 // [] -> [Pointer]
-def GetPtrGlobal : OffsetOpcode;
+def GetPtrGlobal : OffsetOpcode {
+  let NeedsOpPC = 0;
+}
 // [Pointer] -> [Pointer]
 def GetPtrField : OffsetOpcode;
 def GetPtrFieldPop : OffsetOpcode;
@@ -358,10 +360,12 @@ def GetPtrBasePop : OffsetOpcode { let Args = [ArgUint32, ArgBool]; }
 def CastMemberPtrBasePop : Opcode {
   // Offset of field, which is a base.
   let Args = [ArgSint32, ArgRecordDecl];
+  let NeedsOpPC = 0;
 }
 def CastMemberPtrDerivedPop : Opcode {
   // Offset of field, which is a base.
   let Args = [ArgSint32, ArgRecordDecl];
+  let NeedsOpPC = 0;
 }
 
 def FinishInitPop : SuccessOpcode;
@@ -391,7 +395,9 @@ def GetPtrThisVirtBase : Opcode {
 def This : Opcode;
 
 // [] -> [Pointer]
-def RVOPtr : Opcode;
+def RVOPtr : Opcode {
+  let NeedsOpPC = 0;
+}
 
 // [Pointer] -> [Pointer]
 def NarrowPtr : SuccessOpcode;
@@ -445,16 +451,25 @@ class BitFieldOpcode : Opcode {
 // [] -> [Pointer]
 def GetLocal : AccessOpcode { let HasCustomEval = 1; }
 // [] -> [Pointer]
-def SetLocal : AccessOpcode { let HasCustomEval = 1; }
+def SetLocal : AccessOpcode {
+  let HasCustomEval = 1;
+  let CanFail = 0;
+  let NeedsOpPC = 0;
+}
 
 def EndLifetimePop : Opcode;
 def EndLifetime : Opcode;
 def MarkDestroyed : Opcode;
-def StartThisLifetime : Opcode;
-def StartThisLifetime1 : Opcode;
+def StartThisLifetime : Opcode {
+  let NeedsOpPC = 0;
+}
+def StartThisLifetime1 : Opcode {
+  let NeedsOpPC = 0;
+}
 
 def CheckDecl : Opcode {
   let Args = [ArgVarDecl];
+  let NeedsOpPC = 0;
 }
 
 def CheckEnumValue : Opcode {
@@ -477,22 +492,32 @@ def CheckBitCast : Opcode { let Args = [ArgTypePtr, ArgBool]; }
 def GetGlobal : AccessOpcode;
 def GetGlobalUnchecked : AccessOpcode;
 // [Value] -> []
-def InitGlobal : AccessOpcode;
+def InitGlobal : AccessOpcode {
+  let CanFail = 0;
+  let NeedsOpPC = 0;
+}
 // [Value] -> []
 def InitGlobalTemp : AccessOpcode {
   let Args = [ArgUint32, ArgLETD];
+  let NeedsOpPC = 0;
 }
 // [Pointer] -> [Pointer]
 def InitGlobalTempComp : Opcode {
   let Args = [ArgLETD];
+  let NeedsOpPC = 0;
 }
 // [Value] -> []
 def SetGlobal : AccessOpcode;
 
 // [] -> [Value]
-def GetParam : AccessOpcode;
+def GetParam : AccessOpcode {
+  let NeedsOpPC = 0;
+}
 // [Value] -> []
-def SetParam : AccessOpcode;
+def SetParam : AccessOpcode {
+  let NeedsOpPC = 0;
+  let CanFail = 0;
+}
 
 // [Pointer] -> [Pointer, Value]
 def GetField : AccessOpcode;
@@ -551,8 +576,13 @@ def StoreBitFieldPop : StoreBitFieldOpcode {}
 def StoreBitFieldActivate : StoreBitFieldOpcode {}
 def StoreBitFieldActivatePop : StoreBitFieldOpcode {}
 
-def Activate : SuccessOpcode;
-def ActivateThisField : Opcode { let Args = [ArgUint32]; }
+def Activate : SuccessOpcode {
+  let NeedsOpPC = 0;
+}
+def ActivateThisField : Opcode {
+  let Args = [ArgUint32];
+  let NeedsOpPC = 0;
+}
 
 // [Pointer, Value] -> []
 def Init : StoreOpcode {}
@@ -600,9 +630,8 @@ def DecPtr : Opcode;
 //===----------------------------------------------------------------------===//
 // Function pointers.
 //===----------------------------------------------------------------------===//
-def GetFnPtr : Opcode {
+def GetFnPtr : SuccessOpcode {
   let Args = [ArgFunction];
-  let CanFail = 0;
 }
 
 def GetIntPtr : Opcode {
@@ -625,6 +654,7 @@ def Mulf : FloatOpcode;
 def Mulc : Opcode {
   let Types = [NumberTypeClass];
   let HasGroup = 1;
+  let NeedsOpPC = 0;
 }
 def Rem  : IntegerOpcode;
 def Div  : IntegerOpcode;
@@ -634,9 +664,15 @@ def Divc : Opcode {
   let HasGroup = 1;
 }
 
-def BitAnd : IntegerOpcode;
-def BitOr : IntegerOpcode;
-def BitXor : IntegerOpcode;
+def BitAnd : IntegerOpcode {
+  let NeedsOpPC = 0;
+}
+def BitOr : IntegerOpcode {
+  let NeedsOpPC = 0;
+}
+def BitXor : IntegerOpcode {
+  let NeedsOpPC = 0;
+}
 
 def Shl : Opcode {
   let Types = [IntegerTypeClass, IntegerTypeClass];
@@ -653,7 +689,7 @@ def Shr : Opcode {
 //===----------------------------------------------------------------------===//
 
 // [Bool] -> [Bool]
-def Inv: Opcode;
+def Inv: SuccessOpcode;
 
 // Increment and decrement.
 class OverflowOpcode : Opcode {
@@ -698,11 +734,13 @@ def Neg: Opcode {
 def Comp: Opcode {
   let Types = [IntegerTypeClass];
   let HasGroup = 1;
+  let NeedsOpPC = 0;
 }
 
 def IsNonNull : Opcode {
   let Types = [PtrTypeClass];
   let HasGroup = 1;
+  let NeedsOpPC = 0;
 }
 
 //===----------------------------------------------------------------------===//
@@ -724,6 +762,7 @@ def Cast: Opcode {
 
 def CastFP : Opcode {
   let Args = [ArgFltSemantics, ArgRoundingMode];
+  let NeedsOpPC = 0;
 }
 
 def CastFixedPoint : Opcode {
@@ -734,12 +773,14 @@ def CastAP : Opcode {
   let Types = [AluTypeClass];
   let Args = [ArgUint32];
   let HasGroup = 1;
+  let NeedsOpPC = 0;
 }
 
 def CastAPS : Opcode {
   let Types = [AluTypeClass];
   let Args = [ArgUint32];
   let HasGroup = 1;
+  let NeedsOpPC = 0;
 }
 
 def APOnlyTypeClass : TypeClass {
@@ -794,6 +835,7 @@ def CastFloatingFixedPoint : Opcode {
 }
 def CastFixedPointFloating : Opcode {
   let Args = [ArgFltSemantics];
+  let NeedsOpPC = 0;
 }
 def CastFixedPointIntegral : Opcode {
   let Types = [FixedSizeIntegralNoBoolTypeClass];
@@ -813,6 +855,7 @@ def FnPtrCast : Opcode;
 def DecayPtr : Opcode {
   let Types = [PtrTypeClass, PtrTypeClass];
   let HasGroup = 1;
+  let NeedsOpPC = 0;
 }
 
 //===----------------------------------------------------------------------===//
@@ -846,30 +889,31 @@ def GE : ComparisonOpcode;
 //===----------------------------------------------------------------------===//
 
 // [Value] -> []
-def Pop : Opcode {
+def Pop : SuccessOpcode {
   let Types = [AllTypeClass];
   let HasGroup = 1;
-  let CanFail = 0;
 }
 
 // [Value] -> [Value, Value]
-def Dup : Opcode {
+def Dup : SuccessOpcode {
   let Types = [AllTypeClass];
   let HasGroup = 1;
-  let CanFail = 0;
 }
 
-def Flip : Opcode {
+def Flip : SuccessOpcode {
   let Types = [AllTypeClass, AllTypeClass];
   let HasGroup = 1;
-  let CanFail = 0;
 }
 
 // [] -> []
 def Invalid : Opcode {}
 def Unsupported : Opcode {}
-def Error : Opcode {}
-def SideEffect : Opcode {}
+def Error : Opcode {
+  let NeedsOpPC = 0;
+}
+def SideEffect : Opcode {
+  let NeedsOpPC = 0;
+}
 def InvalidCast : Opcode {
   let Args = [ArgCastKind, ArgBool];
 }
@@ -878,7 +922,9 @@ def DynamicCast : Opcode {
 }
 
 def InvalidStore : Opcode { let Args = [ArgTypePtr]; }
-def CheckPseudoDtor : SuccessOpcode;
+def CheckPseudoDtor : SuccessOpcode {
+  let NeedsOpPC = 1;
+}
 
 def InvalidDeclRef : Opcode {
   let Args = [ArgDeclRef, ArgBool];
@@ -900,22 +946,28 @@ def CheckNonNullArg : Opcode {
 
 def Memcpy : Opcode;
 
-def ToMemberPtr : Opcode;
+def ToMemberPtr : SuccessOpcode;
 def CastMemberPtrPtr : Opcode;
-def GetMemberPtr : Opcode {
+def GetMemberPtr : SuccessOpcode {
   let Args = [ArgValueDecl];
-  let CanFail = 0;
 }
-def GetMemberPtrBase : Opcode;
-def GetMemberPtrDecl : Opcode;
-def CopyMemberPtrPath : Opcode {
+def GetMemberPtrBase : Opcode {
+  let NeedsOpPC = 0;
+}
+def GetMemberPtrDecl : Opcode{
+  let NeedsOpPC = 0;
+}
+def CopyMemberPtrPath : SuccessOpcode {
   let Args = [ArgRecordDecl, ArgBool];
+
 }
 
 //===----------------------------------------------------------------------===//
 // Debugging.
 //===----------------------------------------------------------------------===//
-def Dump : Opcode;
+def Dump : Opcode {
+  let NeedsOpPC = 0;
+}
 
 def Alloc : Opcode {
   let Args = [ArgDesc];
@@ -945,8 +997,10 @@ def CheckNewTypeMismatchArray : Opcode {
 }
 def InvalidNewDeleteExpr : Opcode { let Args = [ArgExpr]; }
 
-def IsConstantContext: Opcode;
-def CheckAllocations : Opcode;
+def IsConstantContext: SuccessOpcode;
+def CheckAllocations : Opcode {
+  let NeedsOpPC = 0;
+}
 def CheckNull : Opcode;
 
 def BitCastTypeClass : TypeClass {
@@ -962,17 +1016,20 @@ def BitCastPrim : Opcode {
 
 def BitCast : Opcode;
 
-def GetTypeid : Opcode { let Args = [ArgTypePtr, ArgTypePtr]; }
+def GetTypeid : SuccessOpcode {
+  let Args = [ArgTypePtr, ArgTypePtr];
+}
 def GetTypeidPtr : Opcode { let Args = [ArgTypePtr]; }
 def DiagTypeid : Opcode;
 
 def CheckDestruction : Opcode;
 
-def CtorCheck : Opcode;
+def CtorCheck : Opcode {
+  let NeedsOpPC = 0;
+}
 
-def PushCC : Opcode {
+def PushCC : SuccessOpcode {
   let Args = [ArgBool];
-  let CanFail = 0;
 }
 def PopCC : SuccessOpcode;
 def PushMSVCCE : SuccessOpcode;

diff  --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index 13a99900bc9ec..4a3c901d2de7f 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -126,6 +126,7 @@ void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
     bool CanReturn = R->getValueAsBit("CanReturn");
     const auto &Args = R->getValueAsListOfDefs("Args");
     bool CanFail = R->getValueAsBit("CanFail");
+    bool PassOpPC = R->getValueAsBit("NeedsOpPC");
 
     if (Args.empty()) {
       if (CanReturn) {
@@ -142,7 +143,11 @@ void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
 
       OS << N;
       PrintTypes(OS, TS);
-      OS << "(S, S.PC)";
+      OS << "(S";
+      if (PassOpPC)
+        OS << ", S.PC)";
+      else
+        OS << ")";
 
       if (CanFail)
         OS << ") return false";
@@ -160,7 +165,8 @@ void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
 
     OS << "  {\n";
 
-    OS << "    CodePtr OpPC = S.PC;\n";
+    if (PassOpPC)
+      OS << "    CodePtr OpPC = S.PC;\n";
 
     // Emit calls to read arguments.
     for (size_t I = 0, N = Args.size(); I < N; ++I) {
@@ -182,7 +188,8 @@ void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
     OS << N;
     PrintTypes(OS, TS);
     OS << "(S";
-    OS << ", OpPC";
+    if (PassOpPC)
+      OS << ", OpPC";
     for (size_t I = 0, N = Args.size(); I < N; ++I)
       OS << ", V" << I;
 
@@ -431,10 +438,13 @@ void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N,
               if (N == "EndSpeculation") {
                 OS << "return EndSpeculation(S);\n";
               } else {
+                bool PassOpPC = R->getValueAsBit("NeedsOpPC");
 
                 OS << "  return " << N;
                 PrintTypes(OS, TS);
-                OS << "(S, OpPC";
+                OS << "(S";
+                if (PassOpPC)
+                  OS << ", OpPC";
                 for (size_t I = 0, N = Args.size(); I < N; ++I)
                   OS << ", A" << I;
                 OS << ");\n";


        


More information about the cfe-commits mailing list