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

>From ca6e26a828df55c3432e3fbf2d1f3f269cac52d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Mon, 8 Jun 2026 15:05:35 +0200
Subject: [PATCH] as

---
 clang/lib/AST/ByteCode/Compiler.cpp | 24 ++++++++++++++++++++++--
 clang/lib/AST/ByteCode/Interp.h     | 28 ++++++++++++++++++++++------
 clang/lib/AST/ByteCode/Opcodes.td   |  6 +++++-
 clang/lib/AST/ByteCode/Pointer.cpp  | 14 +++++++++-----
 clang/lib/AST/ByteCode/Pointer.h    | 23 +++++++++++++++--------
 clang/test/AST/ByteCode/codegen.cl  | 17 +++++++++++++++++
 6 files changed, 90 insertions(+), 22 deletions(-)
 create mode 100644 clang/test/AST/ByteCode/codegen.cl

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 38a095f8a1164..450ecf991570b 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -716,7 +716,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *E) {
     // FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
     // diagnostic.
     PrimType T = classifyPrim(IntType);
-    if (!this->emitGetIntPtr(T, E->getType().getTypePtr(), E))
+    uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());
+    if (!this->emitGetIntPtr(T, E->getType().getTypePtr(), Val, E))
       return false;
 
     QualType PtrType = E->getType();
@@ -734,10 +735,29 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *E) {
   case CK_NonAtomicToAtomic:
   case CK_NoOp:
   case CK_UserDefinedConversion:
-  case CK_AddressSpaceConversion:
   case CK_CPointerToObjCPointerCast:
     return this->delegate(SubExpr);
 
+  case CK_AddressSpaceConversion: {
+    if (E->containsErrors())
+      return false;
+
+    if (!this->visit(SubExpr))
+      return false;
+
+    uint64_t Val;
+    if (E->getType()->isPointerType())
+      Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());
+    else
+      Val = 0;
+
+    if (!this->emitCastAddressSpace(Val, E->getType().getTypePtr(), E))
+      return false;
+    if (DiscardResult)
+      return this->emitPopPtr(E);
+    return true;
+  }
+
   case CK_BitCast: {
     if (E->containsErrors())
       return false;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index f7d396b720767..06a05054108c9 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2581,9 +2581,9 @@ std::optional<Pointer> OffsetHelper(InterpState &S, 
CodePtr OpPC,
             : S.getASTContext().getTypeSizeInChars(ElemType).getQuantity();
     uint64_t O = static_cast<uint64_t>(Offset) * ElemSize;
     if constexpr (Op == ArithOp::Add) {
-      return Pointer(V + O, Ptr.asIntPointer().Ty);
+      return Pointer(V + O, Ptr.asIntPointer().getType());
     } else
-      return Pointer(V - O, Ptr.asIntPointer().Ty);
+      return Pointer(V - O, Ptr.asIntPointer().getType());
   } else if (Ptr.isFunctionPointer()) {
     uint64_t O = static_cast<uint64_t>(Offset);
     uint64_t N;
@@ -3202,7 +3202,20 @@ template <PrimType Name, class T = typename 
PrimConv<Name>::T>
 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);
+  if constexpr (std::is_same_v<T, Pointer>)
+    S.Stk.push<T>(Value, Ty, /*Offset=*/0, /*IsNull=*/true);
+  else
+    S.Stk.push<T>(Value, Ty);
+  return true;
+}
+
+inline bool CastAddressSpace(InterpState &S, CodePtr OpPC, uint64_t Value,
+                             const Type *Ty) {
+  const Pointer Ptr = S.Stk.pop<Pointer>();
+  if (Ptr.isZero())
+    S.Stk.push<Pointer>(Value, Ty);
+  else
+    S.Stk.push<Pointer>(Ptr);
   return true;
 }
 
@@ -3648,7 +3661,8 @@ inline bool GetFnPtr(InterpState &S, const Function 
*Func) {
 }
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
-inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Type *Ty) {
+inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Type *Ty,
+                      uint64_t NullValue) {
   const T &IntVal = S.Stk.pop<T>();
 
   S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
@@ -3673,7 +3687,8 @@ inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const 
Type *Ty) {
           S.P.getFunction((const FunctionDecl *)IntVal.getPtr());
       S.Stk.push<Pointer>(F, IntVal.getOffset());
     } else {
-      S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Ty);
+      S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Ty, 0,
+                          static_cast<uint64_t>(IntVal) == NullValue);
     }
   } else {
     S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Ty);
