[PATCH] D157825: [clang] Implement constexpr bit_cast for vectors

Joey Rabil via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 13 14:03:49 PDT 2023


DaPorkchop_ created this revision.
DaPorkchop_ added a project: clang.
Herald added a project: All.
DaPorkchop_ requested review of this revision.
Herald added a subscriber: cfe-commits.

This makes __builtin_bit_cast support converting to and from vector types in a constexpr context.

Without this patch, attempting to use `std::bit_cast` with a vector type will fail to compile with a message such as:  
`constexpr bit_cast involving type '__attribute__((__vector_size__(4 * sizeof(int)))) int const' (vector of 4 'int' values) is not yet supported`


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157825

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp


Index: clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
===================================================================
--- clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
+++ clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
@@ -463,3 +463,19 @@
 static_assert(round_trip<__int128_t>(34.0L));
 #endif
 }
+
+namespace test_vector {
+
+typedef unsigned uint2 __attribute__((vector_size(2 * sizeof(unsigned))));
+typedef char byte8 __attribute__((vector_size(sizeof(unsigned long long))));
+
+constexpr uint2 test_vector = { 0x0C05FEFE, 0xCAFEBABE };
+
+static_assert(bit_cast<unsigned long long>(test_vector) == (LITTLE_END
+                                                                ? 0xCAFEBABE0C05FEFE
+                                                                : 0x0C05FEFECAFEBABE), "");
+
+static_assert(round_trip<uint2>(0xCAFEBABE0C05FEFEULL), "");
+static_assert(round_trip<byte8>(0xCAFEBABE0C05FEFEULL), "");
+
+}
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -6990,10 +6990,11 @@
       return visitArray(Val, Ty, Offset);
     case APValue::Struct:
       return visitRecord(Val, Ty, Offset);
+    case APValue::Vector:
+      return visitVector(Val, Ty, Offset);
 
     case APValue::ComplexInt:
     case APValue::ComplexFloat:
-    case APValue::Vector:
     case APValue::FixedPoint:
       // FIXME: We should support these.
 
@@ -7080,6 +7081,21 @@
     return true;
   }
 
+  bool visitVector(const APValue &Val, QualType Ty, CharUnits Offset) {
+    const auto *VT = Ty->castAs<VectorType>();
+
+    CharUnits ElemWidth = Info.Ctx.getTypeSizeInChars(VT->getElementType());
+    unsigned VectorLength = Val.getVectorLength();
+    // Visit each of the vector elements
+    for (unsigned I = 0; I != VectorLength; ++I) {
+      const APValue &SubObj = Val.getVectorElt(I);
+      if (!visit(SubObj, VT->getElementType(), Offset + I * ElemWidth))
+        return false;
+    }
+
+    return true;
+  }
+
   bool visitInt(const APSInt &Val, QualType Ty, CharUnits Offset) {
     APSInt AdjustedVal = Val;
     unsigned Width = AdjustedVal.getBitWidth();
@@ -7289,6 +7305,22 @@
     return ArrayValue;
   }
 
+  std::optional<APValue> visit(const VectorType *Ty, CharUnits Offset) {
+    size_t NumElements = Ty->getNumElements();
+    CharUnits ElementWidth = Info.Ctx.getTypeSizeInChars(Ty->getElementType());
+
+    SmallVector<APValue, 4> Elts;
+    for (size_t I = 0; I != NumElements; ++I) {
+      std::optional<APValue> ElementValue =
+          visitType(Ty->getElementType(), Offset + I * ElementWidth);
+      if (!ElementValue)
+        return std::nullopt;
+      Elts.push_back(std::move(*ElementValue));
+    }
+
+    return APValue(Elts.data(), Elts.size());
+  }
+
   std::optional<APValue> visit(const Type *Ty, CharUnits Offset) {
     return unsupportedType(QualType(Ty, 0));
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D157825.549754.patch
Type: text/x-patch
Size: 2965 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230813/0a25fca0/attachment.bin>


More information about the cfe-commits mailing list