[clang] [clang][Interp] Integral pointers (PR #84159)

2024-04-11 Thread Simon Pilgrim via cfe-commits


@@ -22,7 +22,11 @@ class FunctionPointer final {
   const Function *Func;
 
 public:
-  FunctionPointer() : Func(nullptr) {}
+  // FIXME: We might want to track the fact that the Function pointer
+  // has been created from an integer and is most likely garbage anyway.
+  FunctionPointer(int IntVal = 0, const Descriptor *Desc = nullptr)

RKSimon wrote:

For reference @AaronBallman fixed this in 
4d80dff819d1164775d0d55fc68bffedb90ba53c

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-04-11 Thread Timm Baeder via cfe-commits


@@ -22,7 +22,11 @@ class FunctionPointer final {
   const Function *Func;
 
 public:
-  FunctionPointer() : Func(nullptr) {}
+  // FIXME: We might want to track the fact that the Function pointer
+  // has been created from an integer and is most likely garbage anyway.
+  FunctionPointer(int IntVal = 0, const Descriptor *Desc = nullptr)

tbaederr wrote:

Ah sorry, looks like I'm too slow :upside_down_face: 

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-04-11 Thread Timm Baeder via cfe-commits


@@ -22,7 +22,11 @@ class FunctionPointer final {
   const Function *Func;
 
 public:
-  FunctionPointer() : Func(nullptr) {}
+  // FIXME: We might want to track the fact that the Function pointer
+  // has been created from an integer and is most likely garbage anyway.
+  FunctionPointer(int IntVal = 0, const Descriptor *Desc = nullptr)

tbaederr wrote:

Sorry, will fix that.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-04-10 Thread Simon Pilgrim via cfe-commits


@@ -22,7 +22,11 @@ class FunctionPointer final {
   const Function *Func;
 
 public:
-  FunctionPointer() : Func(nullptr) {}
+  // FIXME: We might want to track the fact that the Function pointer
+  // has been created from an integer and is most likely garbage anyway.
+  FunctionPointer(int IntVal = 0, const Descriptor *Desc = nullptr)

RKSimon wrote:

@tbaederr  This is causing a lot of MSVC warnings - `int IntVal` -> `intptr_t 
IntVal`?

`warning C4312: 'reinterpret_cast': conversion from 'int' to 'const 
clang::interp::Function *' of greater size`

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-04-10 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr closed 
https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-04-09 Thread Timm Baeder via cfe-commits

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

>From 3d6a09d1324dbd354668b0341644fb70fe09a47c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Wed, 6 Mar 2024 08:36:52 +0100
Subject: [PATCH] [clang][Interp] Integral pointers

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  81 -
 clang/lib/AST/Interp/ByteCodeStmtGen.cpp |   2 +-
 clang/lib/AST/Interp/Descriptor.h|   1 +
 clang/lib/AST/Interp/FunctionPointer.h   |  10 +-
 clang/lib/AST/Interp/Interp.cpp  |   5 +
 clang/lib/AST/Interp/Interp.h|  85 +++--
 clang/lib/AST/Interp/InterpBlock.cpp |   4 +-
 clang/lib/AST/Interp/Opcodes.td  |  12 +
 clang/lib/AST/Interp/Pointer.cpp | 168 +++---
 clang/lib/AST/Interp/Pointer.h   | 383 +--
 clang/lib/AST/Interp/PrimType.h  |   4 +
 clang/test/AST/Interp/c.c|  18 ++
 clang/test/AST/Interp/const-eval.c   | 192 
 clang/test/AST/Interp/functions.cpp  |  15 +
 14 files changed, 798 insertions(+), 182 deletions(-)
 create mode 100644 clang/test/AST/Interp/const-eval.c

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index a1ce6575148325..4e650d49d180bb 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -173,10 +173,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -199,6 +207,41 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType()))
+  Desc = P.createDescriptor(SubExpr, *T);
+else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+
+if (!this->emitGetIntPtr(T, Desc, CE))
+  return false;
+
+PrimType DestPtrT = classifyPrim(PtrType);
+if (DestPtrT == PT_Ptr)
+  return true;
+
+// In case we're converting the integer to a non-Pointer.
+return this->emitDecayPtr(PT_Ptr, DestPtrT, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
   case CK_FunctionToPointerDecay:
@@ -207,13 +250,31 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
   case CK_UserDefinedConversion:
 return this->delegate(SubExpr);
 
-  case CK_BitCast:
+  case CK_BitCast: {
+// Reject bitcasts to atomic types.
 if (CE->getType()->isAtomicType()) {
   if (!this->discard(SubExpr))
 return false;
   return this->emitInvalidCast(CastKind::Reinterpret, CE);
 }
-return this->delegate(SubExpr);
+
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+std::optional FromT = classify(SubExpr->getType());
+std::optional ToT = classifyPrim(CE->getType());
+if (!FromT || !ToT)
+  return false;
+
+assert(isPtrType(*FromT));
+assert(isPtrType(*ToT));
+if (FromT == ToT)
+  return this->delegate(SubExpr);
+
+if (!this->visit(SubExpr))
+  return false;
+return this->emitDecayPtr(*FromT, *ToT, CE);
+  }
 
   case CK_IntegralToBoolean:
   case CK_IntegralCast: {
@@ -245,7 +306,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr 
*CE) {
 if (!this->visit(SubExpr))
   return false;
 
-if (!this->emitNull(PtrT, CE))
+if (!this->emitNull(PtrT, nullptr, CE))
   return false;
 
 return this->emitNE(PtrT, CE);
@@ -455,7 +516,7 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 
   // Pointer arithmetic special case.
   if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
-if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr))
+if (isPtrType(*T) || 

[clang] [clang][Interp] Integral pointers (PR #84159)

2024-04-09 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= 
Message-ID:
In-Reply-To: 



@@ -1912,6 +1929,10 @@ inline bool NoRet(InterpState , CodePtr OpPC) {
 
 inline bool NarrowPtr(InterpState , CodePtr OpPC) {
   const Pointer  = S.Stk.pop();
+  if (!S.getLangOpts().CPlusPlus) {
+S.Stk.push(Ptr);

tbaederr wrote:

Don't remember why I added that but it's not necessary.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-25 Thread Aaron Ballman via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 



@@ -2218,6 +2238,14 @@ inline bool GetFnPtr(InterpState , CodePtr OpPC, const 
Function *Func) {
   return true;
 }
 
+template ::T>
+inline bool GetIntPtr(InterpState , CodePtr OpPC, const Descriptor *Desc) {
+  const T  = S.Stk.pop();
+
+  S.Stk.push(static_cast(IntVal), Desc);

AaronBallman wrote:

`uint64_t`?

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-25 Thread Aaron Ballman via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 



@@ -199,6 +207,41 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType()))
+  Desc = P.createDescriptor(SubExpr, *T);
+else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+
+if (!this->emitGetIntPtr(T, Desc, CE))
+  return false;
+
+PrimType DestPtrT = classifyPrim(PtrType);
+if (DestPtrT == PT_Ptr)
+  return true;
+
+// // In case we're converting the integer to a non-Pointer.

AaronBallman wrote:

```suggestion
// In case we're converting the integer to a non-Pointer.
```

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-25 Thread Aaron Ballman via cfe-commits
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= 
Message-ID:
In-Reply-To: 



@@ -1912,6 +1929,10 @@ inline bool NoRet(InterpState , CodePtr OpPC) {
 
 inline bool NarrowPtr(InterpState , CodePtr OpPC) {
   const Pointer  = S.Stk.pop();
+  if (!S.getLangOpts().CPlusPlus) {
+S.Stk.push(Ptr);

AaronBallman wrote:

Still think a comment here would be helpful

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-25 Thread Aaron Ballman via cfe-commits
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= 
Message-ID:
In-Reply-To: 


https://github.com/AaronBallman approved this pull request.

Basically LGTM, just a few minor things.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-25 Thread Aaron Ballman via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


https://github.com/AaronBallman edited 
https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-25 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= 
Message-ID:
In-Reply-To: 


tbaederr wrote:

Ping

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-18 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


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

>From 1c06781e92b8fec78ae82b0d6a85965524d223d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Mon, 18 Mar 2024 12:21:16 +0100
Subject: [PATCH 1/6] [clang][Interp] Handle CXXDefaultInitExpr of composite
 type

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  6 +-
 clang/test/AST/Interp/records.cpp| 21 +
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 6cee3c1af9f66a..d943dcbe06507b 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2916,11 +2916,7 @@ template 
 bool ByteCodeExprGen::VisitCXXDefaultInitExpr(
 const CXXDefaultInitExpr *E) {
   SourceLocScope SLS(this, E);
-  if (Initializing)
-return this->visitInitializer(E->getExpr());
-
-  assert(classify(E->getType()));
-  return this->visit(E->getExpr());
+  return this->delegate(E->getExpr());
 }
 
 template 
diff --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index d37d4410c763fb..0f76e0cfe99277 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1264,3 +1264,24 @@ namespace {
   static_assert(true_type::value, "");
   static_assert(true_type::value, "");
 }
+
+#if __cplusplus >= 202002L
+namespace {
+  /// Used to crash because the CXXDefaultInitExpr is of compound type.
+  struct A {
+int 
+constexpr ~A() { --x; }
+  };
+  struct B {
+int 
+const A  = A{x};
+  };
+  constexpr int a() {
+int x = 1;
+int f = B{x}.x;
+B{x}; // both-warning {{expression result unused}}
+
+return 1;
+  }
+}
+#endif

>From 3f47e6fde4b0b05ac243d1afa69eb9adde650614 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Wed, 6 Mar 2024 08:36:52 +0100
Subject: [PATCH 2/6] Integral pointers

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  74 -
 clang/lib/AST/Interp/ByteCodeStmtGen.cpp |   2 +-
 clang/lib/AST/Interp/Descriptor.h|   1 +
 clang/lib/AST/Interp/FunctionPointer.h   |  10 +-
 clang/lib/AST/Interp/Interp.cpp  |   5 +
 clang/lib/AST/Interp/Interp.h|  89 --
 clang/lib/AST/Interp/InterpBlock.cpp |   4 +-
 clang/lib/AST/Interp/Opcodes.td  |  12 +
 clang/lib/AST/Interp/Pointer.cpp | 176 ---
 clang/lib/AST/Interp/Pointer.h   | 369 ---
 clang/lib/AST/Interp/PrimType.h  |   4 +
 clang/test/AST/Interp/c.c|  18 ++
 clang/test/AST/Interp/const-eval.c   | 194 
 13 files changed, 777 insertions(+), 181 deletions(-)
 create mode 100644 clang/test/AST/Interp/const-eval.c

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index d943dcbe06507b..464e598cdd77e8 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -173,10 +173,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -199,6 +207,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}
+
+return this->emitGetIntPtr(T, Desc, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case 

[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-18 Thread via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 5143a1241362616840af826d18c067025dae 
6b7b99579fb50c338617af58d3e82ec099430f35 -- clang/test/AST/Interp/const-eval.c 
clang/lib/AST/Interp/ByteCodeExprGen.cpp 
clang/lib/AST/Interp/ByteCodeStmtGen.cpp clang/lib/AST/Interp/Descriptor.h 
clang/lib/AST/Interp/FunctionPointer.h clang/lib/AST/Interp/Interp.cpp 
clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/InterpBlock.cpp 
clang/lib/AST/Interp/Pointer.cpp clang/lib/AST/Interp/Pointer.h 
clang/lib/AST/Interp/PrimType.h clang/test/AST/Interp/c.c 
clang/test/AST/Interp/functions.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 7521d44e3a..387a3e9fd2 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -390,7 +390,8 @@ public:
 // If this points inside a dummy block, return true.
 // FIXME: This might change in the future. If it does, we need
 // to set the proper Ctor/Dtor functions for dummy Descriptors.
-if (asBlockPointer().Base != 0 && asBlockPointer().Base != 
sizeof(InlineDescriptor) && isDummy())
+if (asBlockPointer().Base != 0 &&
+asBlockPointer().Base != sizeof(InlineDescriptor) && isDummy())
   return true;
 return getFieldDesc()->isUnknownSizeArray();
   }

``




https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-18 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


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

>From 7d49f0f7310c86fae986f0b84bfbf2bb6e79a745 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Wed, 6 Mar 2024 08:36:52 +0100
Subject: [PATCH 1/5] Integral pointers

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  74 -
 clang/lib/AST/Interp/ByteCodeStmtGen.cpp |   2 +-
 clang/lib/AST/Interp/Descriptor.h|   1 +
 clang/lib/AST/Interp/FunctionPointer.h   |  10 +-
 clang/lib/AST/Interp/Interp.cpp  |   5 +
 clang/lib/AST/Interp/Interp.h|  89 --
 clang/lib/AST/Interp/InterpBlock.cpp |   4 +-
 clang/lib/AST/Interp/Opcodes.td  |  12 +
 clang/lib/AST/Interp/Pointer.cpp | 176 ---
 clang/lib/AST/Interp/Pointer.h   | 368 ---
 clang/lib/AST/Interp/PrimType.h  |   4 +
 clang/test/AST/Interp/c.c|  18 ++
 clang/test/AST/Interp/const-eval.c   | 194 
 13 files changed, 776 insertions(+), 181 deletions(-)
 create mode 100644 clang/test/AST/Interp/const-eval.c

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 6cee3c1af9f66a..65b68f70b890e4 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -173,10 +173,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -199,6 +207,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}
+
+return this->emitGetIntPtr(T, Desc, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
   case CK_FunctionToPointerDecay:
@@ -207,13 +243,31 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
   case CK_UserDefinedConversion:
 return this->delegate(SubExpr);
 
-  case CK_BitCast:
+  case CK_BitCast: {
+// Reject bitcasts to atomic types.
 if (CE->getType()->isAtomicType()) {
   if (!this->discard(SubExpr))
 return false;
   return this->emitInvalidCast(CastKind::Reinterpret, CE);
 }
-return this->delegate(SubExpr);
+
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+std::optional FromT = classify(SubExpr->getType());
+std::optional ToT = classifyPrim(CE->getType());
+if (!FromT || !ToT)
+  return false;
+
+assert(isPtrType(*FromT));
+assert(isPtrType(*ToT));
+if (FromT == ToT)
+  return this->delegate(SubExpr);
+
+if (!this->visit(SubExpr))
+  return false;
+return this->emitDecayPtr(*FromT, *ToT, CE);
+  }
 
   case CK_IntegralToBoolean:
   case CK_IntegralCast: {
@@ -245,7 +299,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr 
*CE) {
 if (!this->visit(SubExpr))
   return false;
 
-if (!this->emitNull(PtrT, CE))
+if (!this->emitNull(PtrT, nullptr, CE))
   return false;
 
 return this->emitNE(PtrT, CE);
@@ -454,7 +508,7 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 
   // Pointer arithmetic special case.
   if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
-if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr))
+if (isPtrType(*T) || (isPtrType(*LT) && isPtrType(*RT)))
   return this->VisitPointerArithBinOp(BO);
   }
 
@@ -2322,7 +2376,7 @@ bool ByteCodeExprGen::visitBool(const Expr *E) {
 

[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-15 Thread Aaron Ballman via cfe-commits
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= 
Message-ID:
In-Reply-To: 



@@ -53,6 +57,10 @@ class FunctionPointer final {
 return toAPValue().getAsString(Ctx, Func->getDecl()->getType());
   }
 
+  uint32_t getIntegerRepresentation() const {
+return static_cast(reinterpret_cast(Func));
+  }

AaronBallman wrote:

Yeah, same here as below.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-15 Thread Aaron Ballman via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 



@@ -28,11 +28,26 @@ class Block;
 class DeadBlock;
 class Pointer;
 class Context;
+template  class Integral;
 enum PrimType : unsigned;
 
 class Pointer;
 inline llvm::raw_ostream <<(llvm::raw_ostream , const Pointer );
 
+struct BlockPointer {
+  /// The block the pointer is pointing to.
+  Block *Pointee;
+  /// Start of the current subfield.
+  unsigned Base;
+};
+
+struct IntPointer {
+  const Descriptor *Desc;
+  int Value;

AaronBallman wrote:

ah that's a good point, it probably should be uint64_t consistently.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-15 Thread Aaron Ballman via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 



@@ -28,11 +28,26 @@ class Block;
 class DeadBlock;
 class Pointer;
 class Context;
+template  class Integral;
 enum PrimType : unsigned;
 
 class Pointer;
 inline llvm::raw_ostream <<(llvm::raw_ostream , const Pointer );
 
+struct BlockPointer {

AaronBallman wrote:

Let's leave it alone for now.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-14 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 



@@ -28,11 +28,26 @@ class Block;
 class DeadBlock;
 class Pointer;
 class Context;
+template  class Integral;
 enum PrimType : unsigned;
 
 class Pointer;
 inline llvm::raw_ostream <<(llvm::raw_ostream , const Pointer );
 
+struct BlockPointer {

tbaederr wrote:

I don't have that problem but I could imaging renaming to `MemoryPointer` or 
something similar - we do have a `interp::Block` class though, so the name 
`BlockPointer` makes sense in the context. Not sure what I would rename `Block` 
to.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-14 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?B=C3=A4der?= ,
Timm =?utf-8?q?B=C3=A4der?= 
Message-ID:
In-Reply-To: 



@@ -53,6 +57,10 @@ class FunctionPointer final {
 return toAPValue().getAsString(Ctx, Func->getDecl()->getType());
   }
 
+  uint32_t getIntegerRepresentation() const {
+return static_cast(reinterpret_cast(Func));
+  }

tbaederr wrote:

Same comment as below - it should probably be a 64bit int?

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-07 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


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

>From 5eacd7478d3db7472d5ab983468a441b1f61ad7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Wed, 6 Mar 2024 08:36:52 +0100
Subject: [PATCH 1/3] Integral pointers

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  74 -
 clang/lib/AST/Interp/ByteCodeStmtGen.cpp |   2 +-
 clang/lib/AST/Interp/Descriptor.h|   1 +
 clang/lib/AST/Interp/FunctionPointer.h   |  10 +-
 clang/lib/AST/Interp/Interp.cpp  |   5 +
 clang/lib/AST/Interp/Interp.h|  89 --
 clang/lib/AST/Interp/InterpBlock.cpp |   4 +-
 clang/lib/AST/Interp/Opcodes.td  |  12 +
 clang/lib/AST/Interp/Pointer.cpp | 176 ---
 clang/lib/AST/Interp/Pointer.h   | 366 ---
 clang/lib/AST/Interp/PrimType.h  |   4 +
 clang/test/AST/Interp/c.c|  18 ++
 clang/test/AST/Interp/const-eval.c   | 194 
 13 files changed, 775 insertions(+), 180 deletions(-)
 create mode 100644 clang/test/AST/Interp/const-eval.c

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index d887170cbc5d2d..67e7d89c033d63 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -161,10 +161,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -187,6 +195,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}
+
+return this->emitGetIntPtr(T, Desc, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
   case CK_FunctionToPointerDecay:
@@ -195,13 +231,31 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
   case CK_UserDefinedConversion:
 return this->delegate(SubExpr);
 
-  case CK_BitCast:
+  case CK_BitCast: {
+// Reject bitcasts to atomic types.
 if (CE->getType()->isAtomicType()) {
   if (!this->discard(SubExpr))
 return false;
   return this->emitInvalidCast(CastKind::Reinterpret, CE);
 }
-return this->delegate(SubExpr);
+
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+std::optional FromT = classify(SubExpr->getType());
+std::optional ToT = classifyPrim(CE->getType());
+if (!FromT || !ToT)
+  return false;
+
+assert(isPtrType(*FromT));
+assert(isPtrType(*ToT));
+if (FromT == ToT)
+  return this->delegate(SubExpr);
+
+if (!this->visit(SubExpr))
+  return false;
+return this->emitDecayPtr(*FromT, *ToT, CE);
+  }
 
   case CK_IntegralToBoolean:
   case CK_IntegralCast: {
@@ -233,7 +287,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr 
*CE) {
 if (!this->visit(SubExpr))
   return false;
 
-if (!this->emitNull(PtrT, CE))
+if (!this->emitNull(PtrT, nullptr, CE))
   return false;
 
 return this->emitNE(PtrT, CE);
@@ -445,7 +499,7 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 
   // Pointer arithmetic special case.
   if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
-if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr))
+if (isPtrType(*T) || (isPtrType(*LT) && isPtrType(*RT)))
   return this->VisitPointerArithBinOp(BO);
   }
 
@@ -2296,7 +2350,7 @@ bool ByteCodeExprGen::visitBool(const Expr *E) {
 
   // Convert pointers to bool.
   if (T == 

[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-07 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 



@@ -28,11 +28,26 @@ class Block;
 class DeadBlock;
 class Pointer;
 class Context;
+template  class Integral;
 enum PrimType : unsigned;
 
 class Pointer;
 inline llvm::raw_ostream <<(llvm::raw_ostream , const Pointer );
 
+struct BlockPointer {
+  /// The block the pointer is pointing to.
+  Block *Pointee;
+  /// Start of the current subfield.
+  unsigned Base;
+};
+
+struct IntPointer {
+  const Descriptor *Desc;
+  int Value;

tbaederr wrote:

I was wondering about that... shouldn't it be a `uint64_t`? For the case where 
we're on a 32 bit host and compile for a 64 bit target?

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-07 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?B=C3=A4der?= 
Message-ID:
In-Reply-To: 



@@ -123,8 +167,9 @@ APValue Pointer::toAPValue() const {
 Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
 Ptr = Ptr.getBase();
 continue;
+
+llvm_unreachable("Invalid field type");

tbaederr wrote:

It does have _some_ use in its old place.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


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

>From 5eacd7478d3db7472d5ab983468a441b1f61ad7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Wed, 6 Mar 2024 08:36:52 +0100
Subject: [PATCH 1/2] Integral pointers

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  74 -
 clang/lib/AST/Interp/ByteCodeStmtGen.cpp |   2 +-
 clang/lib/AST/Interp/Descriptor.h|   1 +
 clang/lib/AST/Interp/FunctionPointer.h   |  10 +-
 clang/lib/AST/Interp/Interp.cpp  |   5 +
 clang/lib/AST/Interp/Interp.h|  89 --
 clang/lib/AST/Interp/InterpBlock.cpp |   4 +-
 clang/lib/AST/Interp/Opcodes.td  |  12 +
 clang/lib/AST/Interp/Pointer.cpp | 176 ---
 clang/lib/AST/Interp/Pointer.h   | 366 ---
 clang/lib/AST/Interp/PrimType.h  |   4 +
 clang/test/AST/Interp/c.c|  18 ++
 clang/test/AST/Interp/const-eval.c   | 194 
 13 files changed, 775 insertions(+), 180 deletions(-)
 create mode 100644 clang/test/AST/Interp/const-eval.c

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index d887170cbc5d2d..67e7d89c033d63 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -161,10 +161,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -187,6 +195,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}
+
+return this->emitGetIntPtr(T, Desc, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
   case CK_FunctionToPointerDecay:
@@ -195,13 +231,31 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
   case CK_UserDefinedConversion:
 return this->delegate(SubExpr);
 
-  case CK_BitCast:
+  case CK_BitCast: {
+// Reject bitcasts to atomic types.
 if (CE->getType()->isAtomicType()) {
   if (!this->discard(SubExpr))
 return false;
   return this->emitInvalidCast(CastKind::Reinterpret, CE);
 }
-return this->delegate(SubExpr);
+
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+std::optional FromT = classify(SubExpr->getType());
+std::optional ToT = classifyPrim(CE->getType());
+if (!FromT || !ToT)
+  return false;
+
+assert(isPtrType(*FromT));
+assert(isPtrType(*ToT));
+if (FromT == ToT)
+  return this->delegate(SubExpr);
+
+if (!this->visit(SubExpr))
+  return false;
+return this->emitDecayPtr(*FromT, *ToT, CE);
+  }
 
   case CK_IntegralToBoolean:
   case CK_IntegralCast: {
@@ -233,7 +287,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr 
*CE) {
 if (!this->visit(SubExpr))
   return false;
 
-if (!this->emitNull(PtrT, CE))
+if (!this->emitNull(PtrT, nullptr, CE))
   return false;
 
 return this->emitNE(PtrT, CE);
@@ -445,7 +499,7 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 
   // Pointer arithmetic special case.
   if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
-if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr))
+if (isPtrType(*T) || (isPtrType(*LT) && isPtrType(*RT)))
   return this->VisitPointerArithBinOp(BO);
   }
 
@@ -2296,7 +2350,7 @@ bool ByteCodeExprGen::visitBool(const Expr *E) {
 
   // Convert pointers to bool.
   if (T == PT_Ptr || T == PT_FnPtr) {
-   

[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Timm Baeder via cfe-commits

tbaederr wrote:

FWIW I've been tracking test failures by enabling the new interpreter by 
default and running `ninja check-clang-{ast,sema,semacxx,codegen}` at 
https://tbaederr.github.io/stats/. With this patch, we're down from 281 to 262 
(with only one new failure, `Sema/callingconv-cast.c`).

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -26,60 +26,98 @@ Pointer::Pointer(Block *Pointee)
 Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset)
 : Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
 
-Pointer::Pointer(const Pointer ) : Pointer(P.Pointee, P.Base, P.Offset) {}
+Pointer::Pointer(const Pointer )
+: Offset(P.Offset), PointeeStorage(P.PointeeStorage),
+  StorageKind(P.StorageKind) {
 
-Pointer::Pointer(Pointer &)
-: Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) {
-  if (Pointee)
-Pointee->replacePointer(, this);
+  if (isBlockPointer() && PointeeStorage.BS.Pointee)
+PointeeStorage.BS.Pointee->addPointer(this);
 }
 
 Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
-: Pointee(Pointee), Base(Base), Offset(Offset) {
+: Offset(Offset), StorageKind(Storage::Block) {
   assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
+
+  PointeeStorage.BS = {Pointee, Base};
+
   if (Pointee)
 Pointee->addPointer(this);
 }
 
+Pointer::Pointer(Pointer &)
+: Offset(P.Offset), PointeeStorage(P.PointeeStorage),
+  StorageKind(P.StorageKind) {
+
+  if (StorageKind == Storage::Block && PointeeStorage.BS.Pointee) {
+PointeeStorage.BS.Pointee->replacePointer(, this);
+  }
+}
+
 Pointer::~Pointer() {
-  if (Pointee) {
-Pointee->removePointer(this);
-Pointee->cleanup();
+  if (isIntegralPointer())
+return;
+
+  if (PointeeStorage.BS.Pointee) {
+PointeeStorage.BS.Pointee->removePointer(this);
+PointeeStorage.BS.Pointee->cleanup();
   }
 }
 
 void Pointer::operator=(const Pointer ) {
-  Block *Old = Pointee;
 
-  if (Pointee)
-Pointee->removePointer(this);
+  if (this->isIntegralPointer() && P.isBlockPointer()) {
+  } else {
+assert(P.StorageKind == StorageKind);
+  }

AaronBallman wrote:

```suggestion
  if (!this->isIntegralPointer() || !P.isBlockPointer())
assert(P.StorageKind == StorageKind);
```

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -28,11 +28,26 @@ class Block;
 class DeadBlock;
 class Pointer;
 class Context;
+template  class Integral;
 enum PrimType : unsigned;
 
 class Pointer;
 inline llvm::raw_ostream <<(llvm::raw_ostream , const Pointer );
 
+struct BlockPointer {

AaronBallman wrote:

This is not the first time I've hit this cognitive issue, but `Block` is an 
existing term of art in the compiler and means something totally different from 
how we use it in the interpreter. My very first thought was that this was a 
significant amount of work just to support Objective-C block pointers, why 
aren't we doing the same thing for member pointers, etc. It took me a while to 
realize you mean a descriptor for a chunk of memory.

I don't know if others reviewing the interpreter have hit similar issues with 
"block" or not, so I'm not recommending any changes. But it is something to 
keep in mind when naming stuff.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -172,72 +217,107 @@ class Pointer {
 Adjust = sizeof(InitMapPtr);
   else
 Adjust = sizeof(InlineDescriptor);
-  return Pointer(Pointee, Base, Base + getSize() + Adjust);
+  return Pointer(asBlockPointer().Pointee, asBlockPointer().Base,
+ asBlockPointer().Base + getSize() + Adjust);
 }
 
 // Do not step out of array elements.
-if (Base != Offset)
+if (asBlockPointer().Base != Offset)
   return *this;
 
 // If at base, point to an array of base types.
-if (Base == 0 || Base == sizeof(InlineDescriptor))
-  return Pointer(Pointee, RootPtrMark, 0);
+if (asBlockPointer().Base == 0 ||
+asBlockPointer().Base == sizeof(InlineDescriptor))
+  return Pointer(asBlockPointer().Pointee, RootPtrMark, 0);
 
 // Step into the containing array, if inside one.
-unsigned Next = Base - getInlineDesc()->Offset;
+unsigned Next = asBlockPointer().Base - getInlineDesc()->Offset;
 const Descriptor *Desc =
 Next == 0 ? getDeclDesc() : getDescriptor(Next)->Desc;
 if (!Desc->IsArray)
   return *this;
-return Pointer(Pointee, Next, Offset);
+return Pointer(asBlockPointer().Pointee, Next, Offset);
   }
 
   /// Checks if the pointer is null.
-  bool isZero() const { return Pointee == nullptr; }
+  bool isZero() const {
+if (Offset != 0)
+  return false;
+
+if (isBlockPointer())
+  return asBlockPointer().Pointee == nullptr;
+else if (isIntegralPointer())
+  return asIntPointer().Value == 0;
+llvm_unreachable("zomg");

AaronBallman wrote:

```suggestion
assert(isIntegralPointer() && "expected an integral pointer");
return asIntPointer().Value == 0;
```

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -26,60 +26,98 @@ Pointer::Pointer(Block *Pointee)
 Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset)
 : Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
 
-Pointer::Pointer(const Pointer ) : Pointer(P.Pointee, P.Base, P.Offset) {}
+Pointer::Pointer(const Pointer )
+: Offset(P.Offset), PointeeStorage(P.PointeeStorage),
+  StorageKind(P.StorageKind) {
 
-Pointer::Pointer(Pointer &)
-: Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) {
-  if (Pointee)
-Pointee->replacePointer(, this);
+  if (isBlockPointer() && PointeeStorage.BS.Pointee)
+PointeeStorage.BS.Pointee->addPointer(this);
 }
 
 Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
-: Pointee(Pointee), Base(Base), Offset(Offset) {
+: Offset(Offset), StorageKind(Storage::Block) {
   assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
+
+  PointeeStorage.BS = {Pointee, Base};
+
   if (Pointee)
 Pointee->addPointer(this);
 }
 
+Pointer::Pointer(Pointer &)
+: Offset(P.Offset), PointeeStorage(P.PointeeStorage),
+  StorageKind(P.StorageKind) {
+
+  if (StorageKind == Storage::Block && PointeeStorage.BS.Pointee) {
+PointeeStorage.BS.Pointee->replacePointer(, this);
+  }

AaronBallman wrote:

```suggestion
  if (StorageKind == Storage::Block && PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->replacePointer(, this);
```

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -123,8 +167,9 @@ APValue Pointer::toAPValue() const {
 Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
 Ptr = Ptr.getBase();
 continue;
+
+llvm_unreachable("Invalid field type");

AaronBallman wrote:

Errr... given the unconditional `continue` on the line above, I agree this is 
unreachable... but does this actually help anything?

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -88,6 +126,12 @@ APValue Pointer::toAPValue() const {
   if (isZero())
 return APValue(static_cast(nullptr), CharUnits::Zero(), Path,
/*IsOnePastEnd=*/false, /*IsNullPtr=*/true);
+  if (isIntegralPointer()) {
+return APValue(static_cast(nullptr),
+   CharUnits::fromQuantity(asIntPointer().Value + 
this->Offset),
+   Path,
+   /*IsOnePastEnd=*/false, /*IsNullPtr=*/false);
+  }

AaronBallman wrote:

```suggestion
  if (isIntegralPointer())
return APValue(static_cast(nullptr),
   CharUnits::fromQuantity(asIntPointer().Value + this->Offset),
   Path,
   /*IsOnePastEnd=*/false, /*IsNullPtr=*/false);
```

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -809,9 +809,9 @@ inline bool CmpHelperEQ(InterpState , CodePtr 
OpPC, CompareFn Fn) {
 // element in the same array are NOT equal. They have the same Base value,
 // but a different Offset. This is a pretty rare case, so we fix this here
 // by comparing pointers to the first elements.
-if (!LHS.isDummy() && LHS.isArrayRoot())
+if (!LHS.isZero() && !LHS.isDummy() && LHS.isArrayRoot())
   VL = LHS.atIndex(0).getByteOffset();
-if (!RHS.isDummy() && RHS.isArrayRoot())
+if (!RHS.isDummy() && !RHS.isDummy() && RHS.isArrayRoot())

AaronBallman wrote:

```suggestion
if (!RHS.isZero() && !RHS.isDummy() && RHS.isArrayRoot())
```
Right? (Might be missing test coverage.)

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -2180,6 +2201,14 @@ inline bool GetFnPtr(InterpState , CodePtr OpPC, const 
Function *Func) {
   return true;
 }
 
+template ::T>
+inline bool GetIntPtr(InterpState , CodePtr OpPC, const Descriptor *Desc) {
+  const T  = S.Stk.pop();
+
+  S.Stk.push(static_cast(IntVal), Desc);

AaronBallman wrote:

`uintptr_t` instead?

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -187,6 +195,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}

AaronBallman wrote:

```suggestion
if (std::optional T = classify(PtrType->getPointeeType()))
  Desc = P.createDescriptor(SubExpr, *T);
else if (PtrType->getPointeeType()->isVoidType())
  Desc = nullptr;
else
  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
Descriptor::InlineDescMD, true, false,
/*IsMutable=*/false, nullptr);
```

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -26,60 +26,98 @@ Pointer::Pointer(Block *Pointee)
 Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset)
 : Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
 
-Pointer::Pointer(const Pointer ) : Pointer(P.Pointee, P.Base, P.Offset) {}
+Pointer::Pointer(const Pointer )
+: Offset(P.Offset), PointeeStorage(P.PointeeStorage),
+  StorageKind(P.StorageKind) {
 
-Pointer::Pointer(Pointer &)
-: Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) {
-  if (Pointee)
-Pointee->replacePointer(, this);
+  if (isBlockPointer() && PointeeStorage.BS.Pointee)
+PointeeStorage.BS.Pointee->addPointer(this);
 }
 
 Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
-: Pointee(Pointee), Base(Base), Offset(Offset) {
+: Offset(Offset), StorageKind(Storage::Block) {
   assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
+
+  PointeeStorage.BS = {Pointee, Base};
+
   if (Pointee)
 Pointee->addPointer(this);
 }
 
+Pointer::Pointer(Pointer &)
+: Offset(P.Offset), PointeeStorage(P.PointeeStorage),
+  StorageKind(P.StorageKind) {
+
+  if (StorageKind == Storage::Block && PointeeStorage.BS.Pointee) {
+PointeeStorage.BS.Pointee->replacePointer(, this);
+  }
+}
+
 Pointer::~Pointer() {
-  if (Pointee) {
-Pointee->removePointer(this);
-Pointee->cleanup();
+  if (isIntegralPointer())
+return;
+
+  if (PointeeStorage.BS.Pointee) {
+PointeeStorage.BS.Pointee->removePointer(this);
+PointeeStorage.BS.Pointee->cleanup();
   }
 }
 
 void Pointer::operator=(const Pointer ) {
-  Block *Old = Pointee;
 
-  if (Pointee)
-Pointee->removePointer(this);
+  if (this->isIntegralPointer() && P.isBlockPointer()) {
+  } else {
+assert(P.StorageKind == StorageKind);
+  }
 
-  Offset = P.Offset;
-  Base = P.Base;
+  bool WasBlockPointer = isBlockPointer();
+  StorageKind = P.StorageKind;
+  if (StorageKind == Storage::Block) {
+Block *Old = PointeeStorage.BS.Pointee;
+if (WasBlockPointer && PointeeStorage.BS.Pointee)
+  PointeeStorage.BS.Pointee->removePointer(this);
 
-  Pointee = P.Pointee;
-  if (Pointee)
-Pointee->addPointer(this);
+Offset = P.Offset;
+PointeeStorage.BS = P.PointeeStorage.BS;
+
+if (PointeeStorage.BS.Pointee)
+  PointeeStorage.BS.Pointee->addPointer(this);
 
-  if (Old)
-Old->cleanup();
+if (WasBlockPointer && Old)
+  Old->cleanup();
+
+  } else if (StorageKind == Storage::Int) {
+PointeeStorage.Int = P.PointeeStorage.Int;
+  } else
+assert(false);
 }
 
 void Pointer::operator=(Pointer &) {
-  Block *Old = Pointee;
+  if (this->isIntegralPointer() && P.isBlockPointer()) {
+  } else {
+assert(P.StorageKind == StorageKind);
+  }
 
-  if (Pointee)
-Pointee->removePointer(this);
+  bool WasBlockPointer = isBlockPointer();
+  StorageKind = P.StorageKind;
+  if (StorageKind == Storage::Block) {
+Block *Old = PointeeStorage.BS.Pointee;
+if (WasBlockPointer && PointeeStorage.BS.Pointee)
+  PointeeStorage.BS.Pointee->removePointer(this);
 
-  Offset = P.Offset;
-  Base = P.Base;
+Offset = P.Offset;
+PointeeStorage.BS = P.PointeeStorage.BS;
 
-  Pointee = P.Pointee;
-  if (Pointee)
-Pointee->replacePointer(, this);
+if (PointeeStorage.BS.Pointee)
+  PointeeStorage.BS.Pointee->addPointer(this);
+
+if (WasBlockPointer && Old)
+  Old->cleanup();
 
-  if (Old)
-Old->cleanup();
+  } else if (StorageKind == Storage::Int) {
+PointeeStorage.Int = P.PointeeStorage.Int;
+  } else
+assert(false);

AaronBallman wrote:

```suggestion
  } else {
assert(false);
  }
```
Same suggestion here as above.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -1912,6 +1929,10 @@ inline bool NoRet(InterpState , CodePtr OpPC) {
 
 inline bool NarrowPtr(InterpState , CodePtr OpPC) {
   const Pointer  = S.Stk.pop();
+  if (!S.getLangOpts().CPlusPlus) {
+S.Stk.push(Ptr);

AaronBallman wrote:

Might be a good idea to comment why the C logic is different from the C++ logic.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -1505,12 +1509,17 @@ bool OffsetHelper(InterpState , CodePtr OpPC, const T 
,
 return true;
   }
 
-  if (!CheckNull(S, OpPC, Ptr, CSK_ArrayIndex))
-return false;
+  if (!CheckNull(S, OpPC, Ptr, CSK_ArrayIndex)) {
+// The CheckNul will have emitted a note already, but we only
+// abort in C++, since this is fine in C.
+if (S.getLangOpts().CPlusPlus)
+  return false;
+  }
 
   // Arrays of unknown bounds cannot have pointers into them.
-  if (!CheckArray(S, OpPC, Ptr))
+  if (!CheckArray(S, OpPC, Ptr)) {
 return false;
+  }

AaronBallman wrote:

```suggestion
  if (!CheckArray(S, OpPC, Ptr))
return false;
```

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits

https://github.com/AaronBallman commented:

I think the general direction is pretty reasonable.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits

https://github.com/AaronBallman edited 
https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -53,6 +57,10 @@ class FunctionPointer final {
 return toAPValue().getAsString(Ctx, Func->getDecl()->getType());
   }
 
+  uint32_t getIntegerRepresentation() const {
+return static_cast(reinterpret_cast(Func));
+  }

AaronBallman wrote:

This seems dangerous to me. `Func` is a pointer, so casting to `uintptr_t` 
makes sense, but then casting to a 32-bit value seems likely to cause problems 
due to truncation. Any reason why this shouldn't return a `uintptr_t`?

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Aaron Ballman via cfe-commits


@@ -26,60 +26,98 @@ Pointer::Pointer(Block *Pointee)
 Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset)
 : Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
 
-Pointer::Pointer(const Pointer ) : Pointer(P.Pointee, P.Base, P.Offset) {}
+Pointer::Pointer(const Pointer )
+: Offset(P.Offset), PointeeStorage(P.PointeeStorage),
+  StorageKind(P.StorageKind) {
 
-Pointer::Pointer(Pointer &)
-: Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) {
-  if (Pointee)
-Pointee->replacePointer(, this);
+  if (isBlockPointer() && PointeeStorage.BS.Pointee)
+PointeeStorage.BS.Pointee->addPointer(this);
 }
 
 Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
-: Pointee(Pointee), Base(Base), Offset(Offset) {
+: Offset(Offset), StorageKind(Storage::Block) {
   assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
+
+  PointeeStorage.BS = {Pointee, Base};
+
   if (Pointee)
 Pointee->addPointer(this);
 }
 
+Pointer::Pointer(Pointer &)
+: Offset(P.Offset), PointeeStorage(P.PointeeStorage),
+  StorageKind(P.StorageKind) {
+
+  if (StorageKind == Storage::Block && PointeeStorage.BS.Pointee) {
+PointeeStorage.BS.Pointee->replacePointer(, this);
+  }
+}
+
 Pointer::~Pointer() {
-  if (Pointee) {
-Pointee->removePointer(this);
-Pointee->cleanup();
+  if (isIntegralPointer())
+return;
+
+  if (PointeeStorage.BS.Pointee) {
+PointeeStorage.BS.Pointee->removePointer(this);
+PointeeStorage.BS.Pointee->cleanup();
   }
 }
 
 void Pointer::operator=(const Pointer ) {
-  Block *Old = Pointee;
 
-  if (Pointee)
-Pointee->removePointer(this);
+  if (this->isIntegralPointer() && P.isBlockPointer()) {
+  } else {
+assert(P.StorageKind == StorageKind);
+  }
 
-  Offset = P.Offset;
-  Base = P.Base;
+  bool WasBlockPointer = isBlockPointer();
+  StorageKind = P.StorageKind;
+  if (StorageKind == Storage::Block) {
+Block *Old = PointeeStorage.BS.Pointee;
+if (WasBlockPointer && PointeeStorage.BS.Pointee)
+  PointeeStorage.BS.Pointee->removePointer(this);
 
-  Pointee = P.Pointee;
-  if (Pointee)
-Pointee->addPointer(this);
+Offset = P.Offset;
+PointeeStorage.BS = P.PointeeStorage.BS;
+
+if (PointeeStorage.BS.Pointee)
+  PointeeStorage.BS.Pointee->addPointer(this);
+
+if (WasBlockPointer && Old)
+  Old->cleanup();
 
-  if (Old)
-Old->cleanup();
+  } else if (StorageKind == Storage::Int) {
+PointeeStorage.Int = P.PointeeStorage.Int;
+  } else
+assert(false);

AaronBallman wrote:

```suggestion
  } else {
assert(false);
  }
```
It would be good to add `&& "some useful message"` to this assertion.

https://github.com/llvm/llvm-project/pull/84159
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)


Changes

This turns the current `Pointer` class into a discriminated union of 
`BlockPointer` and `IntPointer`. The former is what `Pointer` currently is 
while the latter is just an integer value and an optional `Descriptor*`.

The `Pointer` then has type check functions like 
`isBlockPointer()`/`isIntegralPointer()`/`asBlockPointer()`/`asIntPointer()`, 
which can be used to access its data.

Right now, the `IntPointer` and `BlockPointer` structs do not have any methods 
of their own and everything is instead implemented in Pointer (like it was 
before) and the functions now just either assert for the right type or decide 
what to do based on it.

This also implements bitcasts by decaying the pointer to an integral pointer.

`test/AST/Interp/const-eval.c` is a new test testing all kinds of stuff related 
to this. It still has a few tests `#ifdef`-ed out but that mostly depends on 
other unimplemented things like `__builtin_constant_p`.

---

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


13 Files Affected:

- (modified) clang/lib/AST/Interp/ByteCodeExprGen.cpp (+61-10) 
- (modified) clang/lib/AST/Interp/ByteCodeStmtGen.cpp (+1-1) 
- (modified) clang/lib/AST/Interp/Descriptor.h (+1) 
- (modified) clang/lib/AST/Interp/FunctionPointer.h (+9-1) 
- (modified) clang/lib/AST/Interp/Interp.cpp (+5) 
- (modified) clang/lib/AST/Interp/Interp.h (+65-24) 
- (modified) clang/lib/AST/Interp/InterpBlock.cpp (+2-2) 
- (modified) clang/lib/AST/Interp/Opcodes.td (+12) 
- (modified) clang/lib/AST/Interp/Pointer.cpp (+133-40) 
- (modified) clang/lib/AST/Interp/Pointer.h (+264-102) 
- (modified) clang/lib/AST/Interp/PrimType.h (+4) 
- (modified) clang/test/AST/Interp/c.c (+18) 
- (added) clang/test/AST/Interp/const-eval.c (+194) 


``diff
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index d887170cbc5d2d..ace571dd6bd821 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -161,10 +161,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -187,6 +195,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}
+
+return this->emitGetIntPtr(T, Desc, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
   case CK_FunctionToPointerDecay:
@@ -195,13 +231,28 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
   case CK_UserDefinedConversion:
 return this->delegate(SubExpr);
 
-  case CK_BitCast:
+  case CK_BitCast: {
+// Reject bitcasts to atomic types.
 if (CE->getType()->isAtomicType()) {
   if (!this->discard(SubExpr))
 return false;
   return this->emitInvalidCast(CastKind::Reinterpret, CE);
 }
-return this->delegate(SubExpr);
+
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+PrimType FromT = classifyPrim(SubExpr->getType());
+PrimType ToT = classifyPrim(CE->getType());
+assert(isPtrType(FromT));
+assert(isPtrType(ToT));
+if (FromT == ToT)
+  return this->delegate(SubExpr);
+
+if (!this->visit(SubExpr))
+  return false;
+return this->emitDecayPtr(FromT, ToT, CE);
+  }
 
   case CK_IntegralToBoolean:
   case CK_IntegralCast: {
@@ -233,7 +284,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr 
*CE) {
 

[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-06 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/84159

This turns the current `Pointer` class into a discriminated union of 
`BlockPointer` and `IntPointer`. The former is what `Pointer` currently is 
while the latter is just an integer value and an optional `Descriptor*`.

The `Pointer` then has type check functions like 
`isBlockPointer()`/`isIntegralPointer()`/`asBlockPointer()`/`asIntPointer()`, 
which can be used to access its data.

Right now, the `IntPointer` and `BlockPointer` structs do not have any methods 
of their own and everything is instead implemented in Pointer (like it was 
before) and the functions now just either assert for the right type or decide 
what to do based on it.

This also implements bitcasts by decaying the pointer to an integral pointer.

`test/AST/Interp/const-eval.c` is a new test testing all kinds of stuff related 
to this. It still has a few tests `#ifdef`-ed out but that mostly depends on 
other unimplemented things like `__builtin_constant_p`.

>From 0ffa1ff8e909d4fa7a324b3623348fac9969572f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Wed, 6 Mar 2024 08:36:52 +0100
Subject: [PATCH] Integral pointers

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  71 -
 clang/lib/AST/Interp/ByteCodeStmtGen.cpp |   2 +-
 clang/lib/AST/Interp/Descriptor.h|   1 +
 clang/lib/AST/Interp/FunctionPointer.h   |  10 +-
 clang/lib/AST/Interp/Interp.cpp  |   5 +
 clang/lib/AST/Interp/Interp.h|  89 --
 clang/lib/AST/Interp/InterpBlock.cpp |   4 +-
 clang/lib/AST/Interp/Opcodes.td  |  12 +
 clang/lib/AST/Interp/Pointer.cpp | 173 ---
 clang/lib/AST/Interp/Pointer.h   | 366 ---
 clang/lib/AST/Interp/PrimType.h  |   4 +
 clang/test/AST/Interp/c.c|  18 ++
 clang/test/AST/Interp/const-eval.c   | 194 
 13 files changed, 769 insertions(+), 180 deletions(-)
 create mode 100644 clang/test/AST/Interp/const-eval.c

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index d887170cbc5d2d..ace571dd6bd821 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -161,10 +161,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -187,6 +195,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}
+
+return this->emitGetIntPtr(T, Desc, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
   case CK_FunctionToPointerDecay:
@@ -195,13 +231,28 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
   case CK_UserDefinedConversion:
 return this->delegate(SubExpr);
 
-  case CK_BitCast:
+  case CK_BitCast: {
+// Reject bitcasts to atomic types.
 if (CE->getType()->isAtomicType()) {
   if (!this->discard(SubExpr))
 return false;
   return this->emitInvalidCast(CastKind::Reinterpret, CE);
 }
-return this->delegate(SubExpr);
+
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+PrimType FromT = classifyPrim(SubExpr->getType());
+PrimType ToT = classifyPrim(CE->getType());
+assert(isPtrType(FromT));
+assert(isPtrType(ToT));
+if (FromT == ToT)
+  return this->delegate(SubExpr);
+
+if (!this->visit(SubExpr))
+  return false;
+return this->emitDecayPtr(FromT, ToT, CE);
+  }
 
   case