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

>From 7df8d6ae3341df1aefb3b5fb8451bc6fbc824cdd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Fri, 5 Jun 2026 15:39:50 +0200
Subject: [PATCH] [clang][bytecode] jumpcase

---
 clang/lib/AST/ByteCode/ByteCodeEmitter.cpp |   4 +
 clang/lib/AST/ByteCode/ByteCodeEmitter.h   |   1 +
 clang/lib/AST/ByteCode/Compiler.cpp        |   4 +-
 clang/lib/AST/ByteCode/Disasm.cpp          |   2 +-
 clang/lib/AST/ByteCode/EvalEmitter.cpp     |   4 +
 clang/lib/AST/ByteCode/EvalEmitter.h       |   1 +
 clang/lib/AST/ByteCode/Interp.cpp          |  11 +-
 clang/lib/AST/ByteCode/Opcodes.td          |   2 +
 clang/test/AST/ByteCode/jump-case.cpp      | 140 +++++++++++++++++++++
 9 files changed, 163 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/AST/ByteCode/jump-case.cpp

diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp 
b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index 393b8481fecd1..4e0d7ea782a54 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -225,6 +225,10 @@ bool ByteCodeEmitter::jumpTrue(const LabelTy &Label, 
SourceInfo SI) {
   return emitJt(getOffset(Label), SI);
 }
 
