Timm =?utf-8?q?Bäder?= <[email protected]>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/[email protected]>


https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/207479

>From ce81375b8b793624e39a629aef52c51dd7e05bcc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 3 Jul 2026 16:10:39 +0200
Subject: [PATCH 1/2] PassOpPC

---
 clang/lib/AST/ByteCode/EvalEmitter.cpp       |  4 +-
 clang/lib/AST/ByteCode/Interp.cpp            |  8 +--
 clang/lib/AST/ByteCode/Interp.h              | 55 ++++++++++----------
 clang/lib/AST/ByteCode/Opcodes.td            | 46 ++++++++--------
 clang/utils/TableGen/ClangOpcodesEmitter.cpp | 18 +++++--
 5 files changed, 69 insertions(+), 62 deletions(-)

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 dc93cc4fd698c..6d9b8bc78668f 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -2891,7 +2891,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);
@@ -3175,10 +3175,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..26cada1685186 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -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);
@@ -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,7 +2151,7 @@ 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) {
   S.Stk.dump();
@@ -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())
@@ -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);
@@ -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());
@@ -3654,7 +3653,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 +3665,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 +3676,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 +3705,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;
diff --git a/clang/lib/AST/ByteCode/Opcodes.td 
b/clang/lib/AST/ByteCode/Opcodes.td
index 8123ca7497335..cf99c1f056527 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 {
@@ -272,11 +274,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 +294,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;
 }
 
 
//===----------------------------------------------------------------------===//
@@ -551,8 +546,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 {}
@@ -846,23 +846,20 @@ 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;
 }
 
 // [] -> []
@@ -878,7 +875,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];
@@ -970,9 +969,8 @@ def CheckDestruction : Opcode;
 
 def CtorCheck : Opcode;
 
-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";

>From 27f46239114c0b336aa0dfd93952ff15020d3f10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Sat, 4 Jul 2026 06:21:42 +0200
Subject: [PATCH 2/2] More opcodes

---
 clang/lib/AST/ByteCode/Interp.cpp |  19 +++--
 clang/lib/AST/ByteCode/Interp.h   |  99 ++++++++++++------------
 clang/lib/AST/ByteCode/Opcodes.td | 123 ++++++++++++++++++++++--------
 3 files changed, 147 insertions(+), 94 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 6d9b8bc78668f..22052dc12d0aa 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;
 }
@@ -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>();
 
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 26cada1685186..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;
@@ -1617,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;
   }
@@ -1640,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;
 }
@@ -1766,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>();
@@ -1802,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;
@@ -1821,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;
@@ -2037,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;
 }
@@ -2076,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;
 }
@@ -2153,7 +2153,7 @@ inline bool FinishInitActivatePop(InterpState &S) {
 
 bool FinishInitGlobal(InterpState &S);
 
-inline bool Dump(InterpState &S, CodePtr OpPC) {
+inline bool Dump(InterpState &S) {
   S.Stk.dump();
   return true;
 }
@@ -2168,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;
@@ -2188,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,
@@ -2199,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);
 }
 
 
//===----------------------------------------------------------------------===//
@@ -2486,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>();
 
@@ -2768,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;
@@ -2818,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);
@@ -2845,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>()) {
@@ -2864,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>()) {
@@ -3067,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);
@@ -3168,7 +3168,7 @@ inline bool Null(InterpState &S, 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;
@@ -3207,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;
@@ -3422,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;
@@ -3596,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;
@@ -3637,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.
@@ -3728,17 +3727,15 @@ inline bool PopMSVCCE(InterpState &S) {
 }
 
 /// 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;
@@ -3828,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;
@@ -3853,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
@@ -3988,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();
 }
 
@@ -4101,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 cf99c1f056527..577c8523ab6c3 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -220,7 +220,9 @@ def RetValue : Opcode {
   let HasCustomEval = 1;
 }
 // [] -> EXIT
-def NoRet : Opcode {}
+def NoRet : Opcode {
+  let NeedsOpPC = 0;
+}
 
 
 def Call : Opcode {
@@ -256,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;
 }
@@ -329,6 +331,7 @@ class OffsetOpcode : Opcode {
 // [] -> [Pointer]
 def GetPtrLocal : OffsetOpcode {
   bit HasCustomEval = 1;
+  let NeedsOpPC = 0;
 }
 def GetRefLocal : OffsetOpcode {
   bit HasCustomEval = 1;
@@ -338,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;
@@ -353,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;
@@ -386,7 +395,9 @@ def GetPtrThisVirtBase : Opcode {
 def This : Opcode;
 
 // [] -> [Pointer]
-def RVOPtr : Opcode;
+def RVOPtr : Opcode {
+  let NeedsOpPC = 0;
+}
 
 // [Pointer] -> [Pointer]
 def NarrowPtr : SuccessOpcode;
@@ -440,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 {
@@ -472,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;
@@ -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;
 }
 
 
//===----------------------------------------------------------------------===//
@@ -865,8 +908,12 @@ def Flip : SuccessOpcode {
 // [] -> []
 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];
 }
@@ -899,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];
@@ -944,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 {
@@ -961,13 +1016,17 @@ 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 : SuccessOpcode {
   let Args = [ArgBool];

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

Reply via email to