@@ -4003,7 +4018,8 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const 
Descriptor *ElementDesc,
       return false;
 
     // If this failed and is nothrow, just return a null ptr.
-    S.Stk.push<Pointer>(0, ElementDesc->getType().getTypePtr());
+    S.Stk.push<Pointer>(0, ElementDesc->getType().getTypePtr(), 0,
+                        /*IsNull=*/true);
     return true;
   }
   if (NumElements.isNegative()) {
diff --git a/clang/lib/AST/ByteCode/Opcodes.td 
b/clang/lib/AST/ByteCode/Opcodes.td
index afed0014c1a10..1ec241b1fe974 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -324,6 +324,10 @@ def Null : SuccessOpcode {
   let HasGroup = 1;
 }
 
+def CastAddressSpace : Opcode {
+  let Args = [ArgUint64, ArgTypePtr];
+}
+
 
//===----------------------------------------------------------------------===//
 // Pointer generation
 
//===----------------------------------------------------------------------===//
@@ -654,7 +658,7 @@ def GetFnPtr : SuccessOpcode {
 
 def GetIntPtr : Opcode {
   let Types = [AluTypeClass];
-  let Args = [ArgTypePtr];
+  let Args = [ArgTypePtr, ArgUint64];
   let HasGroup = 1;
 }
 
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp 
b/clang/lib/AST/ByteCode/Pointer.cpp
index dca2630138a4e..29bba15650ffc 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -212,7 +212,8 @@ bool Pointer::operator==(const Pointer &P) const {
 
   switch (StorageKind) {
   case Storage::Int:
-    return P.Int.Value == Int.Value && P.Int.Ty == Int.Ty && P.Offset == 
Offset;
+    return P.Int.Value == Int.Value && P.Int.getType() == Int.getType() &&
+           P.Offset == Offset;
   case Storage::Block:
     return P.view() == view();
   case Storage::Fn:
@@ -477,7 +478,8 @@ void Pointer::print(llvm::raw_ostream &OS) const {
     OS << "}";
   } break;
   case Storage::Int:
-    OS << "(Int) {" << Int.Value << " + " << Offset << ", " << Int.Ty << "}";
+    OS << "(Int) {" << Int.Value << " + " << Offset << ", " << Int.getType()
+       << ", " << (Int.isNull() ? "null" : "nonnull") << '}';
     break;
   case Storage::Fn:
     OS << "(Fn) { " << Fn.Func << " + " << Offset << " }";
@@ -1361,12 +1363,13 @@ std::optional<IntPointer> IntPointer::atOffset(const 
interp::Context &Ctx,
       ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex))
           .getQuantity();
 
-  return IntPointer{FD->getType().getTypePtr(), this->Value + FieldOffset};
+  uint64_t NewValue = this->Value + FieldOffset;
+  return IntPointer{{FD->getType().getTypePtr(), NewValue == 0}, NewValue};
 }
 
 IntPointer IntPointer::baseCast(const interp::Context &Ctx,
                                 unsigned BaseOffset) const {
-  if (!Ty)
+  if (!getType())
     return *this;
 
   QualType CurType = getPointeeType();
@@ -1391,7 +1394,8 @@ IntPointer IntPointer::baseCast(const interp::Context 
&Ctx,
   const RecordDecl *RD = BaseDesc->ElemRecord->getDecl();
   QualType T = RD->getASTContext().getTagType(ElaboratedTypeKeyword::None,
                                               std::nullopt, RD, false);
-  return {T.getTypePtr(), Value + BaseLayoutOffset.getQuantity()};
+  uint64_t NewValue = Value + BaseLayoutOffset.getQuantity();
+  return {{T.getTypePtr(), NewValue == 0}, NewValue};
 }
 
 std::optional<size_t>
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index 54e0f858b4fa0..4f67e668e4786 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -353,17 +353,22 @@ struct BlockPointer {
 };
 
 struct IntPointer {
-  const Type *Ty;
+  llvm::PointerIntPair<const Type *, 1, bool> TypeAndIsNull;
+  // const Type *Ty;
   uint64_t Value;
+  // bool IsNull = false;
 
   std::optional<IntPointer> atOffset(const Context &Ctx, unsigned Offset) 
const;
   IntPointer baseCast(const Context &Ctx, unsigned BaseOffset) const;
 
+  const Type *getType() const { return TypeAndIsNull.getPointer(); }
+  bool isNull() const { return TypeAndIsNull.getInt(); }
+
   QualType getPointeeType() const {
-    if (!Ty)
+    if (!getType())
       return QualType();
 
-    QualType QT(Ty, 0);
+    QualType QT(getType(), 0);
     if (QT->isPointerOrReferenceType())
       QT = QT->getPointeeType();
     else if (QT->isArrayType())
@@ -535,15 +540,17 @@ enum class Storage { Int, Block, Fn, Typeid, String, 
Opaque };
 /// \endverbatim
 class Pointer {
 public:
-  Pointer() : StorageKind(Storage::Int), Int{nullptr, 0} {}
+  Pointer() : StorageKind(Storage::Int), Int{{nullptr, true}, 0} {}
   Pointer(IntPointer &&IntPtr)
       : StorageKind(Storage::Int), Int(std::move(IntPtr)) {}
   Pointer(Block *B);
   Pointer(Block *B, uint64_t BaseAndOffset);
   Pointer(const Pointer &P);
   Pointer(Pointer &&P);
-  Pointer(uint64_t Address, const Type *Ty, uint64_t Offset = 0)
-      : Offset(Offset), StorageKind(Storage::Int), Int{Ty, Address} {}
+  Pointer(uint64_t Address, const Type *Ty, uint64_t Offset = 0,
+          std::optional<bool> IsNull = std::nullopt)
+      : Offset(Offset), StorageKind(Storage::Int),
+        Int{{Ty, IsNull.value_or(Address == 0)}, Address} {}
   Pointer(const Function *F, uint64_t Offset = 0)
       : Offset(Offset), StorageKind(Storage::Fn), Fn{F} {}
   Pointer(const Type *TypePtr, const Type *TypeInfoType, uint64_t Offset = 0)
@@ -603,7 +610,7 @@ class Pointer {
   [[nodiscard]] Pointer atIndex(uint64_t Idx) const {
     switch (StorageKind) {
     case Storage::Int:
-      return Pointer(Int.Value, Int.Ty, Idx);
+      return Pointer(Int.Value, Int.getType(), Idx);
     case Storage::Block:
       return Pointer(view().atIndex(Idx));
     case Storage::Fn:
@@ -646,7 +653,7 @@ class Pointer {
   bool isZero() const {
     switch (StorageKind) {
     case Storage::Int:
-      return Int.Value == 0 && Offset == 0;
+      return Int.isNull();
     case Storage::Block:
       return BS.Pointee == nullptr;
     case Storage::Fn:
diff --git a/clang/test/AST/ByteCode/codegen.cl 
b/clang/test/AST/ByteCode/codegen.cl
new file mode 100644
index 0000000000000..d2e331905e02d
--- /dev/null
+++ b/clang/test/AST/ByteCode/codegen.cl
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -triple amdgcn 
-fcommon -O0 -emit-llvm -o -                                         | 
FileCheck %s
+// RUN: %clang_cc1 -no-enable-noundef-analysis %s -cl-std=CL2.0 -triple amdgcn 
-fcommon -O0 -emit-llvm -o - -fexperimental-new-constant-interpreter | 
FileCheck %s
+
+// CHECK: @fold_int_local ={{.*}} addrspace(1) global i32 13, align 4
+int fold_int_local = (int)(local void*)(generic char*)(global int*)0 + 14;
+
+// CHECK: @fold_int ={{.*}} addrspace(1) global i32 13, align 4
+int fold_int = (int)(private void*)(generic char*)(global int*)0 + 14;
+
+// CHECK: @test_static_var_private.sp4 = internal addrspace(1) global ptr 
addrspace(5) null, align 4
+// CHECK: @test_static_var_private.sp5 = internal addrspace(1) global ptr 
addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), align 4
+
+void test_static_var_private(void) {
+  static private char *sp4 = (private char*)((void)0, 0);
+  const int x = 0;
+  static private char *sp5 = (private char*)x;
+}

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

Reply via email to