[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-07-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder abandoned this revision.
tbaeder added a comment.

I'm gonna close this, since the new approach is too different.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-06-09 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Yes, FWIW I looked into this again last week and noticed a few unsolved 
problems as well. I'll post a comment once I consider it ready for actual 
review.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-06-09 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman requested changes to this revision.
aaron.ballman added a comment.
This revision now requires changes to proceed.

Making it clear that there's more work here.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-06-09 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

There's still quite a few unaddressed comments, FWIW.




Comment at: clang/lib/AST/Interp/Boolean.h:113
+
+  void bitcastToMemory(std::byte *Buff) { std::memcpy(Buff, , sizeof(V)); }
+




CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-05-12 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 521574.
tbaeder marked 3 inline comments as done.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

Files:
  clang/lib/AST/Interp/Boolean.h
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/Floating.h
  clang/lib/AST/Interp/Integral.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/lib/AST/Interp/PrimType.h
  clang/test/AST/Interp/builtin-bit-cast.cpp
  clang/test/AST/Interp/literals.cpp

Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -96,6 +96,11 @@
 static_assert(p != nullptr, "");
 static_assert(*p == 10, "");
 
+constexpr const void *cp = (void *)p;
+// FIXME: This should be an error in the new interpreter.
+constexpr const int *pm = (int*)cp; // ref-error {{ must be initialized by a constant expression}} \
+// ref-note {{cast from 'const void *' is not allowed}}
+
 constexpr const int* getIntPointer() {
   return 
 }
Index: clang/test/AST/Interp/builtin-bit-cast.cpp
===
--- /dev/null
+++ clang/test/AST/Interp/builtin-bit-cast.cpp
@@ -0,0 +1,228 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify=ref -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+
+
+/// ref-no-diagnostics
+
+
+/// FIXME: This is a version of clang/test/SemaCXX/builtin-bit-cast.cpp with
+///   the currently supported subset of operations. They should *all* be
+///   supported though.
+
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define LITTLE_END 1
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  define LITTLE_END 0
+#else
+#  error "huh?"
+#endif
+
+template  struct is_same {
+  static constexpr bool value = false;
+};
+template  struct is_same {
+  static constexpr bool value = true;
+};
+
+static_assert(sizeof(int) == 4);
+static_assert(sizeof(long long) == 8);
+
+template 
+constexpr To bit_cast(const From ) {
+  static_assert(sizeof(To) == sizeof(From));
+  return __builtin_bit_cast(To, from);
+}
+
+template 
+constexpr bool round_trip(const Init ) {
+  return bit_cast(bit_cast(init)) == init;
+}
+
+static_assert(round_trip((int)-1));
+static_assert(round_trip((int)0x12345678));
+static_assert(round_trip((int)0x87654321));
+static_assert(round_trip((int)0x0C05FEFE));
+static_assert(round_trip((int)0x0C05FEFE));
+
+constexpr unsigned char input[] = {0xCA, 0xFE, 0xBA, 0xBE};
+constexpr unsigned expected = LITTLE_END ? 0xBEBAFECA : 0xCAFEBABE;
+static_assert(bit_cast(input) == expected);
+
+constexpr short S[] = {10, 20};
+constexpr int I = __builtin_bit_cast(int, S);
+static_assert(I == (LITTLE_END ? 1310730 : 655380));
+
+
+struct int_splicer {
+  unsigned x;
+  unsigned y;
+
+  constexpr int_splicer() : x(1), y(2) {}
+  constexpr int_splicer(unsigned x, unsigned y) : x(x), y(y) {}
+
+  constexpr bool operator==(const int_splicer ) const {
+return other.x == x && other.y == y;
+  }
+};
+
+constexpr int_splicer splice(0x0C05FEFE, 0xCAFEBABE);
+
+static_assert(bit_cast(splice) == (LITTLE_END
+   ? 0xCAFEBABE0C05FEFE
+   : 0x0C05FEFECAFEBABE));
+
+constexpr int_splicer IS = bit_cast(0xCAFEBABE0C05FEFE);
+static_assert(bit_cast(0xCAFEBABE0C05FEFE).x == (LITTLE_END
+  ? 0x0C05FEFE
+  : 0xCAFEBABE));
+
+static_assert(round_trip(splice));
+static_assert(round_trip(splice));
+
+struct base2 {
+};
+
+struct base3 {
+  unsigned z;
+  constexpr base3() : z(3) {}
+};
+
+struct bases : int_splicer, base2, base3 {
+  unsigned doublez;
+  constexpr bases() : doublez(4) {}
+};
+
+struct tuple4 {
+  unsigned x, y, z, doublez;
+
+  constexpr bool operator==(tuple4 const ) const {
+return x == other.x && y == other.y &&
+   z == other.z && doublez == other.doublez;
+  }
+};
+constexpr bases b;// = {{1, 2}, {}, {3}, 4};
+constexpr tuple4 t4 = bit_cast(b);
+
+// Regardless of endianness, this should hold:
+static_assert(t4.x == 1);
+static_assert(t4.y == 2);
+static_assert(t4.z == 3);
+static_assert(t4.doublez == 4);
+//static_assert(t4 == tuple4{1, 2, 3, 4});
+static_assert(round_trip(b));
+
+
+namespace WithBases {
+  struct Base {
+

[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-05-11 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

In D144943#4334500 , @tbaeder wrote:

> Pig






Comment at: clang/lib/AST/Interp/ByteCodeExprGen.cpp:74
+  // FIXME: Diagnostics.
+  if (ToType->isArrayType() || ToType->isPointerType())
+return false;

Member pointer types? Unions? volatile-qualified types? There's quite a few 
restrictions here for constexpr contexts.



Comment at: clang/lib/AST/Interp/ByteCodeExprGen.cpp:87
+  if (!ToT) {
+// Conversion to an array or record type.
+return this->emitBitCastPtr(E);

We returned earlier if `ToType` is an array, so this comment is a bit 
suspicious.



Comment at: clang/lib/AST/Interp/ByteCodeExprGen.cpp:101
+  // Conversion to a primitive type. FromType can be another
+  // primitive type, or a record/array.
+  //

All the same restrictions for `ToType` apply to `FromType`: 
http://eel.is/c++draft/bit.cast#3



Comment at: clang/lib/AST/Interp/ByteCodeExprGen.cpp:92
+  // FIXME: Diagnostics.
+  if (*ToT == PT_Ptr)
+return false;

tbaeder wrote:
> One of the problems here is that right now, //all// diagnostics are emitted 
> during interpretation time.
Didn't we early return in this case as well?



Comment at: clang/lib/AST/Interp/Integral.h:179
+
+memcpy(, Buff, sizeof(ReprT));
+return Integral(V);

Consistency with below.



Comment at: clang/lib/AST/Interp/Interp.h:1366
+  size_t BuffSize = APFloat::semanticsSizeInBits(*Sem) / 8;
+  std::byte Buff[BuffSize];
+

tbaeder wrote:
> This is a variable sized array. That needs to go of course, but is the best 
> way to heap allocate? Or can we actually use `alloca` in clang code?
We usually go with:
```
std::vector Buff(BuffSize);
if (!DoBitCast(S, FromPtr, Buff.data(), BuffSize))
  return false;
```



Comment at: clang/lib/AST/Interp/InterpBuiltin.cpp:35
+  std::byte *Buff;
+  unsigned Offset;
+  size_t BuffSize;

We should probably be consistent about using `size_t` in this class so there's 
no chance of size conversion between types.



Comment at: clang/lib/AST/Interp/InterpBuiltin.cpp:33
 
+struct Foo {
+  std::byte *Buff;

tbaeder wrote:
> This needs to be renamed obviously, but I was wondering if this already 
> exists somewhere in the llvm/clang codebase...
I'm not aware of one, but perhaps this exists in LLVM somewhere?



Comment at: clang/lib/AST/Interp/InterpBuiltin.cpp:81
+/// Rotate things around for big endian targets.
+static void fiddleMemory(std::byte *M, size_t N) {
+  for (size_t I = 0; I != (N / 2); ++I)

tbaeder wrote:
> Same here, I feel like this should already be available?
See 
https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Support/SwapByteOrder.h


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-05-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Pig


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-05-01 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-04-21 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 515659.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

Files:
  clang/lib/AST/Interp/Boolean.h
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/Floating.h
  clang/lib/AST/Interp/Integral.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/lib/AST/Interp/PrimType.h
  clang/test/AST/Interp/builtin-bit-cast.cpp
  clang/test/AST/Interp/literals.cpp

Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -90,6 +90,11 @@
 static_assert(p != nullptr, "");
 static_assert(*p == 10, "");
 
+constexpr const void *cp = (void *)p;
+// FIXME: This should be an error in the new interpreter.
+constexpr const int *pm = (int*)cp; // ref-error {{ must be initialized by a constant expression}} \
+// ref-note {{cast from 'const void *' is not allowed}}
+
 constexpr const int* getIntPointer() {
   return 
 }
Index: clang/test/AST/Interp/builtin-bit-cast.cpp
===
--- /dev/null
+++ clang/test/AST/Interp/builtin-bit-cast.cpp
@@ -0,0 +1,228 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify=ref -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+
+
+/// ref-no-diagnostics
+
+
+/// FIXME: This is a version of clang/test/SemaCXX/builtin-bit-cast.cpp with
+///   the currently supported subset of operations. They should *all* be
+///   supported though.
+
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define LITTLE_END 1
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  define LITTLE_END 0
+#else
+#  error "huh?"
+#endif
+
+template  struct is_same {
+  static constexpr bool value = false;
+};
+template  struct is_same {
+  static constexpr bool value = true;
+};
+
+static_assert(sizeof(int) == 4);
+static_assert(sizeof(long long) == 8);
+
+template 
+constexpr To bit_cast(const From ) {
+  static_assert(sizeof(To) == sizeof(From));
+  return __builtin_bit_cast(To, from);
+}
+
+template 
+constexpr bool round_trip(const Init ) {
+  return bit_cast(bit_cast(init)) == init;
+}
+
+static_assert(round_trip((int)-1));
+static_assert(round_trip((int)0x12345678));
+static_assert(round_trip((int)0x87654321));
+static_assert(round_trip((int)0x0C05FEFE));
+static_assert(round_trip((int)0x0C05FEFE));
+
+constexpr unsigned char input[] = {0xCA, 0xFE, 0xBA, 0xBE};
+constexpr unsigned expected = LITTLE_END ? 0xBEBAFECA : 0xCAFEBABE;
+static_assert(bit_cast(input) == expected);
+
+constexpr short S[] = {10, 20};
+constexpr int I = __builtin_bit_cast(int, S);
+static_assert(I == (LITTLE_END ? 1310730 : 655380));
+
+
+struct int_splicer {
+  unsigned x;
+  unsigned y;
+
+  constexpr int_splicer() : x(1), y(2) {}
+  constexpr int_splicer(unsigned x, unsigned y) : x(x), y(y) {}
+
+  constexpr bool operator==(const int_splicer ) const {
+return other.x == x && other.y == y;
+  }
+};
+
+constexpr int_splicer splice(0x0C05FEFE, 0xCAFEBABE);
+
+static_assert(bit_cast(splice) == (LITTLE_END
+   ? 0xCAFEBABE0C05FEFE
+   : 0x0C05FEFECAFEBABE));
+
+constexpr int_splicer IS = bit_cast(0xCAFEBABE0C05FEFE);
+static_assert(bit_cast(0xCAFEBABE0C05FEFE).x == (LITTLE_END
+  ? 0x0C05FEFE
+  : 0xCAFEBABE));
+
+static_assert(round_trip(splice));
+static_assert(round_trip(splice));
+
+struct base2 {
+};
+
+struct base3 {
+  unsigned z;
+  constexpr base3() : z(3) {}
+};
+
+struct bases : int_splicer, base2, base3 {
+  unsigned doublez;
+  constexpr bases() : doublez(4) {}
+};
+
+struct tuple4 {
+  unsigned x, y, z, doublez;
+
+  constexpr bool operator==(tuple4 const ) const {
+return x == other.x && y == other.y &&
+   z == other.z && doublez == other.doublez;
+  }
+};
+constexpr bases b;// = {{1, 2}, {}, {3}, 4};
+constexpr tuple4 t4 = bit_cast(b);
+
+// Regardless of endianness, this should hold:
+static_assert(t4.x == 1);
+static_assert(t4.y == 2);
+static_assert(t4.z == 3);
+static_assert(t4.doublez == 4);
+//static_assert(t4 == tuple4{1, 2, 3, 4});
+static_assert(round_trip(b));
+
+
+namespace WithBases {
+  struct Base {
+char A[3] = {1,2,3};
+  };
+
+  struct A 

[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-04-18 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 514572.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

Files:
  clang/lib/AST/Interp/Boolean.h
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/Floating.h
  clang/lib/AST/Interp/Integral.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/lib/AST/Interp/PrimType.h
  clang/test/AST/Interp/builtin-bit-cast.cpp
  clang/test/AST/Interp/literals.cpp

Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -90,6 +90,11 @@
 static_assert(p != nullptr, "");
 static_assert(*p == 10, "");
 
+constexpr const void *cp = (void *)p;
+// FIXME: This should be an error in the new interpreter.
+constexpr const int *pm = (int*)cp; // ref-error {{ must be initialized by a constant expression}} \
+// ref-note {{cast from 'const void *' is not allowed}}
+
 constexpr const int* getIntPointer() {
   return 
 }
Index: clang/test/AST/Interp/builtin-bit-cast.cpp
===
--- /dev/null
+++ clang/test/AST/Interp/builtin-bit-cast.cpp
@@ -0,0 +1,228 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify=ref -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+
+
+/// ref-no-diagnostics
+
+
+/// FIXME: This is a version of clang/test/SemaCXX/builtin-bit-cast.cpp with
+///   the currently supported subset of operations. They should *all* be
+///   supported though.
+
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define LITTLE_END 1
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  define LITTLE_END 0
+#else
+#  error "huh?"
+#endif
+
+template  struct is_same {
+  static constexpr bool value = false;
+};
+template  struct is_same {
+  static constexpr bool value = true;
+};
+
+static_assert(sizeof(int) == 4);
+static_assert(sizeof(long long) == 8);
+
+template 
+constexpr To bit_cast(const From ) {
+  static_assert(sizeof(To) == sizeof(From));
+  return __builtin_bit_cast(To, from);
+}
+
+template 
+constexpr bool round_trip(const Init ) {
+  return bit_cast(bit_cast(init)) == init;
+}
+
+static_assert(round_trip((int)-1));
+static_assert(round_trip((int)0x12345678));
+static_assert(round_trip((int)0x87654321));
+static_assert(round_trip((int)0x0C05FEFE));
+static_assert(round_trip((int)0x0C05FEFE));
+
+constexpr unsigned char input[] = {0xCA, 0xFE, 0xBA, 0xBE};
+constexpr unsigned expected = LITTLE_END ? 0xBEBAFECA : 0xCAFEBABE;
+static_assert(bit_cast(input) == expected);
+
+constexpr short S[] = {10, 20};
+constexpr int I = __builtin_bit_cast(int, S);
+static_assert(I == (LITTLE_END ? 1310730 : 655380));
+
+
+struct int_splicer {
+  unsigned x;
+  unsigned y;
+
+  constexpr int_splicer() : x(1), y(2) {}
+  constexpr int_splicer(unsigned x, unsigned y) : x(x), y(y) {}
+
+  constexpr bool operator==(const int_splicer ) const {
+return other.x == x && other.y == y;
+  }
+};
+
+constexpr int_splicer splice(0x0C05FEFE, 0xCAFEBABE);
+
+static_assert(bit_cast(splice) == (LITTLE_END
+   ? 0xCAFEBABE0C05FEFE
+   : 0x0C05FEFECAFEBABE));
+
+constexpr int_splicer IS = bit_cast(0xCAFEBABE0C05FEFE);
+static_assert(bit_cast(0xCAFEBABE0C05FEFE).x == (LITTLE_END
+  ? 0x0C05FEFE
+  : 0xCAFEBABE));
+
+static_assert(round_trip(splice));
+static_assert(round_trip(splice));
+
+struct base2 {
+};
+
+struct base3 {
+  unsigned z;
+  constexpr base3() : z(3) {}
+};
+
+struct bases : int_splicer, base2, base3 {
+  unsigned doublez;
+  constexpr bases() : doublez(4) {}
+};
+
+struct tuple4 {
+  unsigned x, y, z, doublez;
+
+  constexpr bool operator==(tuple4 const ) const {
+return x == other.x && y == other.y &&
+   z == other.z && doublez == other.doublez;
+  }
+};
+constexpr bases b;// = {{1, 2}, {}, {3}, 4};
+constexpr tuple4 t4 = bit_cast(b);
+
+// Regardless of endianness, this should hold:
+static_assert(t4.x == 1);
+static_assert(t4.y == 2);
+static_assert(t4.z == 3);
+static_assert(t4.doublez == 4);
+//static_assert(t4 == tuple4{1, 2, 3, 4});
+static_assert(round_trip(b));
+
+
+namespace WithBases {
+  struct Base {
+char A[3] = {1,2,3};
+  };
+
+  struct A 

[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-04-13 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-04-06 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 511386.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

Files:
  clang/lib/AST/Interp/Boolean.h
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/Floating.h
  clang/lib/AST/Interp/Integral.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/lib/AST/Interp/PrimType.h
  clang/test/AST/Interp/builtin-bit-cast.cpp
  clang/test/AST/Interp/literals.cpp

Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -90,6 +90,11 @@
 static_assert(p != nullptr, "");
 static_assert(*p == 10, "");
 
+constexpr const void *cp = (void *)p;
+// FIXME: This should be an error in the new interpreter.
+constexpr const int *pm = (int*)cp; // ref-error {{ must be initialized by a constant expression}} \
+// ref-note {{cast from 'const void *' is not allowed}}
+
 constexpr const int* getIntPointer() {
   return 
 }
Index: clang/test/AST/Interp/builtin-bit-cast.cpp
===
--- /dev/null
+++ clang/test/AST/Interp/builtin-bit-cast.cpp
@@ -0,0 +1,228 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify=ref -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+
+
+/// ref-no-diagnostics
+
+
+/// FIXME: This is a version of clang/test/SemaCXX/builtin-bit-cast.cpp with
+///   the currently supported subset of operations. They should *all* be
+///   supported though.
+
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define LITTLE_END 1
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  define LITTLE_END 0
+#else
+#  error "huh?"
+#endif
+
+template  struct is_same {
+  static constexpr bool value = false;
+};
+template  struct is_same {
+  static constexpr bool value = true;
+};
+
+static_assert(sizeof(int) == 4);
+static_assert(sizeof(long long) == 8);
+
+template 
+constexpr To bit_cast(const From ) {
+  static_assert(sizeof(To) == sizeof(From));
+  return __builtin_bit_cast(To, from);
+}
+
+template 
+constexpr bool round_trip(const Init ) {
+  return bit_cast(bit_cast(init)) == init;
+}
+
+static_assert(round_trip((int)-1));
+static_assert(round_trip((int)0x12345678));
+static_assert(round_trip((int)0x87654321));
+static_assert(round_trip((int)0x0C05FEFE));
+static_assert(round_trip((int)0x0C05FEFE));
+
+constexpr unsigned char input[] = {0xCA, 0xFE, 0xBA, 0xBE};
+constexpr unsigned expected = LITTLE_END ? 0xBEBAFECA : 0xCAFEBABE;
+static_assert(bit_cast(input) == expected);
+
+constexpr short S[] = {10, 20};
+constexpr int I = __builtin_bit_cast(int, S);
+static_assert(I == (LITTLE_END ? 1310730 : 655380));
+
+
+struct int_splicer {
+  unsigned x;
+  unsigned y;
+
+  constexpr int_splicer() : x(1), y(2) {}
+  constexpr int_splicer(unsigned x, unsigned y) : x(x), y(y) {}
+
+  constexpr bool operator==(const int_splicer ) const {
+return other.x == x && other.y == y;
+  }
+};
+
+constexpr int_splicer splice(0x0C05FEFE, 0xCAFEBABE);
+
+static_assert(bit_cast(splice) == (LITTLE_END
+   ? 0xCAFEBABE0C05FEFE
+   : 0x0C05FEFECAFEBABE));
+
+constexpr int_splicer IS = bit_cast(0xCAFEBABE0C05FEFE);
+static_assert(bit_cast(0xCAFEBABE0C05FEFE).x == (LITTLE_END
+  ? 0x0C05FEFE
+  : 0xCAFEBABE));
+
+static_assert(round_trip(splice));
+static_assert(round_trip(splice));
+
+struct base2 {
+};
+
+struct base3 {
+  unsigned z;
+  constexpr base3() : z(3) {}
+};
+
+struct bases : int_splicer, base2, base3 {
+  unsigned doublez;
+  constexpr bases() : doublez(4) {}
+};
+
+struct tuple4 {
+  unsigned x, y, z, doublez;
+
+  constexpr bool operator==(tuple4 const ) const {
+return x == other.x && y == other.y &&
+   z == other.z && doublez == other.doublez;
+  }
+};
+constexpr bases b;// = {{1, 2}, {}, {3}, 4};
+constexpr tuple4 t4 = bit_cast(b);
+
+// Regardless of endianness, this should hold:
+static_assert(t4.x == 1);
+static_assert(t4.y == 2);
+static_assert(t4.z == 3);
+static_assert(t4.doublez == 4);
+//static_assert(t4 == tuple4{1, 2, 3, 4});
+static_assert(round_trip(b));
+
+
+namespace WithBases {
+  struct Base {
+char A[3] = {1,2,3};
+  };
+
+  struct A 

[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-04-04 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-03-27 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-03-19 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-03-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-02-27 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/ByteCodeExprGen.cpp:92
+  // FIXME: Diagnostics.
+  if (*ToT == PT_Ptr)
+return false;

One of the problems here is that right now, //all// diagnostics are emitted 
during interpretation time.



Comment at: clang/lib/AST/Interp/Interp.h:1366
+  size_t BuffSize = APFloat::semanticsSizeInBits(*Sem) / 8;
+  std::byte Buff[BuffSize];
+

This is a variable sized array. That needs to go of course, but is the best way 
to heap allocate? Or can we actually use `alloca` in clang code?



Comment at: clang/lib/AST/Interp/InterpBuiltin.cpp:33
 
+struct Foo {
+  std::byte *Buff;

This needs to be renamed obviously, but I was wondering if this already exists 
somewhere in the llvm/clang codebase...



Comment at: clang/lib/AST/Interp/InterpBuiltin.cpp:81
+/// Rotate things around for big endian targets.
+static void fiddleMemory(std::byte *M, size_t N) {
+  for (size_t I = 0; I != (N / 2); ++I)

Same here, I feel like this should already be available?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144943/new/

https://reviews.llvm.org/D144943

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144943: [clang][Interp] Implement bitcasts (WIP)

2023-02-27 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafi.ahmad.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This implements bitcasts by traversing the pointer fields at 
interpretation-time, copying them into a buffer and then either creating a new 
primitive value from the buffer, or traversing the destination pointer and 
reading the field values from that buffer.

This is a bit non-idiomatic to the new interpreter since we do so much work at 
interpretation time instead of doing it at compile-time.
I can imagine ways to change this, but it would require bytecode instructions 
that are rather awkward, I think. So this is my attempt at
doing it this way instead.

It's also missing all the eligibility checks for bitcasts of course.
I have also not tested this on a big-endian host, which I definitely need to do 
(is the bit rotation needed if the host is BE //and// the target is BE?).

I'll try to leave a few comments in the diff.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D144943

Files:
  clang/lib/AST/Interp/Boolean.h
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/Floating.h
  clang/lib/AST/Interp/Integral.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/lib/AST/Interp/PrimType.h
  clang/test/AST/Interp/builtin-bit-cast.cpp

Index: clang/test/AST/Interp/builtin-bit-cast.cpp
===
--- /dev/null
+++ clang/test/AST/Interp/builtin-bit-cast.cpp
@@ -0,0 +1,228 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify=ref -std=c++2a -fsyntax-only %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
+
+
+/// ref-no-diagnostics
+
+
+/// FIXME: This is a version of clang/test/SemaCXX/builtin-bit-cast.cpp with
+///   the currently supported subset of operations. They should *all* be
+///   supported though.
+
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define LITTLE_END 1
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  define LITTLE_END 0
+#else
+#  error "huh?"
+#endif
+
+template  struct is_same {
+  static constexpr bool value = false;
+};
+template  struct is_same {
+  static constexpr bool value = true;
+};
+
+static_assert(sizeof(int) == 4);
+static_assert(sizeof(long long) == 8);
+
+template 
+constexpr To bit_cast(const From ) {
+  static_assert(sizeof(To) == sizeof(From));
+  return __builtin_bit_cast(To, from);
+}
+
+template 
+constexpr bool round_trip(const Init ) {
+  return bit_cast(bit_cast(init)) == init;
+}
+
+static_assert(round_trip((int)-1));
+static_assert(round_trip((int)0x12345678));
+static_assert(round_trip((int)0x87654321));
+static_assert(round_trip((int)0x0C05FEFE));
+static_assert(round_trip((int)0x0C05FEFE));
+
+constexpr unsigned char input[] = {0xCA, 0xFE, 0xBA, 0xBE};
+constexpr unsigned expected = LITTLE_END ? 0xBEBAFECA : 0xCAFEBABE;
+static_assert(bit_cast(input) == expected);
+
+constexpr short S[] = {10, 20};
+constexpr int I = __builtin_bit_cast(int, S);
+static_assert(I == (LITTLE_END ? 1310730 : 655380));
+
+
+struct int_splicer {
+  unsigned x;
+  unsigned y;
+
+  constexpr int_splicer() : x(1), y(2) {}
+  constexpr int_splicer(unsigned x, unsigned y) : x(x), y(y) {}
+
+  constexpr bool operator==(const int_splicer ) const {
+return other.x == x && other.y == y;
+  }
+};
+
+constexpr int_splicer splice(0x0C05FEFE, 0xCAFEBABE);
+
+static_assert(bit_cast(splice) == (LITTLE_END
+   ? 0xCAFEBABE0C05FEFE
+   : 0x0C05FEFECAFEBABE));
+
+constexpr int_splicer IS = bit_cast(0xCAFEBABE0C05FEFE);
+static_assert(bit_cast(0xCAFEBABE0C05FEFE).x == (LITTLE_END
+  ? 0x0C05FEFE
+  : 0xCAFEBABE));
+
+static_assert(round_trip(splice));
+static_assert(round_trip(splice));
+
+struct base2 {
+};
+
+struct base3 {
+  unsigned z;
+  constexpr base3() : z(3) {}
+};
+
+struct bases : int_splicer, base2, base3 {
+  unsigned doublez;
+  constexpr bases() : doublez(4) {}
+};
+
+struct tuple4 {
+  unsigned x, y, z, doublez;
+
+  constexpr bool operator==(tuple4 const ) const {
+return x == other.x && y == other.y &&
+   z == other.z && doublez == other.doublez;
+  }
+};
+constexpr bases b;// = {{1, 2}, {}, {3}, 4};