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