llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

Reverts llvm/llvm-project#<!-- -->173756

Looks like that wasn't enough and we need to disable tail calls on Windows 
generally.

---

Patch is 22.90 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/188032.diff


9 Files Affected:

- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+3-3) 
- (modified) clang/lib/AST/ByteCode/EvalEmitter.cpp (-5) 
- (modified) clang/lib/AST/ByteCode/Interp.cpp (+88-155) 
- (modified) clang/lib/AST/ByteCode/Interp.h (+12-38) 
- (modified) clang/lib/AST/ByteCode/InterpState.h (-3) 
- (modified) clang/lib/AST/ByteCode/Opcodes.td (-3) 
- (modified) clang/test/SemaCXX/cxx2b-deducing-this.cpp (-1) 
- (modified) clang/test/SemaTemplate/stack-exhaustion.cpp (-4) 
- (modified) clang/utils/TableGen/ClangOpcodesEmitter.cpp (+48-87) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index c38eb0fa93877..642a59cf75642 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2819,7 +2819,7 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
   LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
 
   if (IsBcpCall) {
-    if (!this->emitPushIgnoreDiags(E))
+    if (!this->emitStartSpeculation(E))
       return false;
   }
 
@@ -2851,7 +2851,7 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
   this->emitLabel(LabelEnd);
 
   if (IsBcpCall)
-    return this->emitPopIgnoreDiags(E);
+    return this->emitEndSpeculation(E);
   return true;
 }
 
@@ -5417,9 +5417,9 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const 
CallExpr *E,
     LabelTy EndLabel = this->getLabel();
     if (!this->speculate(E, EndLabel))
       return false;
+    this->fallthrough(EndLabel);
     if (!this->emitEndSpeculation(E))
       return false;
-    this->fallthrough(EndLabel);
     if (DiscardResult)
       return this->emitPop(classifyPrim(E), E);
     return true;
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp 
b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index 8e8ffc131814b..3cfc1de1ff35e 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -11,7 +11,6 @@
 #include "IntegralAP.h"
 #include "Interp.h"
 #include "clang/AST/DeclCXX.h"
-#include "llvm/ADT/ScopeExit.h"
 
 using namespace clang;
 using namespace clang::interp;