+bool ByteCodeEmitter::jumpCase(const LabelTy &Label, SourceInfo SI) {
+  return emitJc(getOffset(Label), SI);
+}
+
 bool ByteCodeEmitter::jumpFalse(const LabelTy &Label, SourceInfo SI) {
   return emitJf(getOffset(Label), SI);
 }
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.h 
b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
index 4b42b7eb4063b..8981a43f85b3f 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.h
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
@@ -55,6 +55,7 @@ class ByteCodeEmitter {
 
   /// Emits jumps.
   bool jumpTrue(const LabelTy &Label, SourceInfo SI);
+  bool jumpCase(const LabelTy &Label, SourceInfo SI);
   bool jumpFalse(const LabelTy &Label, SourceInfo SI);
   bool jump(const LabelTy &Label, SourceInfo SI);
   bool fallthrough(const LabelTy &Label);
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 6279b2fb5a38e..ed4de570f980c 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -6654,7 +6654,7 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt 
*S) {
         PrimType HT = this->classifyPrim(High->getType());
         if (!this->emitLE(HT, S))
           return false;
-        if (!this->jumpTrue(CaseLabels[CS], S))
+        if (!this->jumpCase(CaseLabels[CS], S))
           return false;
         this->emitLabel(EndOfRangeCheck);
         continue;
@@ -6674,7 +6674,7 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt 
*S) {
       // Compare and jump to the case label.
       if (!this->emitEQ(ValueT, S))
         return false;
-      if (!this->jumpTrue(CaseLabels[CS], S))
+      if (!this->jumpCase(CaseLabels[CS], S))
         return false;
     } else {
       assert(!DefaultLabel);
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp 
b/clang/lib/AST/ByteCode/Disasm.cpp
index cf7afcd6d4b1e..8060785eb173b 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -128,7 +128,7 @@ template <> inline std::string printArg<FixedPoint>(Program 
&P, CodePtr &OpPC) {
 }
 
 static bool isJumpOpcode(Opcode Op) {
-  return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt;
+  return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt || Op == OP_Jc;
 }
 
 static size_t getNumDisplayWidth(size_t N) {
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp 
b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index 3e1aade65afc8..87fed45646282 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -161,6 +161,10 @@ bool EvalEmitter::jumpTrue(const LabelTy &Label, 
SourceInfo SI) {
   return true;
 }
 
+bool EvalEmitter::jumpCase(const LabelTy &Label, SourceInfo SI) {
+  return jumpTrue(Label, SI);
+}
+
 bool EvalEmitter::jumpFalse(const LabelTy &Label, SourceInfo SI) {
   if (isActive()) {
     CurrentSource = SI;
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h 
b/clang/lib/AST/ByteCode/EvalEmitter.h
index 6fd50da8cad76..e355ea615ebea 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.h
+++ b/clang/lib/AST/ByteCode/EvalEmitter.h
@@ -73,6 +73,7 @@ class EvalEmitter : public SourceMapper {
 
   /// Emits jumps.
   bool jumpTrue(const LabelTy &Label, SourceInfo SI);
+  bool jumpCase(const LabelTy &Label, SourceInfo SI);
   bool jumpFalse(const LabelTy &Label, SourceInfo SI);
   bool jump(const LabelTy &Label, SourceInfo SI);
   bool fallthrough(const LabelTy &Label);
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 699b034c3c683..b974ab75ebdf8 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -62,10 +62,15 @@ static bool Jmp(InterpState &S, CodePtr &PC, int32_t 
Offset) {
   return S.noteStep(PC);
 }
 
-static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
-  if (S.Stk.pop<bool>()) {
+/// jumpCase - like jumpTrue, but we do not note a step.
+static bool Jc(InterpState &S, CodePtr &PC, int32_t Offset) {
+  if (S.Stk.pop<bool>())
     PC += Offset;
-  }
+  return true;
+}
+
+static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset) {
+  Jc(S, PC, Offset);
   return S.noteStep(PC);
 }
 
diff --git a/clang/lib/AST/ByteCode/Opcodes.td 
b/clang/lib/AST/ByteCode/Opcodes.td
index 4bd61cdce658d..b6274c13aa602 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -175,6 +175,8 @@ class JumpOpcode : Opcode {
 def Jmp : JumpOpcode;
 // [Bool] -> [], jumps if true.
 def Jt : JumpOpcode;
+// [Bool] -> [], jumps if true. Does NOT count as a step.
+def Jc : JumpOpcode;
 // [Bool] -> [], jumps if false.
 def Jf : JumpOpcode;
 
diff --git a/clang/test/AST/ByteCode/jump-case.cpp 
b/clang/test/AST/ByteCode/jump-case.cpp
new file mode 100644
index 0000000000000..1b4fcc328c2e9
--- /dev/null
+++ b/clang/test/AST/ByteCode/jump-case.cpp
@@ -0,0 +1,140 @@
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++23 %s 
-fexperimental-new-constant-interpreter -fconstexpr-steps=5000
+
+constexpr int char_to_int(char ch) {
+  switch (ch) {
+  case '0':
+    return 0;
+  case '1':
+    return 1;
+  case '2':
+    return 2;
+  case '3':
+    return 3;
+  case '4':
+    return 4;
+  case '5':
+    return 5;
+  case '6':
+    return 6;
+  case '7':
+    return 7;
+  case '8':
+    return 8;
+  case '9':
+    return 9;
+  case 'a':
+    return 10;
+  case 'A':
+    return 10;
+  case 'b':
+    return 11;
+  case 'B':
+    return 11;
+  case 'c':
+    return 12;
+  case 'C':
+    return 12;
+  case 'd':
+    return 13;
+  case 'D':
+    return 13;
+  case 'e':
+    return 14;
+  case 'E':
+    return 14;
+  case 'f':
+    return 15;
+  case 'F':
+    return 15;
+  case 'g':
+    return 16;
+  case 'G':
+    return 16;
+  case 'h':
+    return 17;
+  case 'H':
+    return 17;
+  case 'i':
+    return 18;
+  case 'I':
+    return 18;
+  case 'j':
+    return 19;
+  case 'J':
+    return 19;
+  case 'k':
+    return 20;
+  case 'K':
+    return 20;
+  case 'l':
+    return 21;
+  case 'L':
+    return 21;
+  case 'm':
+    return 22;
+  case 'M':
+    return 22;
+  case 'n':
+    return 23;
+  case 'N':
+    return 23;
+  case 'o':
+    return 24;
+  case 'O':
+    return 24;
+  case 'p':
+    return 25;
+  case 'P':
+    return 25;
+  case 'q':
+    return 26;
+  case 'Q':
+    return 26;
+  case 'r':
+    return 27;
+  case 'R':
+    return 27;
+  case 's':
+    return 28;
+  case 'S':
+    return 28;
+  case 't':
+    return 29;
+  case 'T':
+    return 29;
+  case 'u':
+    return 30;
+  case 'U':
+    return 30;
+  case 'v':
+    return 31;
+  case 'V':
+    return 31;
+  case 'w':
+    return 32;
+  case 'W':
+    return 32;
+  case 'x':
+    return 33;
+  case 'X':
+    return 33;
+  case 'y':
+  case 'Y':
+    return 34;
+  case 'z':
+  case 'Z':
+    return 35;
+  default:
+    return 0;
+  }
+}
+constexpr bool check() {
+  const char *str = 
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+  unsigned sum = 0;
+  for (const char *p = str; *p != '\0'; ++p) {
+    sum+= char_to_int(*p);
+  }
+  return sum != 0;
+}
+
+static_assert(check());

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

Reply via email to