clang 22.0.0git
Disasm.cpp
Go to the documentation of this file.
1//===--- Disasm.cpp - Disassembler for bytecode functions -------*- 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//===----------------------------------------------------------------------===//
8//
9// Dump method for Function which disassembles the bytecode.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Boolean.h"
14#include "Context.h"
15#include "EvaluationResult.h"
16#include "FixedPoint.h"
17#include "Floating.h"
18#include "Function.h"
19#include "FunctionPointer.h"
20#include "Integral.h"
21#include "IntegralAP.h"
22#include "InterpFrame.h"
23#include "MemberPointer.h"
24#include "Opcode.h"
25#include "PrimType.h"
26#include "Program.h"
28#include "clang/AST/DeclCXX.h"
29#include "clang/AST/ExprCXX.h"
30#include "llvm/Support/Compiler.h"
31
32using namespace clang;
33using namespace clang::interp;
34
35template <typename T>
36inline static std::string printArg(Program &P, CodePtr &OpPC) {
37 if constexpr (std::is_pointer_v<T>) {
38 uint32_t ID = OpPC.read<uint32_t>();
39 std::string Result;
40 llvm::raw_string_ostream SS(Result);
41 SS << reinterpret_cast<T>(P.getNativePointer(ID));
42 return Result;
43 } else {
44 std::string Result;
45 llvm::raw_string_ostream SS(Result);
46 auto Arg = OpPC.read<T>();
47 SS << Arg;
48 return Result;
49 }
50}
51
52template <> inline std::string printArg<Floating>(Program &P, CodePtr &OpPC) {
53 auto Sem = Floating::deserializeSemantics(*OpPC);
54
55 unsigned BitWidth = llvm::APFloatBase::semanticsSizeInBits(
56 llvm::APFloatBase::EnumToSemantics(Sem));
57 auto Memory =
58 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
59 Floating Result(Memory.get(), Sem);
60 Floating::deserialize(*OpPC, &Result);
61
62 OpPC += align(Result.bytesToSerialize());
63
64 std::string S;
65 llvm::raw_string_ostream SS(S);
66 SS << std::move(Result);
67 return S;
68}
69
70template <>
71inline std::string printArg<IntegralAP<false>>(Program &P, CodePtr &OpPC) {
72 using T = IntegralAP<false>;
73 uint32_t BitWidth = T::deserializeSize(*OpPC);
74 auto Memory =
75 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
76
77 T Result(Memory.get(), BitWidth);
78 T::deserialize(*OpPC, &Result);
79
80 OpPC += align(Result.bytesToSerialize());
81
82 std::string Str;
83 llvm::raw_string_ostream SS(Str);
84 SS << std::move(Result);
85 return Str;
86}
87
88template <>
89inline std::string printArg<IntegralAP<true>>(Program &P, CodePtr &OpPC) {
90 using T = IntegralAP<true>;
91 uint32_t BitWidth = T::deserializeSize(*OpPC);
92 auto Memory =
93 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
94
95 T Result(Memory.get(), BitWidth);
96 T::deserialize(*OpPC, &Result);
97
98 OpPC += align(Result.bytesToSerialize());
99
100 std::string Str;
101 llvm::raw_string_ostream SS(Str);
102 SS << std::move(Result);
103 return Str;
104}
105
106template <> inline std::string printArg<FixedPoint>(Program &P, CodePtr &OpPC) {
107 auto F = FixedPoint::deserialize(*OpPC);
108 OpPC += align(F.bytesToSerialize());
109
110 std::string Result;
111 llvm::raw_string_ostream SS(Result);
112 SS << std::move(F);
113 return Result;
114}
115
116static bool isJumpOpcode(Opcode Op) {
117 return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt;
118}
119
120static size_t getNumDisplayWidth(size_t N) {
121 unsigned L = 1u, M = 10u;
122 while (M <= N && ++L != std::numeric_limits<size_t>::digits10 + 1)
123 M *= 10u;
124
125 return L;
126}
127
128LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }
129
130LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {
131 {
132 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_GREEN, true});
133 OS << getName() << " " << (const void *)this << "\n";
134 }
135 OS << "frame size: " << getFrameSize() << "\n";
136 OS << "arg size: " << getArgSize() << "\n";
137 OS << "rvo: " << hasRVO() << "\n";
138 OS << "this arg: " << hasThisPointer() << "\n";
139
140 struct OpText {
141 size_t Addr;
142 std::string Op;
143 bool IsJump;
145 };
146
147 auto PrintName = [](const char *Name) -> std::string {
148 return std::string(Name);
149 };
150
152 size_t LongestAddr = 0;
153 size_t LongestOp = 0;
154
155 for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
156 size_t Addr = PC - Start;
157 OpText Text;
158 auto Op = PC.read<Opcode>();
159 Text.Addr = Addr;
160 Text.IsJump = isJumpOpcode(Op);
161 switch (Op) {
162#define GET_DISASM
163#include "Opcodes.inc"
164#undef GET_DISASM
165 }
166 Code.push_back(Text);
167 LongestOp = std::max(Text.Op.size(), LongestOp);
168 LongestAddr = std::max(getNumDisplayWidth(Addr), LongestAddr);
169 }
170
171 // Record jumps and their targets.
172 struct JmpData {
173 size_t From;
174 size_t To;
175 };
177 for (auto &Text : Code) {
178 if (Text.IsJump)
179 Jumps.push_back({Text.Addr, Text.Addr + std::stoi(Text.Args[0]) +
180 align(sizeof(Opcode)) +
181 align(sizeof(int32_t))});
182 }
183
185 Text.reserve(Code.size());
186 size_t LongestLine = 0;
187 // Print code to a string, one at a time.
188 for (auto C : Code) {
189 std::string Line;
190 llvm::raw_string_ostream LS(Line);
191 LS << C.Addr;
192 LS.indent(LongestAddr - getNumDisplayWidth(C.Addr) + 4);
193 LS << C.Op;
194 LS.indent(LongestOp - C.Op.size() + 4);
195 for (auto &Arg : C.Args) {
196 LS << Arg << ' ';
197 }
198 Text.push_back(Line);
199 LongestLine = std::max(Line.size(), LongestLine);
200 }
201
202 assert(Code.size() == Text.size());
203
204 auto spaces = [](unsigned N) -> std::string {
205 std::string S;
206 for (unsigned I = 0; I != N; ++I)
207 S += ' ';
208 return S;
209 };
210
211 // Now, draw the jump lines.
212 for (auto &J : Jumps) {
213 if (J.To > J.From) {
214 bool FoundStart = false;
215 for (size_t LineIndex = 0; LineIndex != Text.size(); ++LineIndex) {
216 Text[LineIndex] += spaces(LongestLine - Text[LineIndex].size());
217
218 if (Code[LineIndex].Addr == J.From) {
219 Text[LineIndex] += " --+";
220 FoundStart = true;
221 } else if (Code[LineIndex].Addr == J.To) {
222 Text[LineIndex] += " <-+";
223 break;
224 } else if (FoundStart) {
225 Text[LineIndex] += " |";
226 }
227 }
228 LongestLine += 5;
229 } else {
230 bool FoundStart = false;
231 for (ssize_t LineIndex = Text.size() - 1; LineIndex >= 0; --LineIndex) {
232 Text[LineIndex] += spaces(LongestLine - Text[LineIndex].size());
233 if (Code[LineIndex].Addr == J.From) {
234 Text[LineIndex] += " --+";
235 FoundStart = true;
236 } else if (Code[LineIndex].Addr == J.To) {
237 Text[LineIndex] += " <-+";
238 break;
239 } else if (FoundStart) {
240 Text[LineIndex] += " |";
241 }
242 }
243 LongestLine += 5;
244 }
245 }
246
247 for (auto &Line : Text)
248 OS << Line << '\n';
249}
250
251LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }
252
253static const char *primTypeToString(PrimType T) {
254 switch (T) {
255 case PT_Sint8:
256 return "Sint8";
257 case PT_Uint8:
258 return "Uint8";
259 case PT_Sint16:
260 return "Sint16";
261 case PT_Uint16:
262 return "Uint16";
263 case PT_Sint32:
264 return "Sint32";
265 case PT_Uint32:
266 return "Uint32";
267 case PT_Sint64:
268 return "Sint64";
269 case PT_Uint64:
270 return "Uint64";
271 case PT_IntAP:
272 return "IntAP";
273 case PT_IntAPS:
274 return "IntAPS";
275 case PT_Bool:
276 return "Bool";
277 case PT_Float:
278 return "Float";
279 case PT_Ptr:
280 return "Ptr";
281 case PT_MemberPtr:
282 return "MemberPtr";
283 case PT_FixedPoint:
284 return "FixedPoint";
285 }
286 llvm_unreachable("Unhandled PrimType");
287}
288
289LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
290 {
291 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
292 OS << "\n:: Program\n";
293 }
294
295 {
296 ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
297 OS << "Total memory : " << Allocator.getTotalMemory() << " bytes\n";
298 OS << "Global Variables: " << Globals.size() << "\n";
299 }
300 unsigned GI = 0;
301 for (const Global *G : Globals) {
302 const Descriptor *Desc = G->block()->getDescriptor();
303 Pointer GP = getPtrGlobal(GI);
304
305 OS << GI << ": " << (const void *)G->block() << " ";
306 {
307 ColorScope SC(OS, true,
308 GP.isInitialized()
309 ? TerminalColor{llvm::raw_ostream::GREEN, false}
310 : TerminalColor{llvm::raw_ostream::RED, false});
311 OS << (GP.isInitialized() ? "initialized " : "uninitialized ");
312 }
313 Desc->dump(OS);
314
315 if (GP.isInitialized() && Desc->IsTemporary) {
316 if (const auto *MTE =
317 dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->asExpr());
318 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
319 if (const APValue *V =
320 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
321 OS << " (global temporary value: ";
322 {
323 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_MAGENTA, true});
324 std::string VStr;
325 llvm::raw_string_ostream SS(VStr);
326 V->dump(SS, Ctx.getASTContext());
327
328 for (unsigned I = 0; I != VStr.size(); ++I) {
329 if (VStr[I] == '\n')
330 VStr[I] = ' ';
331 }
332 VStr.pop_back(); // Remove the newline (or now space) at the end.
333 OS << VStr;
334 }
335 OS << ')';
336 }
337 }
338 }
339
340 OS << "\n";
341 if (GP.isInitialized() && Desc->isPrimitive() && !G->block()->isDummy()) {
342 OS << " ";
343 {
344 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
345 OS << primTypeToString(Desc->getPrimType()) << " ";
346 }
347 TYPE_SWITCH(Desc->getPrimType(), { GP.deref<T>().print(OS); });
348 OS << "\n";
349 }
350 ++GI;
351 }
352
353 {
354 ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
355 OS << "Functions: " << Funcs.size() << "\n";
356 }
357 for (const auto &Func : Funcs) {
358 Func.second->dump();
359 }
360 for (const auto &Anon : AnonFuncs) {
361 Anon->dump();
362 }
363}
364
365LLVM_DUMP_METHOD void Descriptor::dump() const {
366 dump(llvm::errs());
367 llvm::errs() << '\n';
368}
369
370LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
371 // Source
372 {
373 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
374 if (const auto *ND = dyn_cast_if_present<NamedDecl>(asDecl()))
375 ND->printQualifiedName(OS);
376 else if (asExpr())
377 OS << "Expr " << (const void *)asExpr();
378 }
379
380 // Print a few interesting bits about the descriptor.
381 if (isPrimitiveArray())
382 OS << " primitive-array";
383 else if (isCompositeArray())
384 OS << " composite-array";
385 else if (isUnion())
386 OS << " union";
387 else if (isRecord())
388 OS << " record";
389 else if (isPrimitive())
390 OS << " primitive " << primTypeToString(getPrimType());
391
392 if (isZeroSizeArray())
393 OS << " zero-size-array";
394 else if (isUnknownSizeArray())
395 OS << " unknown-size-array";
396
398 OS << " constexpr-unknown";
399}
400
401/// Dump descriptor, including all valid offsets.
402LLVM_DUMP_METHOD void Descriptor::dumpFull(unsigned Offset,
403 unsigned Indent) const {
404 unsigned Spaces = Indent * 2;
405 llvm::raw_ostream &OS = llvm::errs();
406 OS.indent(Spaces);
407 dump(OS);
408 OS << '\n';
409 OS.indent(Spaces) << "Metadata: " << getMetadataSize() << " bytes\n";
410 OS.indent(Spaces) << "Size: " << getSize() << " bytes\n";
411 OS.indent(Spaces) << "AllocSize: " << getAllocSize() << " bytes\n";
412 Offset += getMetadataSize();
413 if (isCompositeArray()) {
414 OS.indent(Spaces) << "Elements: " << getNumElems() << '\n';
415 unsigned FO = Offset;
416 for (unsigned I = 0; I != getNumElems(); ++I) {
417 FO += sizeof(InlineDescriptor);
418 assert(ElemDesc->getMetadataSize() == 0);
419 OS.indent(Spaces) << "Element " << I << " offset: " << FO << '\n';
420 ElemDesc->dumpFull(FO, Indent + 1);
421
422 FO += ElemDesc->getAllocSize();
423 }
424 } else if (isRecord()) {
425 ElemRecord->dump(OS, Indent + 1, Offset);
426 } else if (isPrimitive()) {
427 } else {
428 }
429
430 OS << '\n';
431}
432
433LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const {
434 {
435 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
436 OS << "InlineDescriptor " << (const void *)this << "\n";
437 }
438 OS << "Offset: " << Offset << "\n";
439 OS << "IsConst: " << IsConst << "\n";
440 OS << "IsInitialized: " << IsInitialized << "\n";
441 OS << "IsBase: " << IsBase << "\n";
442 OS << "IsActive: " << IsActive << "\n";
443 OS << "InUnion: " << InUnion << "\n";
444 OS << "IsFieldMutable: " << IsFieldMutable << "\n";
445 OS << "IsArrayElement: " << IsArrayElement << "\n";
446 OS << "IsConstInMutable: " << IsConstInMutable << '\n';
447 OS << "Desc: ";
448 if (Desc)
449 Desc->dump(OS);
450 else
451 OS << "nullptr";
452 OS << "\n";
453}
454
455LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream &OS,
456 unsigned Indent) const {
457 unsigned Spaces = Indent * 2;
458 {
459 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
460 OS.indent(Spaces);
461 if (getCallee())
462 describe(OS);
463 else
464 OS << "Frame (Depth: " << getDepth() << ")";
465 OS << "\n";
466 }
467 OS.indent(Spaces) << "Function: " << getFunction();
468 if (const Function *F = getFunction()) {
469 OS << " (" << F->getName() << ")";
470 }
471 OS << "\n";
472 OS.indent(Spaces) << "This: " << getThis() << "\n";
473 OS.indent(Spaces) << "RVO: " << getRVOPtr() << "\n";
474 OS.indent(Spaces) << "Depth: " << Depth << "\n";
475 OS.indent(Spaces) << "ArgSize: " << ArgSize << "\n";
476 OS.indent(Spaces) << "Args: " << (void *)Args << "\n";
477 OS.indent(Spaces) << "FrameOffset: " << FrameOffset << "\n";
478 OS.indent(Spaces) << "FrameSize: " << (Func ? Func->getFrameSize() : 0)
479 << "\n";
480
481 for (const InterpFrame *F = this->Caller; F; F = F->Caller) {
482 F->dump(OS, Indent + 1);
483 }
484}
485
486LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
487 unsigned Offset) const {
488 unsigned Indent = Indentation * 2;
489 OS.indent(Indent);
490 {
491 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
492 OS << getName() << "\n";
493 }
494
495 unsigned I = 0;
496 for (const Record::Base &B : bases()) {
497 OS.indent(Indent) << "- Base " << I << ". Offset " << (Offset + B.Offset)
498 << "\n";
499 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
500 ++I;
501 }
502
503 I = 0;
504 for (const Record::Field &F : fields()) {
505 OS.indent(Indent) << "- Field " << I << ": ";
506 {
507 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
508 OS << F.Decl->getName();
509 }
510 OS << ". Offset " << (Offset + F.Offset) << "\n";
511 ++I;
512 }
513
514 I = 0;
515 for (const Record::Base &B : virtual_bases()) {
516 OS.indent(Indent) << "- Virtual Base " << I << ". Offset "
517 << (Offset + B.Offset) << "\n";
518 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
519 ++I;
520 }
521}
522
523LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
524 {
525 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});
526 OS << "Block " << (const void *)this;
527 }
528 OS << " (";
529 Desc->dump(OS);
530 OS << ")\n";
531 unsigned NPointers = 0;
532 for (const Pointer *P = Pointers; P; P = P->asBlockPointer().Next) {
533 ++NPointers;
534 }
535 OS << " EvalID: " << EvalID << '\n';
536 OS << " DeclID: ";
537 if (DeclID)
538 OS << *DeclID << '\n';
539 else
540 OS << "-\n";
541 OS << " Pointers: " << NPointers << "\n";
542 OS << " Dead: " << isDead() << "\n";
543 OS << " Static: " << IsStatic << "\n";
544 OS << " Extern: " << isExtern() << "\n";
545 OS << " Initialized: " << IsInitialized << "\n";
546 OS << " Weak: " << isWeak() << "\n";
547 OS << " Dummy: " << isDummy() << '\n';
548 OS << " Dynamic: " << isDynamic() << "\n";
549}
550
551LLVM_DUMP_METHOD void EvaluationResult::dump() const {
552 auto &OS = llvm::errs();
553
554 if (empty()) {
555 OS << "Empty\n";
556 } else if (isInvalid()) {
557 OS << "Invalid\n";
558 } else {
559 OS << "Value: ";
560#ifndef NDEBUG
561 assert(Ctx);
562 Value.dump(OS, Ctx->getASTContext());
563#endif
564 }
565}
#define V(N, I)
Definition: ASTContext.h:3597
StringRef P
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
std::string printArg< Floating >(Program &P, CodePtr &OpPC)
Definition: Disasm.cpp:52
static const char * primTypeToString(PrimType T)
Definition: Disasm.cpp:253
static size_t getNumDisplayWidth(size_t N)
Definition: Disasm.cpp:120
static bool isJumpOpcode(Opcode Op)
Definition: Disasm.cpp:116
std::string printArg< FixedPoint >(Program &P, CodePtr &OpPC)
Definition: Disasm.cpp:106
static std::string printArg(Program &P, CodePtr &OpPC)
Definition: Disasm.cpp:36
Defines the clang::Expr interface and subclasses for C++ expressions.
StringRef Text
Definition: Format.cpp:3178
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:207
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
void dump() const
Definition: Value.cpp:251
bool isExtern() const
Checks if the block is extern.
Definition: InterpBlock.h:77
bool isDead() const
Definition: InterpBlock.h:85
bool isDynamic() const
Definition: InterpBlock.h:83
void dump() const
Definition: InterpBlock.h:142
bool isDummy() const
Definition: InterpBlock.h:84
bool isWeak() const
Definition: InterpBlock.h:82
Pointer into the code segment.
Definition: Source.h:30
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Definition: Source.h:56
ASTContext & getASTContext() const
Returns the AST context.
Definition: Context.h:74
void dump() const
Dump to stderr.
Definition: Disasm.cpp:551
static FixedPoint deserialize(const std::byte *Buff)
Definition: FixedPoint.h:108
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition: Floating.h:35
static llvm::APFloatBase::Semantics deserializeSemantics(const std::byte *Buff)
Definition: Floating.h:211
static void deserialize(const std::byte *Buff, Floating *Result)
Definition: Floating.h:215
Bytecode function.
Definition: Function.h:86
unsigned getFrameSize() const
Returns the size of the function's local stack.
Definition: Function.h:99
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition: IntegralAP.h:36
Frame storing local variables.
Definition: InterpFrame.h:26
InterpFrame * Caller
The frame of the previous function.
Definition: InterpFrame.h:29
const Pointer & getThis() const
Returns the 'this' pointer.
Definition: InterpFrame.h:108
const Function * getFunction() const
Returns the current function.
Definition: InterpFrame.h:71
unsigned getDepth() const
Definition: InterpFrame.h:128
const Pointer & getRVOPtr() const
Returns the RVO pointer, if the Function has one.
Definition: InterpFrame.h:111
const FunctionDecl * getCallee() const override
Returns the caller.
void describe(llvm::raw_ostream &OS) const override
Describes the frame with arguments for diagnostic purposes.
A pointer to a memory block, live or dead.
Definition: Pointer.h:90
bool isInitialized() const
Checks if an object was initialized.
Definition: Pointer.cpp:432
The program contains and links the bytecode for all functions.
Definition: Program.h:36
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Definition: Program.cpp:109
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Definition: Disasm.cpp:251
void dump(llvm::raw_ostream &OS, unsigned Indentation=0, unsigned Offset=0) const
Definition: Disasm.cpp:486
std::string getName() const
Returns the name of the underlying declaration.
Definition: Record.cpp:32
llvm::iterator_range< const_virtual_iter > virtual_bases() const
Definition: Record.h:99
llvm::iterator_range< const_base_iter > bases() const
Definition: Record.h:88
llvm::iterator_range< const_field_iter > fields() const
Definition: Record.h:80
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:185
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:34
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
Describes a memory block created by an allocation site.
Definition: Descriptor.h:122
unsigned getAllocSize() const
Returns the allocated size, including metadata.
Definition: Descriptor.h:242
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition: Descriptor.h:249
unsigned getSize() const
Returns the size of the object without metadata.
Definition: Descriptor.h:231
void dumpFull(unsigned Offset=0, unsigned Indent=0) const
Dump descriptor, including all valid offsets.
Definition: Disasm.cpp:402
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition: Descriptor.h:263
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition: Descriptor.h:256
const Decl * asDecl() const
Definition: Descriptor.h:210
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition: Descriptor.h:155
unsigned getMetadataSize() const
Returns the size of the metadata.
Definition: Descriptor.h:246
bool isUnknownSizeArray() const
Checks if the descriptor is of an array of unknown size.
Definition: Descriptor.h:260
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:254
bool isZeroSizeArray() const
Checks if the descriptor is of an array of zero size.
Definition: Descriptor.h:258
PrimType getPrimType() const
Definition: Descriptor.h:236
bool isRecord() const
Checks if the descriptor is of a record.
Definition: Descriptor.h:268
const bool IsTemporary
Flag indicating if the block is a temporary.
Definition: Descriptor.h:165
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition: Descriptor.h:153
bool isUnion() const
Checks if the descriptor is of a union.
Definition: Descriptor.cpp:470
const Expr * asExpr() const
Definition: Descriptor.h:211
Inline descriptor embedded in structures and arrays.
Definition: Descriptor.h:67
unsigned IsActive
Flag indicating if the field is the active member of a union.
Definition: Descriptor.h:89
unsigned IsConstInMutable
Flag indicating if this field is a const field nested in a mutable parent field.
Definition: Descriptor.h:99
unsigned IsBase
Flag indicating if the field is an embedded base class.
Definition: Descriptor.h:83
unsigned InUnion
Flag indicating if this field is in a union (even if nested).
Definition: Descriptor.h:92
unsigned Offset
Offset inside the structure/array.
Definition: Descriptor.h:69
unsigned IsInitialized
For primitive fields, it indicates if the field was initialized.
Definition: Descriptor.h:80
unsigned IsConst
Flag indicating if the storage is constant or not.
Definition: Descriptor.h:74
unsigned IsArrayElement
Flag indicating if the field is an element of a composite array.
Definition: Descriptor.h:102
unsigned IsFieldMutable
Flag indicating if the field is mutable (if in a record).
Definition: Descriptor.h:95