Skip to content

[clang][bytecode] Use bitcasts to cast from integer to vector #117547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 25, 2024

Conversation

tbaederr
Copy link
Contributor

In C, a cast from an integer to a vector is a CK_BitCast. Implement this using the same code we use for __builtin_bit_cast.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Nov 25, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 25, 2024

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

In C, a cast from an integer to a vector is a CK_BitCast. Implement this using the same code we use for __builtin_bit_cast.


Full diff: https://github.com/llvm/llvm-project/pull/117547.diff

2 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Compiler.cpp (+21-2)
  • (modified) clang/test/AST/ByteCode/c23.c (+25-1)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 7cf2519d6a71fb..964df7f069df0d 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -448,6 +448,10 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
 
     QualType SubExprTy = SubExpr->getType();
     std::optional<PrimType> FromT = classify(SubExprTy);
+    // Casts from integer to vectors in C.
+    if (FromT && CE->getType()->isVectorType())
+      return this->emitBuiltinBitCast(CE);
+
     std::optional<PrimType> ToT = classify(CE->getType());
     if (!FromT || !ToT)
       return false;
@@ -6471,8 +6475,23 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
   }
 
   // Get a pointer to the value-to-cast on the stack.
-  if (!this->visit(SubExpr))
-    return false;
+  // For CK_LValueToRValueBitCast, this is always an lvalue and
+  // we later assume it to be one (i.e. a PT_Ptr). However,
+  // we call this function for other utility methods where
+  // a bitcast might be useful, so convert it to a PT_Ptr in that case.
+  if (SubExpr->isLValue()) {
+    if (!this->visit(SubExpr))
+      return false;
+  } else if (std::optional<PrimType> FromT = classify(FromType)) {
+    unsigned TempOffset = allocateLocalPrimitive(
+        SubExpr, *FromT, /*IsConst=*/true, /*IsExtended=*/false);
+    if (!this->visit(SubExpr))
+      return false;
+    if (!this->emitSetLocal(*FromT, TempOffset, E))
+      return false;
+    if (!this->emitGetPtrLocal(TempOffset, E))
+      return false;
+  }
 
   if (!ToT || ToT == PT_Ptr) {
     if (!this->emitBitCastPtr(E))
diff --git a/clang/test/AST/ByteCode/c23.c b/clang/test/AST/ByteCode/c23.c
index f9157e40610cc3..5154d57f6cb9e7 100644
--- a/clang/test/AST/ByteCode/c23.c
+++ b/clang/test/AST/ByteCode/c23.c
@@ -1,5 +1,8 @@
 // RUN: %clang_cc1 -std=c23 -fexperimental-new-constant-interpreter -verify=expected,both %s
 // RUN: %clang_cc1 -std=c23 -verify=ref,both %s
+// RUN: %clang_cc1 -std=c23 -triple=aarch64_be-linux-gnu -fexperimental-new-constant-interpreter -verify=expected,both %s
+// RUN: %clang_cc1 -std=c23 -triple=aarch64_be-linux-gnu -verify=ref,both %s
+
 
 typedef typeof(nullptr) nullptr_t;
 
@@ -23,5 +26,26 @@ char bar() {
   return ((struct S *)buffer)->c;
 }
 
-
 static_assert((nullptr_t){} == 0);
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define LITTLE_END 1
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  define LITTLE_END 0
+#else
+#  error "huh?"
+#endif
+
+typedef unsigned char u8x4_t __attribute__((vector_size(4)));
+constexpr u8x4_t arg1 = (u8x4_t)0xCAFEBABE; // okay
+#if LITTLE_END
+static_assert(arg1[0] == 190);
+static_assert(arg1[1] == 186);
+static_assert(arg1[2] == 254);
+static_assert(arg1[3] == 202);
+#else
+static_assert(arg1[0] == 202);
+static_assert(arg1[1] == 254);
+static_assert(arg1[2] == 186);
+static_assert(arg1[3] == 190);
+#endif

In C, a cast from an integer to a vector is a CK_BitCast. Implement
this using the same code we use for __builtin_bit_cast.
@tbaederr tbaederr merged commit 6f16a8b into llvm:main Nov 25, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants