38 Bits FullBitWidth,
bool PackedBools)>;
40#define BITCAST_TYPE_SWITCH(Expr, B) \
43 TYPE_SWITCH_CASE(PT_Sint8, B) \
44 TYPE_SWITCH_CASE(PT_Uint8, B) \
45 TYPE_SWITCH_CASE(PT_Sint16, B) \
46 TYPE_SWITCH_CASE(PT_Uint16, B) \
47 TYPE_SWITCH_CASE(PT_Sint32, B) \
48 TYPE_SWITCH_CASE(PT_Uint32, B) \
49 TYPE_SWITCH_CASE(PT_Sint64, B) \
50 TYPE_SWITCH_CASE(PT_Uint64, B) \
51 TYPE_SWITCH_CASE(PT_IntAP, B) \
52 TYPE_SWITCH_CASE(PT_IntAPS, B) \
53 TYPE_SWITCH_CASE(PT_Bool, B) \
55 llvm_unreachable("Unhandled bitcast type"); \
59#define BITCAST_TYPE_SWITCH_FIXED_SIZE(Expr, B) \
62 TYPE_SWITCH_CASE(PT_Sint8, B) \
63 TYPE_SWITCH_CASE(PT_Uint8, B) \
64 TYPE_SWITCH_CASE(PT_Sint16, B) \
65 TYPE_SWITCH_CASE(PT_Uint16, B) \
66 TYPE_SWITCH_CASE(PT_Sint32, B) \
67 TYPE_SWITCH_CASE(PT_Uint32, B) \
68 TYPE_SWITCH_CASE(PT_Sint64, B) \
69 TYPE_SWITCH_CASE(PT_Uint64, B) \
70 TYPE_SWITCH_CASE(PT_Bool, B) \
72 llvm_unreachable("Unhandled bitcast type"); \
87 return F(
P, FieldDesc->
getPrimType(), Offset, FullBitWidth,
100 for (
unsigned I =
P.getIndex(); I != NumElems; ++I) {
101 Ok =
Ok && F(
P.atIndex(I), ElemT, Offset, ElemSize, PackedBools);
102 Offset += PackedBools ?
Bits(1) : ElemSize;
103 if (Offset >= BitsToRead)
113 for (
unsigned I = 0; I != FieldDesc->
getNumElems(); ++I) {
116 if (Offset >= BitsToRead)
129 for (
const Record::Field &Fi : R->
fields()) {
130 if (Fi.isUnnamedBitField())
132 Pointer Elem =
P.atField(Fi.Offset);
137 for (
const Record::Base &B : R->
bases()) {
152 llvm_unreachable(
"Unhandled data type");
179 enum { C_Member, C_Base };
181 auto diag = [&](
int Reason) ->
bool {
182 const Expr *
E = S.Current->getExpr(OpPC);
183 S.FFDiag(
E, diag::note_constexpr_bit_cast_invalid_type)
184 <<
static_cast<int>(IsToType) << (Reason == E_Reference) << Reason
189 S.Note(NoteRange.getBegin(), diag::note_constexpr_bit_cast_invalid_subtype)
190 << NoteType << Construct <<
T.getUnqualifiedType() << NoteRange;
194 T =
T.getCanonicalType();
197 return diag(E_Union);
199 return diag(E_Pointer);
201 return diag(E_MemberPointer);
202 if (
T.isVolatileQualified())
203 return diag(E_Volatile);
206 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
209 return note(C_Base, BS.getType(), BS.getBeginLoc());
212 for (
const FieldDecl *FD : RD->fields()) {
213 if (FD->getType()->isReferenceType())
214 return diag(E_Reference);
216 return note(C_Member, FD->getType(), FD->getSourceRange());
227 QualType EltTy = VT->getElementType();
228 unsigned NElts = VT->getNumElements();
237 const Expr *
E = S.Current->getExpr(OpPC);
238 S.FFDiag(
E, diag::note_constexpr_bit_cast_invalid_vector)
248 const Expr *
E = S.Current->getExpr(OpPC);
249 S.FFDiag(
E, diag::note_constexpr_bit_cast_unsupported_type) << EltTy;
260 bool ReturnOnUninit) {
266 FromPtr, Ctx, Buffer.
size(),
268 bool PackedBools) ->
bool {
269 Bits BitWidth = FullBitWidth;
271 if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
272 BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx),
273 (unsigned)FullBitWidth.getQuantity()));
274 else if (T == PT_Bool && PackedBools)
277 if (BitWidth.isZero())
281 if (!P.isInitialized())
285 assert(P.getType()->isNullPtrType());
292 assert(
P.isInitialized());
293 auto Buff = std::make_unique<std::byte[]>(FullBitWidth.
roundToBytes());
300 llvm::APFloatBase::getSizeInBits(F.
getAPFloat().getSemantics()));
301 assert(NumBits.isFullByte());
302 assert(NumBits.getQuantity() <= FullBitWidth.
getQuantity());
306 if (llvm::sys::IsBigEndianHost)
307 swapBytes(Buff.get(), NumBits.roundToBytes());
313 if (llvm::sys::IsBigEndianHost)
318 Buffer.
pushData(Buff.get(), BitOffset, BitWidth, TargetEndianness);
324 std::byte *Buff,
Bits BitWidth,
Bits FullBitWidth,
325 bool &HasIndeterminateBits) {
329 assert(BitWidth <= FullBitWidth);
348 std::memcpy(Buff, B.get(), BuffSize);
350 if (llvm::sys::IsBigEndianHost)
387 ToPtr, S.getContext(), Buffer.
size(),
389 bool PackedBools) ->
bool {
390 QualType PtrType = P.getType();
392 const auto &Semantics = ASTCtx.getFloatTypeSemantics(PtrType);
393 Bits NumBits = Bits(llvm::APFloatBase::getSizeInBits(Semantics));
394 assert(NumBits.isFullByte());
395 assert(NumBits.getQuantity() <= FullBitWidth.getQuantity());
396 auto M = Buffer.copyBits(BitOffset, NumBits, FullBitWidth,
399 if (llvm::sys::IsBigEndianHost)
400 swapBytes(M.get(), NumBits.roundToBytes());
402 P.deref<Floating>() = Floating::bitcastFromMemory(M.get(), Semantics);
408 if (
const FieldDecl *FD =
P.getField(); FD && FD->isBitField())
409 BitWidth =
Bits(std::min(FD->getBitWidthValue(ASTCtx),
414 BitWidth = FullBitWidth;
420 if (!PtrType->isStdByteType() &&
421 !PtrType->isSpecificBuiltinType(BuiltinType::UChar) &&
422 !PtrType->isSpecificBuiltinType(BuiltinType::Char_U)) {
423 const Expr *E = S.Current->getExpr(OpPC);
424 S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
425 << PtrType << S.getLangOpts().CharIsSigned
426 << E->getSourceRange();
433 auto Memory = Buffer.
copyBits(BitOffset, BitWidth, FullBitWidth,
435 if (llvm::sys::IsBigEndianHost)
439 if (BitWidth.nonZero())
440 P.deref<
T>() = T::bitcastFromMemory(Memory.get(), T::bitWidth())
441 .truncate(BitWidth.getQuantity());
443 P.deref<
T>() = T::zero();
463 Bits FullBitWidth,
bool PackedBools) ->
bool {
464 unsigned SrcOffsetDiff =
465 P.getByteOffset() - SrcStartOffset;
468 Pointer(DestPtr.asBlockPointer().Pointee,
469 DestPtr.asBlockPointer().Base,
470 DestStartOffset + SrcOffsetDiff);
473 DestP.deref<T>() = P.deref<T>();
Defines the clang::ASTContext interface.
#define BITCAST_TYPE_SWITCH_FIXED_SIZE(Expr, B)
llvm::function_ref< bool(const Pointer &P, PrimType Ty, Bits BitOffset, Bits FullBitWidth, bool PackedBools)> DataFunc
Implement __builtin_bit_cast and related operations.
#define BITCAST_TYPE_SWITCH(Expr, B)
static bool CheckBitcastType(InterpState &S, CodePtr OpPC, QualType T, bool IsToType)
static bool enumeratePointerFields(const Pointer &P, const Context &Ctx, Bits BitsToRead, DataFunc F)
static bool enumerateData(const Pointer &P, const Context &Ctx, Bits Offset, Bits BitsToRead, DataFunc F)
We use this to recursively iterate over all fields and elements of a pointer and extract relevant dat...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const TargetInfo & getTargetInfo() const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
Represents a base class of a C++ class.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
This represents one expression.
Represents a member of a struct/union/class.
A (possibly-)qualified type.
Represents a struct/union/class.
ASTContext & getASTContext() const
A trivial tuple used to represent a source range.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isLittleEndian() const
bool isPointerType() const
bool isExtVectorBoolType() const
bool isMemberPointerType() const
bool isRealFloatingType() const
Floating point categories.
const T * getAs() const
Member-template getAs<specific type>'.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Represents a GCC generic vector type.
Pointer into the code segment.
Holds all information required to evaluate constexpr code in a module.
ASTContext & getASTContext() const
Returns the AST context.
std::optional< PrimType > classify(QualType T) const
Classifies a type.
const APFloat & getAPFloat() const
void bitcastToMemory(std::byte *Buff) const
A pointer to a memory block, live or dead.
QualType getType() const
Returns the type of the innermost field.
bool isLive() const
Checks if the pointer is live.
uint64_t getByteOffset() const
Returns the byte offset from the start.
bool isBlockPointer() const
void initialize() const
Initializes a field.
Structure/Class descriptor.
const RecordDecl * getDecl() const
Returns the underlying declaration.
llvm::iterator_range< const_base_iter > bases() const
llvm::iterator_range< const_field_iter > fields() const
Defines the clang::TargetInfo interface.
bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr, BitcastBuffer &Buffer, bool ReturnOnUninit)
bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr, Pointer &ToPtr)
PrimType
Enumeration of the primitive types of the VM.
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest)
Copy the contents of Src into Dest.
bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, std::byte *Buff, Bits BitWidth, Bits FullBitWidth, bool &HasIndeterminateBits)
static void swapBytes(std::byte *M, size_t N)
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
const FunctionProtoType * T
@ Success
Template argument deduction was successful.
Track what bits have been initialized to known values and which ones have indeterminate value.
std::unique_ptr< std::byte[]> copyBits(Bits BitOffset, Bits BitWidth, Bits FullBitWidth, Endian TargetEndianness) const
Copy BitWidth bits at offset BitOffset from the buffer.
void markInitialized(Bits Start, Bits Length)
Marks the bits in the given range as initialized.
bool rangeInitialized(Bits Offset, Bits Length) const
Bits size() const
Returns the buffer size in bits.
void pushData(const std::byte *In, Bits BitOffset, Bits BitWidth, Endian TargetEndianness)
Push BitWidth bits at BitOffset from In into the buffer.
size_t roundToBytes() const
size_t getQuantity() const
Describes a memory block created by an allocation site.
unsigned getNumElems() const
Returns the number of elements stored in the block.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
QualType getElemQualType() const
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
PrimType getPrimType() const
bool isRecord() const
Checks if the descriptor is of a record.
const Record *const ElemRecord
Pointer to the record, if block contains records.