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>(
105 auto *Memory =
new std::byte[
sizeof(
Block) + Desc->getAllocSize()];
110 if (CharWidth == 1) {
111 std::memcpy(&Ptr.elem<
char>(0), S->
getString().data(), StringLength);
114 for (
unsigned I = 0; I <= StringLength; ++I) {
117 Ptr.elem<
T>(I) = T::from(CodePoint, BitWidth););
120 Ptr.initializeAllElements();
121 return std::make_pair(std::move(B), std::move(Desc));
135 return F(P, FieldDesc->
getPrimType(), Offset, FullBitWidth,
149 for (
unsigned I = P.
getIndex(); I != NumElems; ++I) {
150 Result Res = F(P.
atIndex(I), ElemT, Offset, ElemSize, PackedBools);
153 Offset += PackedBools ?
Bits(1) : ElemSize;
154 if (Offset >= BitsToRead)
168 if (Offset >= BitsToRead)
177 if (R->getDecl()->isInvalidDecl())
183 for (
const Record::Field &Fi : R->fields()) {
184 if (Fi.isUnnamedBitField())
191 enumerateData(Elem, Ctx, BitOffset, BitsToRead, F, Initialize);
200 for (
const Record::Base &B : R->bases()) {
209 enumerateData(Elem, Ctx, BitOffset, BitsToRead, F, Initialize);
221 llvm_unreachable(
"Unhandled data type");
234 delete[]
reinterpret_cast<std::byte *
>(B);
261 enum { C_Member, C_Base };
263 auto diag = [&](
int Reason) ->
bool {
265 S.
FFDiag(E, diag::note_constexpr_bit_cast_invalid_type)
266 <<
static_cast<int>(IsToType) << (Reason == E_Reference) << Reason
270 auto note = [&](
int Construct,
QualType NoteType,
272 S.
Note(NoteRange.getBegin(), diag::note_constexpr_bit_cast_invalid_subtype)
273 << NoteType << Construct <<
T.getUnqualifiedType() << NoteRange;
276 auto unsupported = [&](
QualType T) ->
bool {
278 diag::note_constexpr_bit_cast_unsupported_type)
283 T =
T.getCanonicalType();
285 if (
T->isUnionType())
286 return diag(E_Union);
287 if (
T->isPointerType())
288 return diag(E_Pointer);
289 if (
T->isMemberPointerType())
290 return diag(E_MemberPointer);
291 if (
T.isVolatileQualified())
292 return diag(E_Volatile);
295 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
298 return note(C_Base, BS.getType(), BS.getBeginLoc());
301 for (
const FieldDecl *FD : RD->fields()) {
302 if (FD->getType()->isReferenceType())
303 return diag(E_Reference);
305 return note(C_Member, FD->getType(), FD->getSourceRange());
309 if (
T->isArrayType() &&
316 QualType EltTy = VT->getElementType();
317 unsigned NElts = VT->getNumElements();
327 diag::note_constexpr_bit_cast_invalid_vector)
337 return unsupported(EltTy);
341 if (
T->isBlockPointerType())
342 return unsupported(
T);
350 bool ReturnOnUninit) {
356 FromPtr, Ctx, Buffer.
size(),
358 bool PackedBools) ->
Result {
359 Bits BitWidth = FullBitWidth;
361 if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
362 BitWidth = Bits(std::min(FD->getBitWidthValue(),
363 (unsigned)FullBitWidth.getQuantity()));
364 else if (T == PT_Bool && PackedBools)
367 if (BitWidth.isZero())
371 if (!P.isInitialized())
375 assert(P.getType()->isNullPtrType());
383 auto Buff = std::make_unique<std::byte[]>(FullBitWidth.
roundToBytes());
390 llvm::APFloatBase::getSizeInBits(F.
getAPFloat().getSemantics()));
391 assert(NumBits.isFullByte());
392 assert(NumBits.getQuantity() <= FullBitWidth.
getQuantity());
396 if (llvm::sys::IsBigEndianHost)
397 swapBytes(Buff.get(), NumBits.roundToBytes());
405 Val.bitcastToMemory(Buff.get());
408 if (llvm::sys::IsBigEndianHost)
413 Buffer.
pushData(Buff.get(), BitOffset, BitWidth, TargetEndianness);
420 std::byte *Buff,
Bits BitWidth,
Bits FullBitWidth,
421 bool &HasIndeterminateBits) {
422 assert(Ptr.isLive());
423 assert(Ptr.isReadablePointerType());
425 assert(BitWidth <= FullBitWidth);
445 std::memcpy(Buff, B.get(), BuffSize);
447 if (llvm::sys::IsBigEndianHost)
486 bool PackedBools) ->
Result {
487 QualType PtrType = P.getType();
489 const auto &Semantics = ASTCtx.getFloatTypeSemantics(PtrType);
490 Bits NumBits = Bits(llvm::APFloatBase::getSizeInBits(Semantics));
491 assert(NumBits.isFullByte());
492 assert(NumBits.getQuantity() <= FullBitWidth.getQuantity());
493 auto M = Buffer.copyBits(BitOffset, NumBits, FullBitWidth,
496 if (llvm::sys::IsBigEndianHost)
497 swapBytes(M.get(), NumBits.roundToBytes());
499 Floating R = S.allocFloat(Semantics);
500 Floating::bitcastFromMemory(M.get(), Semantics, &R);
501 P.deref<Floating>() = R;
503 return Result::Success;
508 BitWidth =
Bits(std::min(FD->getBitWidthValue(),
513 BitWidth = FullBitWidth;
519 if (!PtrType->isStdByteType() &&
520 !PtrType->isSpecificBuiltinType(BuiltinType::UChar) &&
521 !PtrType->isSpecificBuiltinType(BuiltinType::Char_U)) {
523 S.
FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
532 auto Memory = Buffer.
copyBits(BitOffset, BitWidth, FullBitWidth,
534 if (llvm::sys::IsBigEndianHost)
551 if (BitWidth.nonZero())
552 P.
deref<
T>() = T::bitcastFromMemory(Memory.get(), T::bitWidth())
553 .truncate(BitWidth.getQuantity());
567 std::variant<Pointer, MemberPointer, FixedPoint, Char<false>,
Char<true>,
594 bool PackedBools) ->
Result {
595 TYPE_SWITCH(T, { Values.push_back(P.deref<T>()); });
604 SrcPtr, S.getContext(), Size,
606 bool PackedBools) ->
Result {
607 TYPE_SWITCH(T, { Values.push_back(P.deref<T>()); });
613 unsigned ValueIndex = 0;
615 DestPtr, S.getContext(), Size,
617 bool PackedBools) ->
Result {
619 P.deref<T>() = std::get<T>(Values[ValueIndex]);
629 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.
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, Reflect > PrimTypeVariant
#define BITCAST_TYPE_SWITCH(Expr, B)
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.
This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
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, bool Activate, bool Diagnose)
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)
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.
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