@@ -162,10 +161,6 @@ bool EvalEmitter::fallthrough(const LabelTy &Label) {
 bool EvalEmitter::speculate(const CallExpr *E, const LabelTy &EndLabel) {
   if (!isActive())
     return true;
-
-  PushIgnoreDiags(S, OpPC);
-  auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S, OpPC); });
-
   size_t StackSizeBefore = S.Stk.size();
   const Expr *Arg = E->getArg(0);
   if (!this->visit(Arg)) {
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 6e7a60d5e4332..1b6b785b58757 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -28,23 +28,7 @@
 using namespace clang;
 using namespace clang::interp;
 
-#if __has_cpp_attribute(clang::musttail)
-#define MUSTTAIL [[clang::musttail]]
-#elif __has_cpp_attribute(msvc::musttail)
-#define MUSTTAIL [[msvc::musttail]]
-#elif __has_attribute(musttail)
-#define MUSTTAIL __attribute__((musttail))
-#endif
-
-// On MSVC, musttail does not guarantee tail calls in debug mode.
-#if (defined(_MSC_VER) && defined(_DEBUG)) || !defined(MUSTTAIL)
-#define MUSTTAIL
-#define USE_TAILCALLS 0
-#else
-#define USE_TAILCALLS 1
-#endif
-
-PRESERVE_NONE static bool RetValue(InterpState &S, CodePtr &Ptr) {
+static bool RetValue(InterpState &S, CodePtr &Pt) {
   llvm::report_fatal_error("Interpreter cannot return values");
 }
 
@@ -71,6 +55,76 @@ static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
   return S.noteStep(PC);
 }
 
+// https://github.com/llvm/llvm-project/issues/102513
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
+#pragma optimize("", off)
+#endif
+// FIXME: We have the large switch over all opcodes here again, and in
+// Interpret().
+static bool BCP(InterpState &S, CodePtr &RealPC, int32_t Offset, PrimType PT) {
+  [[maybe_unused]] CodePtr PCBefore = RealPC;
+  size_t StackSizeBefore = S.Stk.size();
+
+  auto SpeculativeInterp = [&S, RealPC]() -> bool {
+    const InterpFrame *StartFrame = S.Current;
+    CodePtr PC = RealPC;
+
+    for (;;) {
+      auto Op = PC.read<Opcode>();
+      if (Op == OP_EndSpeculation)
+        return true;
+      CodePtr OpPC = PC;
+
+      switch (Op) {
+#define GET_INTERP
+#include "Opcodes.inc"
+#undef GET_INTERP
+      }
+    }
+    llvm_unreachable("We didn't see an EndSpeculation op?");
+  };
+
+  if (SpeculativeInterp()) {
+    if (PT == PT_Ptr) {
+      const auto &Ptr = S.Stk.pop<Pointer>();
+      assert(S.Stk.size() == StackSizeBefore);
+      S.Stk.push<Integral<32, true>>(
+          Integral<32, true>::from(CheckBCPResult(S, Ptr)));
+    } else {
+      // Pop the result from the stack and return success.
+      TYPE_SWITCH(PT, S.Stk.pop<T>(););
+      assert(S.Stk.size() == StackSizeBefore);
+      S.Stk.push<Integral<32, true>>(Integral<32, true>::from(1));
+    }
+  } else {
+    if (!S.inConstantContext())
+      return Invalid(S, RealPC);
+
+    S.Stk.clearTo(StackSizeBefore);
+    S.Stk.push<Integral<32, true>>(Integral<32, true>::from(0));
+  }
+
+  // RealPC should not have been modified.
+  assert(*RealPC == *PCBefore);
+
+  // Jump to end label. This is a little tricker than just RealPC += Offset
+  // because our usual jump instructions don't have any arguments, to the 
offset
+  // we get is a little too much and we need to subtract the size of the
+  // bool and PrimType arguments again.
+  int32_t ParamSize = align(sizeof(PrimType));
+  assert(Offset >= ParamSize);
+  RealPC += Offset - ParamSize;
+
+  [[maybe_unused]] CodePtr PCCopy = RealPC;
+  assert(PCCopy.read<Opcode>() == OP_EndSpeculation);
+
+  return true;
+}
+// https://github.com/llvm/llvm-project/issues/102513
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
+#pragma optimize("", on)
+#endif
+
 static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC,
                                        const ValueDecl *VD) {
   const SourceInfo &E = S.Current->getSource(OpPC);
@@ -204,9 +258,6 @@ 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,
-                              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>());
@@ -2531,156 +2582,38 @@ bool CastMemberPtrDerivedPop(InterpState &S, CodePtr 
OpPC, int32_t Off,
   return castBackMemberPointer(S, Ptr, Off, BaseDecl);
 }
 
-// FIXME: Would be nice to generate this instead of hardcoding it here.
-constexpr bool OpReturns(Opcode Op) {
-  return Op == OP_RetVoid || Op == OP_RetValue || Op == OP_NoRet ||
-         Op == OP_RetSint8 || Op == OP_RetUint8 || Op == OP_RetSint16 ||
-         Op == OP_RetUint16 || Op == OP_RetSint32 || Op == OP_RetUint32 ||
-         Op == OP_RetSint64 || Op == OP_RetUint64 || Op == OP_RetIntAP ||
-         Op == OP_RetIntAPS || Op == OP_RetBool || Op == OP_RetFixedPoint ||
-         Op == OP_RetPtr || Op == OP_RetMemberPtr || Op == OP_RetFloat ||
-         Op == OP_EndSpeculation;
-}
-
-#if USE_TAILCALLS
-PRESERVE_NONE static bool InterpNext(InterpState &S, CodePtr &PC);
+// https://github.com/llvm/llvm-project/issues/102513
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
+#pragma optimize("", off)
 #endif
