clang 22.0.0git
InterpBuiltinBitCast.cpp
Go to the documentation of this file.
1//===-------------------- InterpBuiltinBitCast.cpp --------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
9#include "BitcastBuffer.h"
10#include "Boolean.h"
11#include "Context.h"
12#include "Floating.h"
13#include "Integral.h"
14#include "InterpState.h"
15#include "MemberPointer.h"
16#include "Pointer.h"
17#include "Record.h"
21
22#include <variant>
23
24using namespace clang;
25using namespace clang::interp;
26
27/// Implement __builtin_bit_cast and related operations.
28/// Since our internal representation for data is more complex than
29/// something we can simply memcpy or memcmp, we first bitcast all the data
30/// into a buffer, which we then later use to copy the data into the target.
31
32// TODO:
33// - Try to minimize heap allocations.
34// - Optimize the common case of only pushing and pulling full
35// bytes to/from the buffer.
36
37/// Used to iterate over pointer fields.
38using DataFunc =
39 llvm::function_ref<bool(const Pointer &P, PrimType Ty, Bits BitOffset,
40 Bits FullBitWidth, bool PackedBools)>;
41
42#define BITCAST_TYPE_SWITCH(Expr, B) \
43 do { \
44 switch (Expr) { \
45 TYPE_SWITCH_CASE(PT_Sint8, B) \
46 TYPE_SWITCH_CASE(PT_Uint8, B) \
47 TYPE_SWITCH_CASE(PT_Sint16, B) \
48 TYPE_SWITCH_CASE(PT_Uint16, B) \
49 TYPE_SWITCH_CASE(PT_Sint32, B) \
50 TYPE_SWITCH_CASE(PT_Uint32, B) \
51 TYPE_SWITCH_CASE(PT_Sint64, B) \
52 TYPE_SWITCH_CASE(PT_Uint64, B) \
53 TYPE_SWITCH_CASE(PT_IntAP, B) \
54 TYPE_SWITCH_CASE(PT_IntAPS, B) \
55 TYPE_SWITCH_CASE(PT_Bool, B) \
56 default: \
57 llvm_unreachable("Unhandled bitcast type"); \
58 } \
59 } while (0)
60
61#define BITCAST_TYPE_SWITCH_FIXED_SIZE(Expr, B) \
62 do { \
63 switch (Expr) { \
64 TYPE_SWITCH_CASE(PT_Sint8, B) \
65 TYPE_SWITCH_CASE(PT_Uint8, B) \
66 TYPE_SWITCH_CASE(PT_Sint16, B) \
67 TYPE_SWITCH_CASE(PT_Uint16, B) \
68 TYPE_SWITCH_CASE(PT_Sint32, B) \
69 TYPE_SWITCH_CASE(PT_Uint32, B) \
70 TYPE_SWITCH_CASE(PT_Sint64, B) \
71 TYPE_SWITCH_CASE(PT_Uint64, B) \
72 TYPE_SWITCH_CASE(PT_Bool, B) \
73 default: \
74 llvm_unreachable("Unhandled bitcast type"); \
75 } \
76 } while (0)
77
78/// We use this to recursively iterate over all fields and elements of a pointer
79/// and extract relevant data for a bitcast.
80static bool enumerateData(const Pointer &P, const Context &Ctx, Bits Offset,
81 Bits BitsToRead, DataFunc F) {
82 const Descriptor *FieldDesc = P.getFieldDesc();
83 assert(FieldDesc);
84
85 // Primitives.
86 if (FieldDesc->isPrimitive()) {
87 Bits FullBitWidth =
88 Bits(Ctx.getASTContext().getTypeSize(FieldDesc->getType()));
89 return F(P, FieldDesc->getPrimType(), Offset, FullBitWidth,
90 /*PackedBools=*/false);
91 }
92
93 // Primitive arrays.
94 if (FieldDesc->isPrimitiveArray()) {
95 QualType ElemType = FieldDesc->getElemQualType();
96 Bits ElemSize = Bits(Ctx.getASTContext().getTypeSize(ElemType));
97 PrimType ElemT = *Ctx.classify(ElemType);
98 // Special case, since the bools here are packed.
99 bool PackedBools =
100 FieldDesc->getType()->isPackedVectorBoolType(Ctx.getASTContext());
101 unsigned NumElems = FieldDesc->getNumElems();
102 bool Ok = true;
103 for (unsigned I = P.getIndex(); I != NumElems; ++I) {
104 Ok = Ok && F(P.atIndex(I), ElemT, Offset, ElemSize, PackedBools);
105 Offset += PackedBools ? Bits(1) : ElemSize;
106 if (Offset >= BitsToRead)
107 break;
108 }
109 return Ok;
110 }
111
112 // Composite arrays.
113 if (FieldDesc->isCompositeArray()) {
114 QualType ElemType = FieldDesc->getElemQualType();
115 Bits ElemSize = Bits(Ctx.getASTContext().getTypeSize(ElemType));
116 for (unsigned I = P.getIndex(); I != FieldDesc->getNumElems(); ++I) {
117 enumerateData(P.atIndex(I).narrow(), Ctx, Offset, BitsToRead, F);
118 Offset += ElemSize;
119 if (Offset >= BitsToRead)
120 break;
121 }
122 return true;
123 }
124
125 // Records.
126 if (FieldDesc->isRecord()) {
127 const Record *R = FieldDesc->ElemRecord;
128 const ASTRecordLayout &Layout =
129 Ctx.getASTContext().getASTRecordLayout(R->getDecl());
130 bool Ok = true;
131
132 for (const Record::Field &Fi : R->fields()) {
133 if (Fi.isUnnamedBitField())
134 continue;
135 Pointer Elem = P.atField(Fi.Offset);
136 Bits BitOffset =
137 Offset + Bits(Layout.getFieldOffset(Fi.Decl->getFieldIndex()));
138 Ok = Ok && enumerateData(Elem, Ctx, BitOffset, BitsToRead, F);
139 }
140 for (const Record::Base &B : R->bases()) {
141 Pointer Elem = P.atField(B.Offset);
142 CharUnits ByteOffset =
143 Layout.getBaseClassOffset(cast<CXXRecordDecl>(B.Decl));
144 Bits BitOffset = Offset + Bits(Ctx.getASTContext().toBits(ByteOffset));
145 Ok = Ok && enumerateData(Elem, Ctx, BitOffset, BitsToRead, F);
146 // FIXME: We should only (need to) do this when bitcasting OUT of the
147 // buffer, not when copying data into it.
148 if (Ok)
149 Elem.initialize();
150 }
151
152 return Ok;
153 }
154
155 llvm_unreachable("Unhandled data type");
156}
157
158static bool enumeratePointerFields(const Pointer &P, const Context &Ctx,
159 Bits BitsToRead, DataFunc F) {
160 return enumerateData(P, Ctx, Bits::zero(), BitsToRead, F);
161}
162
163// This function is constexpr if and only if To, From, and the types of
164// all subobjects of To and From are types T such that...
165// (3.1) - is_union_v<T> is false;
166// (3.2) - is_pointer_v<T> is false;
167// (3.3) - is_member_pointer_v<T> is false;
168// (3.4) - is_volatile_v<T> is false; and
169// (3.5) - T has no non-static data members of reference type
170//
171// NOTE: This is a version of checkBitCastConstexprEligibilityType() in
172// ExprConstant.cpp.
174 bool IsToType) {
175 enum {
176 E_Union = 0,
177 E_Pointer,
178 E_MemberPointer,
179 E_Volatile,
180 E_Reference,
181 };
182 enum { C_Member, C_Base };
183
184 auto diag = [&](int Reason) -> bool {
185 const Expr *E = S.Current->getExpr(OpPC);
186 S.FFDiag(E, diag::note_constexpr_bit_cast_invalid_type)
187 << static_cast<int>(IsToType) << (Reason == E_Reference) << Reason
188 << E->getSourceRange();
189 return false;
190 };
191 auto note = [&](int Construct, QualType NoteType, SourceRange NoteRange) {
192 S.Note(NoteRange.getBegin(), diag::note_constexpr_bit_cast_invalid_subtype)
193 << NoteType << Construct << T.getUnqualifiedType() << NoteRange;
194 return false;
195 };
196
197 T = T.getCanonicalType();
198
199 if (T->isUnionType())
200 return diag(E_Union);
201 if (T->isPointerType())
202 return diag(E_Pointer);
203 if (T->isMemberPointerType())
204 return diag(E_MemberPointer);
205 if (T.isVolatileQualified())
206 return diag(E_Volatile);
207
208 if (const RecordDecl *RD = T->getAsRecordDecl()) {
209 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
210 for (const CXXBaseSpecifier &BS : CXXRD->bases()) {
211 if (!CheckBitcastType(S, OpPC, BS.getType(), IsToType))
212 return note(C_Base, BS.getType(), BS.getBeginLoc());
213 }
214 }
215 for (const FieldDecl *FD : RD->fields()) {
216 if (FD->getType()->isReferenceType())
217 return diag(E_Reference);
218 if (!CheckBitcastType(S, OpPC, FD->getType(), IsToType))
219 return note(C_Member, FD->getType(), FD->getSourceRange());
220 }
221 }
222
223 if (T->isArrayType() &&
225 IsToType))
226 return false;
227
228 if (const auto *VT = T->getAs<VectorType>()) {
229 const ASTContext &ASTCtx = S.getASTContext();
230 QualType EltTy = VT->getElementType();
231 unsigned NElts = VT->getNumElements();
232 unsigned EltSize =
233 VT->isPackedVectorBoolType(ASTCtx) ? 1 : ASTCtx.getTypeSize(EltTy);
234
235 if ((NElts * EltSize) % ASTCtx.getCharWidth() != 0) {
236 // The vector's size in bits is not a multiple of the target's byte size,
237 // so its layout is unspecified. For now, we'll simply treat these cases
238 // as unsupported (this should only be possible with OpenCL bool vectors
239 // whose element count isn't a multiple of the byte size).
240 const Expr *E = S.Current->getExpr(OpPC);
241 S.FFDiag(E, diag::note_constexpr_bit_cast_invalid_vector)
242 << QualType(VT, 0) << EltSize << NElts << ASTCtx.getCharWidth();
243 return false;
244 }
245
246 if (EltTy->isRealFloatingType() &&
247 &ASTCtx.getFloatTypeSemantics(EltTy) == &APFloat::x87DoubleExtended()) {
248 // The layout for x86_fp80 vectors seems to be handled very inconsistently
249 // by both clang and LLVM, so for now we won't allow bit_casts involving
250 // it in a constexpr context.
251 const Expr *E = S.Current->getExpr(OpPC);
252 S.FFDiag(E, diag::note_constexpr_bit_cast_unsupported_type) << EltTy;
253 return false;
254 }
255 }
256
257 return true;
258}
259
261 const Pointer &FromPtr,
262 BitcastBuffer &Buffer,
263 bool ReturnOnUninit) {
264 const ASTContext &ASTCtx = Ctx.getASTContext();
265 Endian TargetEndianness =
266 ASTCtx.getTargetInfo().isLittleEndian() ? Endian::Little : Endian::Big;
267
269 FromPtr, Ctx, Buffer.size(),
270 [&](const Pointer &P, PrimType T, Bits BitOffset, Bits FullBitWidth,
271 bool PackedBools) -> bool {
272 Bits BitWidth = FullBitWidth;
273
274 if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
275 BitWidth = Bits(std::min(FD->getBitWidthValue(),
276 (unsigned)FullBitWidth.getQuantity()));
277 else if (T == PT_Bool && PackedBools)
278 BitWidth = Bits(1);
279
280 if (BitWidth.isZero())
281 return true;
282
283 // Bits will be left uninitialized and diagnosed when reading.
284 if (!P.isInitialized())
285 return true;
286
287 if (T == PT_Ptr) {
288 assert(P.getType()->isNullPtrType());
289 // Clang treats nullptr_t has having NO bits in its value
290 // representation. So, we accept it here and leave its bits
291 // uninitialized.
292 return true;
293 }
294
295 assert(P.isInitialized());
296 auto Buff = std::make_unique<std::byte[]>(FullBitWidth.roundToBytes());
297 // Work around floating point types that contain unused padding bytes.
298 // This is really just `long double` on x86, which is the only
299 // fundamental type with padding bytes.
300 if (T == PT_Float) {
301 const Floating &F = P.deref<Floating>();
302 Bits NumBits = Bits(
303 llvm::APFloatBase::getSizeInBits(F.getAPFloat().getSemantics()));
304 assert(NumBits.isFullByte());
305 assert(NumBits.getQuantity() <= FullBitWidth.getQuantity());
306 F.bitcastToMemory(Buff.get());
307 // Now, only (maybe) swap the actual size of the float, excluding
308 // the padding bits.
309 if (llvm::sys::IsBigEndianHost)
310 swapBytes(Buff.get(), NumBits.roundToBytes());
311
312 Buffer.markInitialized(BitOffset, NumBits);
313 } else {
314 BITCAST_TYPE_SWITCH(T, { P.deref<T>().bitcastToMemory(Buff.get()); });
315
316 if (llvm::sys::IsBigEndianHost)
317 swapBytes(Buff.get(), FullBitWidth.roundToBytes());
318 Buffer.markInitialized(BitOffset, BitWidth);
319 }
320
321 Buffer.pushData(Buff.get(), BitOffset, BitWidth, TargetEndianness);
322 return true;
323 });
324}
325
327 std::byte *Buff, Bits BitWidth, Bits FullBitWidth,
328 bool &HasIndeterminateBits) {
329 assert(Ptr.isLive());
330 assert(Ptr.isBlockPointer());
331 assert(Buff);
332 assert(BitWidth <= FullBitWidth);
333 assert(FullBitWidth.isFullByte());
334 assert(BitWidth.isFullByte());
335
336 BitcastBuffer Buffer(FullBitWidth);
337 size_t BuffSize = FullBitWidth.roundToBytes();
338 QualType DataType = Ptr.getFieldDesc()->getDataType(S.getASTContext());
339 if (!CheckBitcastType(S, OpPC, DataType, /*IsToType=*/false))
340 return false;
341
342 bool Success = readPointerToBuffer(S.getContext(), Ptr, Buffer,
343 /*ReturnOnUninit=*/false);
344 HasIndeterminateBits = !Buffer.rangeInitialized(Bits::zero(), BitWidth);
345
346 const ASTContext &ASTCtx = S.getASTContext();
347 Endian TargetEndianness =
348 ASTCtx.getTargetInfo().isLittleEndian() ? Endian::Little : Endian::Big;
349 auto B =
350 Buffer.copyBits(Bits::zero(), BitWidth, FullBitWidth, TargetEndianness);
351
352 std::memcpy(Buff, B.get(), BuffSize);
353
354 if (llvm::sys::IsBigEndianHost)
355 swapBytes(Buff, BitWidth.roundToBytes());
356
357 return Success;
358}
360 const Pointer &FromPtr, Pointer &ToPtr) {
361 const ASTContext &ASTCtx = S.getASTContext();
362 CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(ToPtr.getType());
363
364 return DoBitCastPtr(S, OpPC, FromPtr, ToPtr, ObjectReprChars.getQuantity());
365}
366
368 const Pointer &FromPtr, Pointer &ToPtr,
369 size_t Size) {
370 assert(FromPtr.isLive());
371 assert(FromPtr.isBlockPointer());
372 assert(ToPtr.isBlockPointer());
373
374 QualType FromType = FromPtr.getFieldDesc()->getDataType(S.getASTContext());
375 QualType ToType = ToPtr.getFieldDesc()->getDataType(S.getASTContext());
376
377 if (!CheckBitcastType(S, OpPC, ToType, /*IsToType=*/true))
378 return false;
379 if (!CheckBitcastType(S, OpPC, FromType, /*IsToType=*/false))
380 return false;
381
382 const ASTContext &ASTCtx = S.getASTContext();
383 BitcastBuffer Buffer(Bytes(Size).toBits());
384 readPointerToBuffer(S.getContext(), FromPtr, Buffer,
385 /*ReturnOnUninit=*/false);
386
387 // Now read the values out of the buffer again and into ToPtr.
388 Endian TargetEndianness =
389 ASTCtx.getTargetInfo().isLittleEndian() ? Endian::Little : Endian::Big;
391 ToPtr, S.getContext(), Buffer.size(),
392 [&](const Pointer &P, PrimType T, Bits BitOffset, Bits FullBitWidth,
393 bool PackedBools) -> bool {
394 QualType PtrType = P.getType();
395 if (T == PT_Float) {
396 const auto &Semantics = ASTCtx.getFloatTypeSemantics(PtrType);
397 Bits NumBits = Bits(llvm::APFloatBase::getSizeInBits(Semantics));
398 assert(NumBits.isFullByte());
399 assert(NumBits.getQuantity() <= FullBitWidth.getQuantity());
400 auto M = Buffer.copyBits(BitOffset, NumBits, FullBitWidth,
401 TargetEndianness);
402
403 if (llvm::sys::IsBigEndianHost)
404 swapBytes(M.get(), NumBits.roundToBytes());
405
406 Floating R = S.allocFloat(Semantics);
407 Floating::bitcastFromMemory(M.get(), Semantics, &R);
408 P.deref<Floating>() = R;
409 P.initialize();
410 return true;
411 }
412
413 Bits BitWidth;
414 if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
415 BitWidth = Bits(std::min(FD->getBitWidthValue(),
416 (unsigned)FullBitWidth.getQuantity()));
417 else if (T == PT_Bool && PackedBools)
418 BitWidth = Bits(1);
419 else
420 BitWidth = FullBitWidth;
421
422 // If any of the bits are uninitialized, we need to abort unless the
423 // target type is std::byte or unsigned char.
424 bool Initialized = Buffer.rangeInitialized(BitOffset, BitWidth);
425 if (!Initialized) {
426 if (!PtrType->isStdByteType() &&
427 !PtrType->isSpecificBuiltinType(BuiltinType::UChar) &&
428 !PtrType->isSpecificBuiltinType(BuiltinType::Char_U)) {
429 const Expr *E = S.Current->getExpr(OpPC);
430 S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
431 << PtrType << S.getLangOpts().CharIsSigned
432 << E->getSourceRange();
433
434 return false;
435 }
436 return true;
437 }
438
439 auto Memory = Buffer.copyBits(BitOffset, BitWidth, FullBitWidth,
440 TargetEndianness);
441 if (llvm::sys::IsBigEndianHost)
442 swapBytes(Memory.get(), FullBitWidth.roundToBytes());
443
445 if (BitWidth.nonZero())
446 P.deref<T>() = T::bitcastFromMemory(Memory.get(), T::bitWidth())
447 .truncate(BitWidth.getQuantity());
448 else
449 P.deref<T>() = T::zero();
450 });
451 P.initialize();
452 return true;
453 });
454
455 return Success;
456}
457
464
465// NB: This implementation isn't exactly ideal, but:
466// 1) We can't just do a bitcast here since we need to be able to
467// copy pointers.
468// 2) This also needs to handle overlapping regions.
469// 3) We currently have no way of iterating over the fields of a pointer
470// backwards.
472 const Pointer &SrcPtr, const Pointer &DestPtr,
473 Bits Size) {
474 assert(SrcPtr.isBlockPointer());
475 assert(DestPtr.isBlockPointer());
476
478 enumeratePointerFields(SrcPtr, S.getContext(), Size,
479 [&](const Pointer &P, PrimType T, Bits BitOffset,
480 Bits FullBitWidth, bool PackedBools) -> bool {
481 TYPE_SWITCH(T, { Values.push_back(P.deref<T>()); });
482 return true;
483 });
484
485 unsigned ValueIndex = 0;
486 enumeratePointerFields(DestPtr, S.getContext(), Size,
487 [&](const Pointer &P, PrimType T, Bits BitOffset,
488 Bits FullBitWidth, bool PackedBools) -> bool {
489 TYPE_SWITCH(T, {
490 P.deref<T>() = std::get<T>(Values[ValueIndex]);
491 P.initialize();
492 });
493
494 ++ValueIndex;
495 return true;
496 });
497
498 // We should've read all the values into DestPtr.
499 assert(ValueIndex == Values.size());
500
501 return true;
502}
Defines the clang::ASTContext interface.
StringRef P
Expr * E
#define BITCAST_TYPE_SWITCH_FIXED_SIZE(Expr, B)
std::variant< Pointer, FunctionPointer, MemberPointer, FixedPoint, Integral< 8, false >, Integral< 8, 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
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 ...
Definition: ASTContext.h:188
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.
Definition: ASTContext.h:2625
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:859
uint64_t getCharWidth() const
Return the size of the character type, in bits.
Definition: ASTContext.h:2629
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Definition: RecordLayout.h:38
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Definition: RecordLayout.h:201
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
Definition: RecordLayout.h:250
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition: CharUnits.h:185
This represents one expression.
Definition: Expr.h:112
Represents a member of a struct/union/class.
Definition: Decl.h:3157
A (possibly-)qualified type.
Definition: TypeBase.h:937
Represents a struct/union/class.
Definition: Decl.h:4309
ASTContext & getASTContext() const
Definition: Sema.h:918
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...
Definition: Stmt.cpp:334
bool isLittleEndian() const
Definition: TargetInfo.h:1706
bool isPackedVectorBoolType(const ASTContext &ctx) const
Definition: Type.cpp:418
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.h:41
bool isArrayType() const
Definition: TypeBase.h:8679
bool isPointerType() const
Definition: TypeBase.h:8580
bool isMemberPointerType() const
Definition: TypeBase.h:8661
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2324
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isUnionType() const
Definition: Type.cpp:718
Represents a GCC generic vector type.
Definition: TypeBase.h:4191
Wrapper around boolean types.
Definition: Boolean.h:25
Pointer into the code segment.
Definition: Source.h:30
Holds all information required to evaluate constexpr code in a module.
Definition: Context.h:41
Wrapper around fixed point types.
Definition: FixedPoint.h:23
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition: Floating.h:35
void bitcastToMemory(std::byte *Buff) const
Definition: Floating.h:190
APFloat getAPFloat() const
Definition: Floating.h:63
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition: IntegralAP.h:36
Wrapper around numeric types.
Definition: Integral.h:66
Interpreter context.
Definition: InterpState.h:43
A pointer to a memory block, live or dead.
Definition: Pointer.h:90
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:332
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:264
bool isBlockPointer() const
Definition: Pointer.h:464
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition: Pointer.h:322
void initialize() const
Initializes a field.
Definition: Pointer.cpp:483
Structure/Class descriptor.
Definition: Record.h:25
const RecordDecl * getDecl() const
Returns the underlying declaration.
Definition: Record.h:53
llvm::iterator_range< const_base_iter > bases() const
Definition: Record.h:88
llvm::iterator_range< const_field_iter > fields() const
Definition: Record.h:80
#define bool
Definition: gpuintrin.h:32
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.
Definition: PrimType.h:34
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())))
@ Success
Annotation was successful.
const FunctionProtoType * T
Track what bits have been initialized to known values and which ones have indeterminate value.
Definition: BitcastBuffer.h:81
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.
Definition: BitcastBuffer.h:93
void pushData(const std::byte *In, Bits BitOffset, Bits BitWidth, Endian TargetEndianness)
Push BitWidth bits at BitOffset from In into the buffer.
A quantity in bits.
Definition: BitcastBuffer.h:24
size_t roundToBytes() const
Definition: BitcastBuffer.h:30
bool isFullByte() const
Definition: BitcastBuffer.h:32
static Bits zero()
Definition: BitcastBuffer.h:27
size_t getQuantity() const
Definition: BitcastBuffer.h:29
A quantity in bytes.
Definition: BitcastBuffer.h:55
Describes a memory block created by an allocation site.
Definition: Descriptor.h:122
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition: Descriptor.h:249
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition: Descriptor.h:263
QualType getElemQualType() const
Definition: Descriptor.cpp:390
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition: Descriptor.h:256
QualType getType() const
Definition: Descriptor.cpp:371
QualType getDataType(const ASTContext &Ctx) const
Definition: Descriptor.cpp:414
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:254
PrimType getPrimType() const
Definition: Descriptor.h:236
bool isRecord() const
Checks if the descriptor is of a record.
Definition: Descriptor.h:268
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition: Descriptor.h:153