Timm =?utf-8?q?Bäder?= <[email protected]>,
Timm =?utf-8?q?Bäder?= <[email protected]>,
Timm =?utf-8?q?Bäder?= <[email protected]>,
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/173756

>From 91e1b64929800f76a031fd9a58bea87e497707c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 26 Dec 2025 09:07:13 +0100
Subject: [PATCH 1/5] Test

---
 clang/lib/AST/ExprConstant.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8618979d1eba0..72e9193d89f5d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -931,7 +931,7 @@ namespace {
         : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), 
CurrentCall(nullptr),
           CallStackDepth(0), NextCallIndex(1),
           StepsLeft(C.getLangOpts().ConstexprStepLimit),
-          EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp),
+          EnableNewConstInterp(true),
           BottomFrame(*this, SourceLocation(), /*Callee=*/nullptr,
                       /*This=*/nullptr,
                       /*CallExpr=*/nullptr, CallRef()),

>From 8d5e63f54399bb8ef3049a0beabf67730cbec8c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 26 Dec 2025 09:06:45 +0100
Subject: [PATCH 2/5] musttail

---
 clang/lib/AST/ByteCode/Interp.cpp            | 44 +++++-----
 clang/lib/AST/ByteCode/Interp.h              |  7 +-
 clang/utils/TableGen/ClangOpcodesEmitter.cpp | 87 ++++++++++++++++++++
 3 files changed, 114 insertions(+), 24 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 889ac1e1a9a7e..af1bf76db865d 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -28,7 +28,8 @@
 using namespace clang;
 using namespace clang::interp;
 
