[clang] [clang][bytecode] Move the program counter into `InterpState` (PR #207393)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 3 06:55:00 PDT 2026
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?= <tbaeder at redhat.com>
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";
});
More information about the cfe-commits
mailing list