43 Bits FullBitWidth,
bool PackedBools)>;
45#define BITCAST_TYPE_SWITCH(Expr, B) \
48 TYPE_SWITCH_CASE(PT_Sint8, B) \
49 TYPE_SWITCH_CASE(PT_Uint8, B) \
50 TYPE_SWITCH_CASE(PT_Sint16, B) \
51 TYPE_SWITCH_CASE(PT_Uint16, B) \
52 TYPE_SWITCH_CASE(PT_Sint32, B) \
53 TYPE_SWITCH_CASE(PT_Uint32, B) \
54 TYPE_SWITCH_CASE(PT_Sint64, B) \
55 TYPE_SWITCH_CASE(PT_Uint64, B) \
56 TYPE_SWITCH_CASE(PT_IntAP, B) \
57 TYPE_SWITCH_CASE(PT_IntAPS, B) \
58 TYPE_SWITCH_CASE(PT_Bool, B) \
60 llvm_unreachable("Unhandled bitcast type"); \
64#define BITCAST_TYPE_SWITCH_FIXED_SIZE(Expr, B) \
67 TYPE_SWITCH_CASE(PT_Sint8, B) \
68 TYPE_SWITCH_CASE(PT_Uint8, B) \
69 TYPE_SWITCH_CASE(PT_Sint16, B) \
70 TYPE_SWITCH_CASE(PT_Uint16, B) \
71 TYPE_SWITCH_CASE(PT_Sint32, B) \
72 TYPE_SWITCH_CASE(PT_Uint32, B) \
73 TYPE_SWITCH_CASE(PT_Sint64, B) \
74 TYPE_SWITCH_CASE(PT_Uint64, B) \
75 TYPE_SWITCH_CASE(PT_Bool, B) \
77 llvm_unreachable("Unhandled bitcast type"); \
84static std::pair<Block *, std::unique_ptr<Descriptor>>
88 const size_t BitWidth = CharWidth * Ctx.
getCharBit();
96 std::unique_ptr<Descriptor> Desc = std::make_unique<Descriptor>(
106 auto *Memory =
new std::byte[
sizeof(
Block) + Desc->getAllocSize()];
113 if (CharWidth == 1) {
114 std::memcpy(&Ptr.elem<
char>(0), S->
getString().data(), StringLength);
117 for (
unsigned I = 0; I <= StringLength; ++I) {
120 Ptr.elem<
T>(I) = T::from(CodePoint, BitWidth););
123 Ptr.initializeAllElements();
124 return std::make_pair(std::move(B), std::move(Desc));
138 return F(P, FieldDesc->
getPrimType(), Offset, FullBitWidth,
152 for (
unsigned I = P.
getIndex(); I != NumElems; ++I) {
153 Result Res = F(P.
atIndex(I), ElemT, Offset, ElemSize, PackedBools);
156 Offset += PackedBools ?
Bits(1) : ElemSize;
157 if (Offset >= BitsToRead)
171 if (Offset >= BitsToRead)
180 if (R->getDecl()->isInvalidDecl())
186 for (
const Record::Field &Fi : R->fields()) {
187 if (Fi.isUnnamedBitField())
194 enumerateData(Elem, Ctx, BitOffset, BitsToRead, F, Initialize);
203 for (
const Record::Base &B : R->bases()) {
212 enumerateData(Elem, Ctx, BitOffset, BitsToRead, F, Initialize);
224 llvm_unreachable(
"Unhandled data type");
237 delete[]
reinterpret_cast<std::byte *
>(B);
264 enum { C_Member, C_Base };
266 auto diag = [&](
int Reason) ->
bool {
268 S.
FFDiag(E, diag::note_constexpr_bit_cast_invalid_type)
269 <<
static_cast<int>(IsToType) << (Reason == E_Reference) << Reason
273 auto note = [&](
int Construct,
QualType NoteType,
275 S.
Note(NoteRange.getBegin(), diag::note_constexpr_bit_cast_invalid_subtype)
276 << NoteType << Construct <<
T.getUnqualifiedType() << NoteRange;
279 auto unsupported = [&](
QualType T) ->
bool {
281 diag::note_constexpr_bit_cast_unsupported_type)
286 T =
T.getCanonicalType();
288 if (
T->isUnionType())
289 return diag(E_Union);
290 if (
T->isPointerType())
291 return diag(E_Pointer);
292 if (
T->isMemberPointerType())
293 return diag(E_MemberPointer);
294 if (
T.isVolatileQualified())
295 return diag(E_Volatile);
298 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
301 return note(C_Base, BS.getType(), BS.getBeginLoc());
304 for (
const FieldDecl *FD : RD->fields()) {
305 if (FD->getType()->isReferenceType())
306 return diag(E_Reference);
308 return note(C_Member, FD->getType(), FD->getSourceRange());
312 if (
T->isArrayType() &&
319 QualType EltTy = VT->getElementType();
320 unsigned NElts = VT->getNumElements();
330 S.
FFDiag(E, diag::note_constexpr_bit_cast_invalid_vector)
340 return unsupported(EltTy);
344 if (
T->isBlockPointerType())
345 return unsupported(
T);
353 bool ReturnOnUninit) {
359 FromPtr, Ctx, Buffer.
size(),
361 bool PackedBools) ->
Result {
362 Bits BitWidth = FullBitWidth;
364 if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
365 BitWidth = Bits(std::min(FD->getBitWidthValue(),
366 (unsigned)FullBitWidth.getQuantity()));
367 else if (T == PT_Bool && PackedBools)
370 if (BitWidth.isZero())
374 if (!P.isInitialized())
378 assert(P.getType()->isNullPtrType());
386 auto Buff = std::make_unique<std::byte[]>(FullBitWidth.
roundToBytes());
393 llvm::APFloatBase::getSizeInBits(F.
getAPFloat().getSemantics()));
394 assert(NumBits.isFullByte());
395 assert(NumBits.getQuantity() <= FullBitWidth.
getQuantity());
399 if (llvm::sys::IsBigEndianHost)
400 swapBytes(Buff.get(), NumBits.roundToBytes());
408 Val.bitcastToMemory(Buff.get());
411 if (llvm::sys::IsBigEndianHost)
416 Buffer.
pushData(Buff.get(), BitOffset, BitWidth, TargetEndianness);
423 std::byte *Buff,
Bits BitWidth,
Bits FullBitWidth,
424 bool &HasIndeterminateBits) {
425 assert(Ptr.isLive());
426 assert(Ptr.isBlockPointer());
428 assert(BitWidth <= FullBitWidth);
448 std::memcpy(Buff, B.get(), BuffSize);
450 if (llvm::sys::IsBigEndianHost)
489 bool PackedBools) ->
Result {
490 QualType PtrType = P.getType();
492 const auto &Semantics = ASTCtx.getFloatTypeSemantics(PtrType);
493 Bits NumBits = Bits(llvm::APFloatBase::getSizeInBits(Semantics));
494 assert(NumBits.isFullByte());
495 assert(NumBits.getQuantity() <= FullBitWidth.getQuantity());
496 auto M = Buffer.copyBits(BitOffset, NumBits, FullBitWidth,
499 if (llvm::sys::IsBigEndianHost)
500 swapBytes(M.get(), NumBits.roundToBytes());
502 Floating R = S.allocFloat(Semantics);
503 Floating::bitcastFromMemory(M.get(), Semantics, &R);
504 P.deref<Floating>() = R;
506 return Result::Success;
511 BitWidth =
Bits(std::min(FD->getBitWidthValue(),
516 BitWidth = FullBitWidth;
522 if (!PtrType->isStdByteType() &&
523 !PtrType->isSpecificBuiltinType(BuiltinType::UChar) &&
524 !PtrType->isSpecificBuiltinType(BuiltinType::Char_U)) {
526 S.
FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
535 auto Memory = Buffer.
copyBits(BitOffset, BitWidth, FullBitWidth,
537 if (llvm::sys::IsBigEndianHost)
554 if (BitWidth.nonZero())
555 P.
deref<
T>() = T::bitcastFromMemory(Memory.get(), T::bitWidth())
556 .truncate(BitWidth.getQuantity());
570 std::variant<Pointer, MemberPointer, FixedPoint, Char<false>,
Char<true>,
596 bool PackedBools) ->
Result {
597 TYPE_SWITCH(T, { Values.push_back(P.deref<T>()); });
606 SrcPtr, S.getContext(), Size,
608 bool PackedBools) ->
Result {
609 TYPE_SWITCH(T, { Values.push_back(P.deref<T>()); });
615 unsigned ValueIndex = 0;
617 DestPtr, S.getContext(), Size,
619 bool PackedBools) ->
Result {
621 P.deref<T>() = std::get<T>(Values[ValueIndex]);
631 assert(ValueIndex == Values.size());
Defines the clang::ASTContext interface.
static Result enumerateData(PtrView P, const Context &Ctx, Bits Offset, Bits BitsToRead, DataFunc F, bool Initialize)
We use this to recursively iterate over all fields and elements of a pointer and extract relevant dat...
#define BITCAST_TYPE_SWITCH_FIXED_SIZE(Expr, B)
Result
Implement __builtin_bit_cast and related operations.
static bool enumeratePointerFields(const Pointer &P, const Context &Ctx, Bits BitsToRead, DataFunc F, bool Initialize)
static std::pair< Block *, std::unique_ptr< Descriptor > > convertToBlockPointer(const Context &Ctx, const StringPointer &SP)
llvm::function_ref< Result(PtrView P, PrimType Ty, Bits BitOffset, Bits FullBitWidth, bool PackedBools)> DataFunc
Used to iterate over pointer fields.
#define BITCAST_TYPE_SWITCH(Expr, B)
std::variant< Pointer, MemberPointer, FixedPoint, Char< false >, Char< true >, Integral< 16, false >, Integral< 16, true >, Integral< 32, false >, Integral< 32, true >, Integral< 64, false >, Integral< 64, true >, IntegralAP< true >, IntegralAP< false >, Boolean, Floating > PrimTypeVariant
static bool CheckBitcastType(InterpState &S, CodePtr OpPC, QualType T, bool IsToType)
#define INT_TYPE_SWITCH_NO_BOOL(Expr, B)
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.
QualType getElementType() const
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.
bool isBitField() const
Determines whether this field is a bitfield.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Represents a struct/union/class.
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...
StringLiteral - This represents a string literal expression, e.g.
unsigned getLength() const
uint32_t getCodeUnit(size_t I) const
Return the code unit at the given position.
StringRef getString() const
unsigned getCharByteWidth() const
bool isLittleEndian() const
bool isPackedVectorBoolType(const ASTContext &ctx) const
const ArrayType * castAsArrayTypeUnsafe() const
A variant of castAs<> for array type which silently discards qualifiers from the outermost type.
bool isRealFloatingType() const
Floating point categories.
Represents a GCC generic vector type.
A memory block, either on the stack or in the heap.
Wrapper around boolean types.
Pointer into the code segment.
Holds all information required to evaluate constexpr code in a module.
unsigned getCharBit() const
Returns CHAR_BIT.
ASTContext & getASTContext() const
Returns the AST context.
OptPrimType classify(QualType T) const
Classifies a type.
unsigned getEvalID() const
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
void bitcastToMemory(std::byte *Buff) const
APFloat getAPFloat() const
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
static void bitcastFromMemory(const std::byte *Src, unsigned BitWidth, IntegralAP *Result)
Wrapper around numeric types.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
const Expr * getExpr(CodePtr PC) const
Context & getContext() const
InterpFrame * Current
The current frame.
T allocAP(unsigned BitWidth)
A pointer to a memory block, live or dead.
int64_t getIndex() const
Returns the index into an array.
bool isStringPointer() const
QualType getType() const
Returns the type of the innermost field.
bool isLive() const
Checks if the pointer is live.
const StringPointer & asStringPointer() const
bool isBlockPointer() const
bool isReadablePointerType() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Structure/Class descriptor.
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
ASTContext & getASTContext() const
const LangOptions & getLangOpts() 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)
Top level wrappers for InstallAPI frontend operations.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ Success
Annotation was successful.
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
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.
QualType getDataType(const ASTContext &Ctx) const
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.
Descriptor used for global variables.
PtrView atField(unsigned Offset) const
const Descriptor * getFieldDesc() const
const FieldDecl * getField() const
PtrView atIndex(unsigned Idx) const
void startLifetime() const
bool isInitialized() const
const StringLiteral * getLiteral() const