-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][Interp] Implement __builtin_bit_cast #68288
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
Changes from all commits
0472490
0c62a90
4feef2c
7006c2e
1591e2c
c5f20a8
ee8d32d
612d365
5c77f91
afd8a49
2988205
f3a05e4
48c0eeb
2caadff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,10 +9,9 @@ | |
#ifndef LLVM_CLANG_AST_INTERP_BOOLEAN_H | ||
#define LLVM_CLANG_AST_INTERP_BOOLEAN_H | ||
|
||
#include <cstddef> | ||
#include <cstdint> | ||
#include "Integral.h" | ||
#include "clang/AST/APValue.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/AST/ComparisonCategories.h" | ||
#include "llvm/ADT/APSInt.h" | ||
#include "llvm/Support/MathExtras.h" | ||
|
@@ -66,6 +65,12 @@ class Boolean final { | |
Boolean toUnsigned() const { return *this; } | ||
|
||
constexpr static unsigned bitWidth() { return 1; } | ||
constexpr static unsigned objectReprBits() { return 8; } | ||
constexpr static unsigned valueReprBytes(const ASTContext &Ctx) { return 1; } | ||
constexpr static unsigned valueReprBits(const ASTContext &Ctx) { | ||
return 8; | ||
} // FIXME: Is this correct? | ||
|
||
bool isZero() const { return !V; } | ||
bool isMin() const { return isZero(); } | ||
|
||
|
@@ -107,6 +112,14 @@ class Boolean final { | |
return Boolean(!Value.isZero()); | ||
} | ||
|
||
static Boolean bitcastFromMemory(const std::byte *Buff, unsigned BitWidth) { | ||
assert(BitWidth == 8); | ||
bool Val = static_cast<bool>(*Buff); | ||
return Boolean(Val); | ||
} | ||
|
||
void bitcastToMemory(std::byte *Buff) { std::memcpy(Buff, &V, sizeof(V)); } | ||
Comment on lines
+115
to
+121
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a tradeoff to be made, here: booleans are among the primitive types that have padding bits, though I believe them to be by far the most commonly used (other contenders include The wrinkle is something like this: constexpr bool b() {
return std::bit_cast<bool, uint8_t>(0x02);
}
int main() {
if constexpr (b() == 0)
return b();
return 1;
} For that sample, There's another question about whether it's worth giving constexpr auto a = std::bit_cast<uint8_t>(false);
constexpr auto b = std::bit_cast<__int128_t>((long double)0);
constexpr auto c = std::bit_cast<bool>('\x02');
constexpr auto d = std::bit_cast<long double>((__int128_t)~0); Right now, I see two fully consistent interpretations, here (considering both implementation & semantics):
Both are backwards-incompatible changes, though: code that used to compile with the old constant interpreter would fail under the new one. The third choice preserves backwards compatibility by holding |
||
|
||
static Boolean zero() { return from(false); } | ||
|
||
template <typename T> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
|
||
#include "Primitives.h" | ||
#include "clang/AST/APValue.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "llvm/ADT/APFloat.h" | ||
|
||
namespace clang { | ||
|
@@ -84,6 +85,12 @@ class Floating final { | |
} | ||
|
||
unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); } | ||
unsigned objectReprBits() { return F.semanticsSizeInBits(F.getSemantics()); } | ||
|
||
unsigned valueReprBytes(const ASTContext &Ctx) { | ||
return Ctx.toCharUnitsFromBits(F.semanticsSizeInBits(F.getSemantics())) | ||
.getQuantity(); | ||
} | ||
|
||
bool isSigned() const { return true; } | ||
bool isNegative() const { return F.isNegative(); } | ||
|
@@ -134,6 +141,10 @@ class Floating final { | |
|
||
return Floating(APFloat(Sem, API)); | ||
} | ||
void bitcastToMemory(std::byte *Buff) { | ||
llvm::APInt API = F.bitcastToAPInt(); | ||
llvm::StoreIntToMemory(API, (uint8_t *)Buff, bitWidth() / 8); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should that use |
||
} | ||
|
||
// === Serialization support === | ||
size_t bytesToSerialize() const { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://eel.is/c++draft/basic#fundamental-10 -- so it's implementation-defined how many bits are in the value representation; we default to 8 (
llvm-project/clang/lib/Basic/TargetInfo.cpp
Line 72 in 5975002
I think we may need to use
TargetInfo
for these at some point so we're matching the target when constant evaluating on the host. But I think that can happen later.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ctx.getTargetInfo().getBoolWidth()
should do the trick