Skip to content

[clang][bytecode] Support bitcasting into float fields #114825

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 5, 2024

Conversation

tbaederr
Copy link
Contributor

@tbaederr tbaederr commented Nov 4, 2024

No description provided.

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

llvmbot commented Nov 4, 2024

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

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

4 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Compiler.cpp (+1-1)
  • (modified) clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp (+19-3)
  • (modified) clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp (+10-3)
  • (modified) clang/test/AST/ByteCode/builtin-bit-cast.cpp (+19)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 35116952901684..396213c7b2ae0e 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2735,7 +2735,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
       InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
       if (!this->emitGetPtrLocal(*LocalIndex, E))
         return false;
-      return this->visitInitializer(SubExpr);
+      return this->visitInitializer(SubExpr) && this->emitFinishInit(E);
     }
   }
   return false;
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index dd02eb25c3fa1f..e1de151af3e021 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -397,19 +397,35 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
                       /*ReturnOnUninit=*/false);
 
   // Now read the values out of the buffer again and into ToPtr.
+  const ASTContext &ASTCtx = S.getASTContext();
   size_t BitOffset = 0;
   bool Success = enumeratePointerFields(
       ToPtr, S.getContext(),
       [&](const Pointer &P, PrimType T, size_t _) -> bool {
-        BITCAST_TYPE_SWITCH_FIXED_SIZE(T, {
-          T &Val = P.deref<T>();
+        if (T == PT_Float) {
+          CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType());
+          const auto &Semantics = ASTCtx.getFloatTypeSemantics(P.getType());
+          unsigned NumBits = llvm::APFloatBase::getSizeInBits(Semantics);
+          assert(NumBits % 8 == 0);
+          assert(NumBits <= ASTCtx.toBits(ObjectReprChars));
+          std::byte *M = Buffer.getBytes(BitOffset);
+
+          if (llvm::sys::IsBigEndianHost)
+            swapBytes(M, NumBits / 8);
 
+          P.deref<Floating>() = Floating::bitcastFromMemory(M, Semantics);
+          P.initialize();
+          BitOffset += ASTCtx.toBits(ObjectReprChars);
+          return true;
+        }
+
+        BITCAST_TYPE_SWITCH_FIXED_SIZE(T, {
           std::byte *M = Buffer.getBytes(BitOffset);
 
           if (llvm::sys::IsBigEndianHost)
             swapBytes(M, T::bitWidth() / 8);
 
-          Val = T::bitcastFromMemory(M, T::bitWidth());
+          P.deref<T>() = T::bitcastFromMemory(M, T::bitWidth());
           P.initialize();
           BitOffset += T::bitWidth();
         });
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
index 230680ff3ced7d..0929f7cb70b744 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
@@ -45,7 +45,7 @@ struct bytes {
   unsigned char d[16];
 };
 
-// static_assert(round_trip<bytes>(ld), "");
+static_assert(round_trip<bytes>(ld), "");
 
 static_assert(round_trip<long double>(10.0L));
 
@@ -77,10 +77,17 @@ constexpr bytes ld539 = {
   0x8, 0x40, 0x0,  0x0,
   0x0, 0x0,  0x0,  0x0,
 };
-
 constexpr long double fivehundredandthirtynine = 539.0;
-
 static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, "");
+
+struct LD {
+  long double v;
+};
+
+constexpr LD ld2 = __builtin_bit_cast(LD, ld539.d);
+constexpr long double five39 = __builtin_bit_cast(long double, ld539.d);
+static_assert(ld2.v == five39);
+
 #else
 static_assert(round_trip<__int128_t>(34.0L));
 #endif
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
index 50382399eefc9c..0c55155ec64a24 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -467,3 +467,22 @@ struct ref_mem {
 // both-error@+2 {{constexpr variable 'run_ref_mem' must be initialized by a constant expression}}
 // both-note@+1 {{bit_cast from a type with a reference member is not allowed in a constant expression}}
 constexpr intptr_t run_ref_mem = __builtin_bit_cast(intptr_t, ref_mem{global_int});
+
+
+
+
+namespace test_complex {
+  constexpr _Complex unsigned test_int_complex = { 0x0C05FEFE, 0xCAFEBABE };
+  static_assert(round_trip<_Complex unsigned>(0xCAFEBABE0C05FEFEULL), "");
+  static_assert(bit_cast<unsigned long long>(test_int_complex) == (LITTLE_END
+                                                                   ? 0xCAFEBABE0C05FEFE
+                                                                   : 0x0C05FEFECAFEBABE), "");
+  static_assert(sizeof(double) == 2 * sizeof(float));
+  struct TwoFloats { float A; float B; };
+  constexpr _Complex float test_float_complex = {1.0f, 2.0f};
+  constexpr TwoFloats TF = __builtin_bit_cast(TwoFloats, test_float_complex);
+  static_assert(TF.A == 1.0f && TF.B == 2.0f);
+
+  constexpr double D = __builtin_bit_cast(double, test_float_complex);
+  constexpr int M = __builtin_bit_cast(int, test_int_complex); // both-error {{__builtin_bit_cast source size does not equal destination size}}
+}

@tbaederr tbaederr merged commit 2f13fbf into llvm:main Nov 5, 2024
11 checks passed
PhilippRados pushed a commit to PhilippRados/llvm-project that referenced this pull request Nov 6, 2024
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