-static bool RetValue(InterpState &S, CodePtr &Pt) {
+__attribute__((preserve_none)) static bool RetValue(InterpState &S,
+                                                    CodePtr &Pt) {
   llvm::report_fatal_error("Interpreter cannot return values");
 }
 
@@ -2324,38 +2325,39 @@ bool FinishInitGlobal(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-// https://github.com/llvm/llvm-project/issues/102513
-#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
-#pragma optimize("", off)
-#endif
+__attribute__((preserve_none)) static bool InterpNext(InterpState &S,
+                                                      CodePtr &PC);
+
 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();
 
-  // Empty program.
-  if (!PC)
-    return true;
+  return InterpNext(S, PC);
+}
 
-  for (;;) {
-    auto Op = PC.read<Opcode>();
-    CodePtr OpPC = PC;
+#define GET_INTERPFNS_
+#include "Opcodes.inc"
+#undef GET_INTERPFNS_
 
-    switch (Op) {
-#define GET_INTERP
+using InterpFn = __attribute__((preserve_none)) bool (*)(InterpState &,
+                                                         CodePtr &PC);
+
+const InterpFn InterpFunctions[] = {
+#define GET_INTERPFNS
 #include "Opcodes.inc"
-#undef GET_INTERP
-    }
-  }
+#undef GET_INTERPFNS
+};
+
+__attribute__((preserve_none)) static bool InterpNext(InterpState &S,
+                                                      CodePtr &PC) {
+  auto Op = PC.read<Opcode>();
+  auto Fn = InterpFunctions[Op];
+  [[clang::musttail]] return Fn(S, PC);
 }
-// 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 9accbbc1605a9..c32ade5e125b0 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -221,7 +221,7 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
                               const Function *Func);
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-bool Ret(InterpState &S, CodePtr &PC) {
+__attribute__((preserve_none)) bool Ret(InterpState &S, CodePtr &PC) {
   const T &Ret = S.Stk.pop<T>();
 
   assert(S.Current);
@@ -243,7 +243,8 @@ bool Ret(InterpState &S, CodePtr &PC) {
   return true;
 }
 
-inline bool RetVoid(InterpState &S, CodePtr &PC) {
+__attribute__((preserve_none)) inline bool RetVoid(InterpState &S,
+                                                   CodePtr &PC) {
   assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
 
   if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
@@ -3040,7 +3041,7 @@ static inline bool ShiftFixedPoint(InterpState &S, 
CodePtr OpPC, bool Left) {
 // NoRet
 
//===----------------------------------------------------------------------===//
 
-inline bool NoRet(InterpState &S, CodePtr OpPC) {
+__attribute__((preserve_none)) inline bool NoRet(InterpState &S, CodePtr OpPC) 
{
   SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
   S.FFDiag(EndLoc, diag::note_constexpr_no_return);
   return false;
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp 
b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index d26122aca46bd..84c4a673e133a 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -36,6 +36,8 @@ class ClangOpcodesEmitter {
 
   /// Emits the switch case and the invocation in the interpreter.
   void EmitInterp(raw_ostream &OS, StringRef N, const Record *R);
+  void EmitInterpFns(raw_ostream &OS, StringRef N, const Record *R);
+  void EmitInterpFns_(raw_ostream &OS, StringRef N, const Record *R);
 
   /// Emits the disassembler.
   void EmitDisasm(raw_ostream &OS, StringRef N, const Record *R);
@@ -92,6 +94,8 @@ void ClangOpcodesEmitter::run(raw_ostream &OS) {
 
     EmitEnum(OS, N, Opcode);
     EmitInterp(OS, N, Opcode);
+    EmitInterpFns(OS, N, Opcode);
+    EmitInterpFns_(OS, N, Opcode);
     EmitDisasm(OS, N, Opcode);
     EmitProto(OS, N, Opcode);
     EmitGroup(OS, N, Opcode);
@@ -109,6 +113,89 @@ void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, 
StringRef N,
   OS << "#endif\n";
 }
 
+void ClangOpcodesEmitter::EmitInterpFns_(raw_ostream &OS, StringRef N,
+                                         const Record *R) {
+  OS << "#ifdef GET_INTERPFNS_\n";
+  Enumerate(R, N, [&](ArrayRef<const Record *> TS, const Twine &ID) {
+    OS << "__attribute__((preserve_none))\nstatic bool Interp_" << ID
+       << "(InterpState &S, CodePtr &PC) {\n";
+
+    bool CanReturn = R->getValueAsBit("CanReturn");
+    const auto &Args = R->getValueAsListOfDefs("Args");
+    bool ChangesPC = R->getValueAsBit("ChangesPC");
+
+    if (Args.empty()) {
+      if (CanReturn) {
+        OS << " [[clang::musttail]] return " << N;
+        PrintTypes(OS, TS);
+        OS << "(S, PC);\n";
+        OS << "}\n";
+        return;
+      }
+
+      // OS << "llvm::errs() << \"Calling \" << \"" << N << "\\n\";";//'\n';
+      OS << "  if (!" << N;
+      PrintTypes(OS, TS);
+      OS << "(S, PC))\n";
+      OS << "  return false;\n";
+      OS << "[[clang::musttail]] return InterpNext(S, PC);\n";
+      OS << "}\n";
+      return;
+    }
+
+    OS << "{\n";
+
+    if (!ChangesPC)
+      OS << "  CodePtr OpPC = PC;\n";
+
+    // Emit calls to read arguments.
+    for (size_t I = 0, N = Args.size(); I < N; ++I) {
+      const auto *Arg = Args[I];
+      bool AsRef = Arg->getValueAsBit("AsRef");
+
+      if (AsRef)
+        OS << "  const auto &V" << I;
+      else
+        OS << "  const auto V" << I;
+      OS << " = ";
+      OS << "ReadArg<" << Arg->getValueAsString("Name") << ">(S, PC);\n";
+    }
+
+    OS << "  if (!" << N;
+    PrintTypes(OS, TS);
+    OS << "(S";
+    // OS << ", OpPC";
+    if (ChangesPC)
+      OS << ", PC";
+    else
+      OS << ", OpPC";
+    for (size_t I = 0, N = Args.size(); I < N; ++I)
+      OS << ", V" << I;
+    OS << "))\n";
+    OS << "    return false;\n";
+
+    OS << "}\n";
+
+    if (!CanReturn)
+      OS << "[[clang::musttail]] return InterpNext(S, PC);\n";
+    else
+      OS << " return true;\n";
+    // OS << "  return false;\n";
+
+    OS << "}\n";
+  });
+  OS << "#endif\n";
+}
+
+void ClangOpcodesEmitter::EmitInterpFns(raw_ostream &OS, StringRef N,
+                                        const Record *R) {
+  OS << "#ifdef GET_INTERPFNS\n";
+  Enumerate(R, N, [&OS](ArrayRef<const Record *>, const Twine &ID) {
+    OS << "&Interp_" << ID << ",\n";
+  });
+  OS << "#endif\n";
+}
+
 void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N,
                                      const Record *R) {
   OS << "#ifdef GET_INTERP\n";

>From 63ca4e59c10b19eed4b5c2e173b33c4758d889b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Sun, 28 Dec 2025 06:37:20 +0100
Subject: [PATCH 3/5] Revert "Test"

This reverts commit 699354a4146e2ebc7e7c7aa84d14c396a4300508.
---
 clang/lib/AST/ExprConstant.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 72e9193d89f5d..8618979d1eba0 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -931,7 +931,7 @@ namespace {
         : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), 
CurrentCall(nullptr),
           CallStackDepth(0), NextCallIndex(1),
           StepsLeft(C.getLangOpts().ConstexprStepLimit),
-          EnableNewConstInterp(true),
+          EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp),
           BottomFrame(*this, SourceLocation(), /*Callee=*/nullptr,
                       /*This=*/nullptr,
                       /*CallExpr=*/nullptr, CallRef()),

>From 721741435ec7f21caacd2e6f5e48f0ef5b2a92ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 2 Jan 2026 10:38:31 +0100
Subject: [PATCH 4/5] Use a macro for the preserve_none attribute

---
 clang/lib/AST/ByteCode/Interp.cpp            | 30 ++++++++++++--------
 clang/utils/TableGen/ClangOpcodesEmitter.cpp | 22 +++++++-------
 2 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index af1bf76db865d..dbd0cccd9ba75 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -28,8 +28,13 @@
 using namespace clang;
 using namespace clang::interp;
 
-__attribute__((preserve_none)) static bool RetValue(InterpState &S,
-                                                    CodePtr &Pt) {
+#ifdef __clang__
+#define PRESERVE_NONE [[clang::preserve_none]]
+#else
+#define PRESERVE_NONE
+#endif
+
+PRESERVE_NONE static bool RetValue(InterpState &S, CodePtr &Pt) {
   llvm::report_fatal_error("Interpreter cannot return values");
 }
 
@@ -2325,8 +2330,7 @@ bool FinishInitGlobal(InterpState &S, CodePtr OpPC) {
   return true;
 }
 
-__attribute__((preserve_none)) static bool InterpNext(InterpState &S,
-                                                      CodePtr &PC);
+PRESERVE_NONE static bool InterpNext(InterpState &S, CodePtr &PC);
 
 bool Interpret(InterpState &S) {
   // The current stack frame when we started Interpret().
@@ -2339,21 +2343,23 @@ bool Interpret(InterpState &S) {
   return InterpNext(S, PC);
 }
 
-#define GET_INTERPFNS_
+// The dispatcher functions read the opcode arguments from the
+// bytecode and call the implementation function.
+#define GET_INTERPFN_DISPATCHERS
 #include "Opcodes.inc"
-#undef GET_INTERPFNS_
+#undef GET_INTERPFN_DISPATCHERS
 
-using InterpFn = __attribute__((preserve_none)) bool (*)(InterpState &,
-                                                         CodePtr &PC);
+using InterpFn = bool (*)(InterpState &, CodePtr &PC) PRESERVE_NONE;
 
+// Array of the dispatcher functions defined above.
 const InterpFn InterpFunctions[] = {
-#define GET_INTERPFNS
+#define GET_INTERPFN_LIST
 #include "Opcodes.inc"
-#undef GET_INTERPFNS
+#undef GET_INTERPFN_LIST
 };
 
-__attribute__((preserve_none)) static bool InterpNext(InterpState &S,
-                                                      CodePtr &PC) {
+// 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];
   [[clang::musttail]] return Fn(S, PC);
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp 
b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index 84c4a673e133a..ed6934509b4da 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -36,8 +36,8 @@ class ClangOpcodesEmitter {
 
   /// Emits the switch case and the invocation in the interpreter.
   void EmitInterp(raw_ostream &OS, StringRef N, const Record *R);
-  void EmitInterpFns(raw_ostream &OS, StringRef N, const Record *R);
-  void EmitInterpFns_(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 disassembler.
   void EmitDisasm(raw_ostream &OS, StringRef N, const Record *R);
@@ -94,8 +94,8 @@ void ClangOpcodesEmitter::run(raw_ostream &OS) {
 
     EmitEnum(OS, N, Opcode);
     EmitInterp(OS, N, Opcode);
-    EmitInterpFns(OS, N, Opcode);
-    EmitInterpFns_(OS, N, Opcode);
+    EmitInterpFnList(OS, N, Opcode);
+    EmitInterpFnDispatchers(OS, N, Opcode);
     EmitDisasm(OS, N, Opcode);
     EmitProto(OS, N, Opcode);
     EmitGroup(OS, N, Opcode);
@@ -113,11 +113,11 @@ void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, 
StringRef N,
   OS << "#endif\n";
 }
 
-void ClangOpcodesEmitter::EmitInterpFns_(raw_ostream &OS, StringRef N,
-                                         const Record *R) {
-  OS << "#ifdef GET_INTERPFNS_\n";
+void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
+                                                  const Record *R) {
+  OS << "#ifdef GET_INTERPFN_DISPATCHERS\n";
   Enumerate(R, N, [&](ArrayRef<const Record *> TS, const Twine &ID) {
-    OS << "__attribute__((preserve_none))\nstatic bool Interp_" << ID
+    OS << "PRESERVE_NONE\nstatic bool Interp_" << ID
        << "(InterpState &S, CodePtr &PC) {\n";
 
     bool CanReturn = R->getValueAsBit("CanReturn");
@@ -187,9 +187,9 @@ void ClangOpcodesEmitter::EmitInterpFns_(raw_ostream &OS, 
StringRef N,
   OS << "#endif\n";
 }
 
-void ClangOpcodesEmitter::EmitInterpFns(raw_ostream &OS, StringRef N,
-                                        const Record *R) {
-  OS << "#ifdef GET_INTERPFNS\n";
+void ClangOpcodesEmitter::EmitInterpFnList(raw_ostream &OS, StringRef N,
+                                           const Record *R) {
+  OS << "#ifdef GET_INTERPFN_LIST\n";
   Enumerate(R, N, [&OS](ArrayRef<const Record *>, const Twine &ID) {
     OS << "&Interp_" << ID << ",\n";
   });

>From 6b87a71d03cbe396f6f26044e444047641b7eee5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 2 Jan 2026 12:10:49 +0100
Subject: [PATCH 5/5] Use a macro for musttail attribute

---
 clang/lib/AST/ByteCode/Interp.cpp            | 10 ++++++++
 clang/utils/TableGen/ClangOpcodesEmitter.cpp | 27 +++++++++-----------
 2 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index dbd0cccd9ba75..b391171f86682 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -34,6 +34,16 @@ using namespace clang::interp;
 #define PRESERVE_NONE
 #endif
 
+#if defined(_MSC_VER) && !defined(__clang__)
+#ifdef NDEBUG
+#define MUSTTAIL [[msvc::musttail]]
+#else
+#define MUSTTAIL
+#endif
+#else
+#define MUSTTAIL [[clang::musttail]]
+#endif
+
 PRESERVE_NONE static bool RetValue(InterpState &S, CodePtr &Pt) {
   llvm::report_fatal_error("Interpreter cannot return values");
 }
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp 
b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index ed6934509b4da..c89dc632d1137 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -126,27 +126,26 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
 
     if (Args.empty()) {
       if (CanReturn) {
-        OS << " [[clang::musttail]] return " << N;
+        OS << " MUSTTAIL return " << N;
         PrintTypes(OS, TS);
         OS << "(S, PC);\n";
         OS << "}\n";
         return;
       }
 
-      // OS << "llvm::errs() << \"Calling \" << \"" << N << "\\n\";";//'\n';
       OS << "  if (!" << N;
       PrintTypes(OS, TS);
       OS << "(S, PC))\n";
-      OS << "  return false;\n";
-      OS << "[[clang::musttail]] return InterpNext(S, PC);\n";
+      OS << "    return false;\n";
+      OS << "  MUSTTAIL return InterpNext(S, PC);\n";
       OS << "}\n";
       return;
     }
 
-    OS << "{\n";
+    OS << "  {\n";
 
     if (!ChangesPC)
-      OS << "  CodePtr OpPC = PC;\n";
+      OS << "    CodePtr OpPC = PC;\n";
 
     // Emit calls to read arguments.
     for (size_t I = 0, N = Args.size(); I < N; ++I) {
@@ -154,17 +153,16 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
       bool AsRef = Arg->getValueAsBit("AsRef");
 
       if (AsRef)
-        OS << "  const auto &V" << I;
+        OS << "    const auto &V" << I;
       else
-        OS << "  const auto V" << I;
+        OS << "    const auto V" << I;
       OS << " = ";
       OS << "ReadArg<" << Arg->getValueAsString("Name") << ">(S, PC);\n";
     }
 
-    OS << "  if (!" << N;
+    OS << "    if (!" << N;
     PrintTypes(OS, TS);
     OS << "(S";
-    // OS << ", OpPC";
     if (ChangesPC)
       OS << ", PC";
     else
@@ -172,15 +170,14 @@ void 
ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N,
     for (size_t I = 0, N = Args.size(); I < N; ++I)
       OS << ", V" << I;
     OS << "))\n";
-    OS << "    return false;\n";
+    OS << "      return false;\n";
 
-    OS << "}\n";
+    OS << "  }\n";
 
     if (!CanReturn)
-      OS << "[[clang::musttail]] return InterpNext(S, PC);\n";
+      OS << "  MUSTTAIL return InterpNext(S, PC);\n";
     else
-      OS << " return true;\n";
-    // OS << "  return false;\n";
+      OS << "  return true;\n";
 
     OS << "}\n";
   });

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

Reply via email to