-
-// The dispatcher functions read the opcode arguments from the
-// bytecode and call the implementation function.
-#define GET_INTERPFN_DISPATCHERS
-#include "Opcodes.inc"
-#undef GET_INTERPFN_DISPATCHERS
-
-using InterpFn = bool (*)(InterpState &, CodePtr &PC) PRESERVE_NONE;
-// Array of the dispatcher functions defined above.
-const InterpFn InterpFunctions[] = {
-#define GET_INTERPFN_LIST
-#include "Opcodes.inc"
-#undef GET_INTERPFN_LIST
-};
-
-#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>();
-  auto Fn = InterpFunctions[Op];
-  MUSTTAIL return Fn(S, PC);
-}
-#endif
-
 bool Interpret(InterpState &S) {
   // The current stack frame when we started Interpret().
   // This is being used by the ops to determine wheter
   // to return from this function and thus terminate
   // interpretation.
+  const InterpFrame *StartFrame = S.Current;
   assert(!S.Current->isRoot());
   CodePtr PC = S.Current->getPC();
 
-#if USE_TAILCALLS
-  return InterpNext(S, PC);
-#else
-  while (true) {
-    auto Op = PC.read<Opcode>();
-    auto Fn = InterpFunctions[Op];
-
-    if (!Fn(S, PC))
-      return false;
-    if (OpReturns(Op))
-      break;
-  }
-  return true;
-#endif
-}
-
-/// This is used to implement speculative execution via __builtin_constant_p
-/// when we generate bytecode.
-///
-/// The setup here is that we use the same tailcall mechanism for speculative
-/// evaluation that we use for the regular one.
-/// Since each speculative execution ends with an EndSpeculation opcode,
-/// that one does NOT call InterpNext() but simply returns true.
-/// 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,
-                              PrimType PT) {
-  [[maybe_unused]] CodePtr PCBefore = RealPC;
-  size_t StackSizeBefore = S.Stk.size();
-
-  // Speculation depth must be at least 1 here, since we must have
-  // passed a StartSpeculation op before.
-#ifndef NDEBUG
-  [[maybe_unused]] unsigned DepthBefore = S.SpeculationDepth;
-  assert(DepthBefore >= 1);
-#endif
-
-  CodePtr PC = RealPC;
-  auto SpeculativeInterp = [&S, &PC]() -> bool {
-    // Ignore diagnostics during speculative execution.
-    PushIgnoreDiags(S, PC);
-    auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S, PC); });
+  // Empty program.
+  if (!PC)
+    return true;
 
-#if USE_TAILCALLS
+  for (;;) {
     auto Op = PC.read<Opcode>();
-    auto Fn = InterpFunctions[Op];
-    return Fn(S, PC);
-#else
-    while (true) {
-      auto Op = PC.read<Opcode>();
-      auto Fn = InterpFunctions[Op];
+    CodePtr OpPC = PC;
 
-      if (!Fn(S, PC))
-        return false;
-      if (OpReturns(Op))
-        break;
-    }
-    return true;
-#endif
-  };
-
-  if (SpeculativeInterp()) {
-    // Speculation must've ended naturally via a EndSpeculation opcode.
-    assert(S.SpeculationDepth == DepthBefore - 1);
-    if (PT == PT_Ptr) {
-      const auto &Ptr = S.Stk.pop<Pointer>();
-      assert(S.Stk.size() == StackSizeBefore);
-      S.Stk.push<Integral<32, true>>(
-          Integral<32, true>::from(CheckBCPResult(S, Ptr)));
-    } else {
-      // Pop the result from the stack and return success.
-      TYPE_SWITCH(PT, S.Stk.discard<T>(););
-      assert(S.Stk.size() == StackSizeBefore);
-      S.Stk.push<Integral<32, true>>(Integral<32, true>::from(1));
+    switch (Op) {
+#define GET_INTERP
+#include "Opcodes.inc"
+#undef GET_INTERP
     }
-  } else {
-    // End the speculation manually since we didn't call EndSpeculation
-    // naturally.
-    EndSpeculation(S, RealPC);
-
-    if (!S.inConstantContext())
-      return Invalid(S, RealPC);
-
-    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);
-
-  // Jump to end label. This is a little tricker than just RealPC += Offset
-  // because our usual jump instructions don't have any arguments, to the 
offset
-  // we get is a little too much and we need to subtract the size of the
-  // bool and PrimType arguments again.
-  int32_t ParamSize = align(sizeof(PrimType));
-  assert(Offset >= ParamSize);
-  RealPC += Offset - ParamSize;
-
-  return true;
 }
+// https://github.com/llvm/llvm-project/issues/102513
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
+#pragma optimize("", on)
+#endif
 
 } // namespace interp
 } // namespace clang
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 0646b87f9412c..eb41021bcf7cf 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -33,15 +33,8 @@
 #include "clang/AST/Expr.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/ScopeExit.h"
 #include <type_traits>
 
-#if __has_cpp_attribute(clang::preserve_none)
-#define PRESERVE_NONE [[clang::preserve_none]]
-#else
-#define PRESERVE_NONE
-#endif
-
 namespace clang {
 namespace interp {
 
@@ -240,7 +233,7 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
                               const Function *Func);
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC) {
+bool Ret(InterpState &S, CodePtr &PC) {
   const T &Ret = S.Stk.pop<T>();
 
   assert(S.Current);
@@ -259,11 +252,10 @@ PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC) {
     // The topmost frame should come from an EvalEmitter,
     // which has its own implementation of the Ret<> instruction.
   }
-
   return true;
 }
 
-PRESERVE_NONE inline bool RetVoid(InterpState &S, CodePtr &PC) {
+inline bool RetVoid(InterpState &S, CodePtr &PC) {
   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
 
   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
@@ -277,7 +269,6 @@ PRESERVE_NONE inline bool RetVoid(InterpState &S, CodePtr 
&PC) {
     InterpFrame::free(S.Current);
     S.Current = nullptr;
   }
-
   return true;
 }
 
@@ -3091,7 +3082,8 @@ static inline bool ShiftFixedPoint(InterpState &S, 
CodePtr OpPC, bool Left) {
 
//===----------------------------------------------------------------------===//
 // NoRet
 
//===----------------------------------------------------------------------===//
-PRESERVE_NONE inline bool NoRet(InterpState &S, CodePtr OpPC) {
+
+inline bool NoRet(InterpState &S, CodePtr OpPC) {
   SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
   S.FFDiag(EndLoc, diag::note_constexpr_no_return);
   return false;
@@ -3312,45 +3304,27 @@ inline bool Unsupported(InterpState &S, CodePtr OpPC) {
   return false;
 }
 
-inline bool PushIgnoreDiags(InterpState &S, CodePtr OpPC) {
-  ++S.DiagIgnoreDepth;
-  if (S.DiagIgnoreDepth != 1)
+inline bool StartSpeculation(InterpState &S, CodePtr OpPC) {
+  ++S.SpeculationDepth;
+  if (S.SpeculationDepth != 1)
     return true;
+
   assert(S.PrevDiags == nullptr);
   S.PrevDiags = S.getEvalStatus().Diag;
   S.getEvalStatus().Diag = nullptr;
-  assert(!S.diagnosing());
   return true;
 }
 
-inline bool PopIgnoreDiags(InterpState &S, CodePtr OpPC) {
-  assert(S.DiagIgnoreDepth != 0);
-  --S.DiagIgnoreDepth;
-  if (S.DiagIgnoreDepth == 0) {
+inline bool EndSpeculation(InterpState &S, CodePtr OpPC) {
+  assert(S.SpeculationDepth != 0);
+  --S.SpeculationDepth;
+  if (S.SpeculationDepth == 0) {
     S.getEvalStatus().Diag = S.PrevDiags;
     S.PrevDiags = nullptr;
   }
   return true;
 }
 
-inline bool StartSpeculation(InterpState &S, CodePtr OpPC) {
-#ifndef NDEBUG
-  ++S.SpeculationDepth;
-#endif
-  return true;
-}
-
-// 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) {
-#ifndef NDEBUG
-  assert(S.SpeculationDepth != 0);
-  --S.SpeculationDepth;
-#endif
-  return true;
-}
-
 inline bool PushCC(InterpState &S, CodePtr OpPC, bool Value) {
   S.ConstantContextOverride = Value;
   return true;
diff --git a/clang/lib/AST/ByteCode/InterpState.h 
b/clang/lib/AST/ByteCode/InterpState.h
index 499a21a094e2c..8ed92432f1c7e 100644
--- a/clang/lib/AST/ByteCode/InterpState.h
+++ b/clang/lib/AST/ByteCode/InterpState.h
@@ -164,10 +164,7 @@ class InterpState final : public State, public 
SourceMapper {
 
   /// Things needed to do speculative execution.
   SmallVectorImpl<PartialDiagnosticAt> *PrevDiags = nullptr;
-#ifndef NDEBUG
   unsigned SpeculationDepth = 0;
-#endif
-  unsigned DiagIgnoreDepth = 0;
   std::optional<bool> ConstantContextOverride;
 
   llvm::SmallVector<
diff --git a/clang/lib/AST/ByteCode/Opcodes.td 
b/clang/lib/AST/ByteCode/Opcodes.td
index 5fbd35950c0eb..da3b850945499 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -178,9 +178,6 @@ def Jt : JumpOpcode;
 // [Bool] -> [], jumps if false.
 def Jf : JumpOpcode;
 
-def PushIgnoreDiags : Opcode;
-def PopIgnoreDiags : Opcode;
-
 def StartSpeculation : Opcode;
 def EndSpeculation : Opcode;
 def BCP : Opcode {
diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp 
b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
index b86731c7d7a11..efa5e06f8a32c 100644
--- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++2b -Woverloaded-virtual %s -verify
-// RUN: %clang_cc1 -fsyntax-only -std=c++2b -Woverloaded-virtual %s -verify 
-fexperimental-new-constant-interpreter
 
 
 // FIXME: can we improve these diagnostics?
diff --git a/clang/test/SemaTemplate/stack-exhaustion.cpp 
b/clang/test/SemaTemplate/stack-exhaustion.cpp
index 61014c7724ce2..c7bfea4132d5e 100644
--- a/clang/test/SemaTemplate/stack-exhaustion.cpp
+++ b/clang/test/SemaTemplate/stack-exhaustion.cpp
@@ -1,10 +1,6 @@
 // RUN: %clang_cc1 -verify %s -DTEST=1
 // RUN: %clang_cc1 -verify %s -DTEST=2
 // RUN: %clang_cc1 -verify %s -DTEST=3
-// RUN: %clang_cc1 -verify %s -DTEST=1 -fexperimental-new-constant-interpreter
-// RUN: %clang_cc1 -verify %s -DTEST=2 -fexperimental-new-constant-interpreter
-// RUN: %clang_cc1 -verify %s -DTEST=3 -fexperimental-new-constant-interpreter
-
 // REQUIRES: thread_support
 
 // FIXME: Detection of, or recovery from, stack exhaustion does not work on
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp 
b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index 3192891801ae9..d26122aca46bd 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -34,8 +34,8 @@ class ClangOpcodesEmitter {
   /// The name is obtained by concatenating the name with the list of types.
   void EmitEnum(raw_ostream &OS, StringRef N, const Record *R);
 
-  void EmitInterpFnList(raw_ostream &OS, StringRef N, const Record *R);
-  void EmitInterpFnDispatchers(raw_ostream &OS, StringRef N, const Record *R);
+  /// Emits the switch case and the invocation in the interpreter.
+  void EmitInterp(raw_ostream &OS, StringRef N, const Record *R);
 
   /// Emits the disassembler.
   void EmitDisasm(raw_ostream &OS, StringRef N, const Record *R);
@@ -91,8 +91,7 @@ void ClangOpcodesEmitter::run(raw_ostream &OS) {
       N = Opcode->getName();
 
     EmitEnum(OS, N, Opcode);
-    EmitInterpFnList(OS, N, Opcode);
-    EmitInterpFnDispatchers(OS, N, Opcode);
+    EmitInterp(OS, N, Opcode);
     EmitDisasm(OS, N, Opcode);
     EmitProto(OS, N, Opcode);
     EmitGroup(OS, N, Opcode);
@@ -110,98 +109,60 @@ void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, 
StringRef N,
   OS << "#endif\n";
 }
 
-void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
-                                                  const Record *R) {
-  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";
-
-    if (ID.str() == "EndSpeculation") {
-      OS << "    MUSTTAIL return EndSpeculation(S, PC);\n";
-      OS << "}\n";
-      return;
-    }
-
-    bool CanReturn = R->getValueAsBit("CanReturn");
-    const auto &Args = R->getValueAsListOfDefs("Args");
-    bool ChangesPC = R->getValueAsBit("ChangesPC");
-
-    if (Args.empty()) {
-      if (CanReturn) {
-        OS << " MUSTTAIL return " << N;
-        PrintTypes(OS, TS);
-        OS << "(S, PC);\n";
-        OS << "}\n";
-        return;
-      }
-
-      OS << "  if (!" << N;
-      PrintTypes(OS, TS);
-      OS << "(S, PC))\n";
-      OS << "    return false;\n";
-      OS << "#if USE_TAILCALLS\n";
-      OS << "  MUSTTAIL return InterpNext(S, PC);\n";
-      OS << "#else\n";
-      OS << "  return true;\n";
-      OS << "#endif\n";
-      OS << "}\n";
-      return;
-    }
+void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N,
+                                     const Record *R) {
+  OS << "#ifdef GET_INTERP\n";
 
-    OS << "  {\n";
+  Enumerate(R, N,
+            [this, R, &OS, &N](ArrayRef<const Record *> TS, const Twine &ID) {
+              bool CanReturn = R->getValueAsBit("CanReturn");
+              bool ChangesPC = R->getVa...
[truncated]

``````````

</details>


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

Reply via email to