clang 24.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 "Char.h"
15#include "Context.h"
16#include "EvaluationResult.h"
17#include "FixedPoint.h"
18#include "Floating.h"
19#include "Function.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#include "llvm/Support/FormatVariadic.h"
32
33using namespace clang;
34using namespace clang::interp;
35
36template <typename T> inline static std::string printArg(CodePtr &OpPC) {
37 if constexpr (std::is_pointer_v<T>) {
38 uintptr_t Ptr = OpPC.read<uintptr_t>();
39 std::string Result;
40 llvm::raw_string_ostream SS(Result);
41 SS << reinterpret_cast<void *>(Ptr);
42 return Result;
43 } else {
44 std::string Result;
45 llvm::raw_string_ostream SS(Result);
46 auto Arg = OpPC.read<T>();
47 // Make sure we print the integral value of chars.
48 if constexpr (std::is_integral_v<T>) {
49 if constexpr (sizeof(T) == 1) {
50 if constexpr (std::is_signed_v<T>)
51 SS << static_cast<int32_t>(Arg);
52 else
53 SS << static_cast<uint32_t>(Arg);
54 } else {
55 SS << Arg;
56 }
57 } else {
58 SS << Arg;
59 }
60
61 return Result;
62 }
63}
64
65template <> inline std::string printArg<Floating>(CodePtr &OpPC) {
66 auto Sem = Floating::deserializeSemantics(*OpPC);
67
68 unsigned BitWidth = llvm::APFloatBase::semanticsSizeInBits(
69 llvm::APFloatBase::EnumToSemantics(Sem));
70 auto Memory =
71 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
72 Floating Result(Memory.get(), Sem);
74
75 OpPC += align(Result.bytesToSerialize());
76
77 std::string S;
78 llvm::raw_string_ostream SS(S);
79 SS << std::move(Result);
80 return S;
81}
82
83template <> inline std::string printArg<IntegralAP<false>>(CodePtr &OpPC) {
84 using T = IntegralAP<false>;
85 uint32_t BitWidth = T::deserializeSize(*OpPC);
86 auto Memory =
87 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
88
89 T Result(Memory.get(), BitWidth);
90 T::deserialize(*OpPC, &Result);
91
92 OpPC += align(Result.bytesToSerialize());
93
94 std::string Str;
95 llvm::raw_string_ostream SS(Str);
96 SS << std::move(Result);
97 return Str;
98}
99
100template <> inline std::string printArg<IntegralAP<true>>(CodePtr &OpPC) {
101 using T = IntegralAP<true>;
102 uint32_t BitWidth = T::deserializeSize(*OpPC);
103 auto Memory =
104 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
105
106 T Result(Memory.get(), BitWidth);
107 T::deserialize(*OpPC, &Result);
108
109 OpPC += align(Result.bytesToSerialize());
110
111 std::string Str;
112 llvm::raw_string_ostream SS(Str);
113 SS << std::move(Result);
114 return Str;
115}
116
117template <> inline std::string printArg<FixedPoint>(CodePtr &OpPC) {
118 auto F = FixedPoint::deserialize(*OpPC);
119 OpPC += align(F.bytesToSerialize());
120
121 std::string Result;
122 llvm::raw_string_ostream SS(Result);
123 SS << std::move(F);
124 return Result;
125}
126
127static bool isJumpOpcode(Opcode Op) {
128 return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt;
129}
130
131static size_t getNumDisplayWidth(size_t N) {
132 unsigned L = 1u, M = 10u;
133 while (M <= N && ++L != std::numeric_limits<size_t>::digits10 + 1)
134 M *= 10u;
135
136 return L;
137}
138
139LLVM_DUMP_METHOD void Function::dump(CodePtr PC) const {
140 dump(llvm::errs(), PC);
141}
142
143LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS,
144 CodePtr OpPC) const {
145 if (OpPC) {
146 assert(OpPC >= getCodeBegin());
147 assert(OpPC <= getCodeEnd());
148 }
149 {
150 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_GREEN, true});
151 if (const FunctionDecl *FD = getDecl()) {
152 FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
153 /*Qualified=*/true);
154 } else {
155 OS << getName();
156 }
157 OS << " " << (const void *)this << "\n";
158 }
159 OS << "frame size: " << getFrameSize() << "\n";
160 OS << "arg size: " << getArgSize() << "\n";
161 OS << "rvo: " << hasRVO() << "\n";
162 OS << "this arg: " << hasThisPointer() << "\n";
163
164 struct OpText {
165 size_t Addr;
166 std::string Op;
167 bool IsJump;
168 bool CurrentOp = false;
169 llvm::SmallVector<std::string> Args;
170 };
171
172 auto PrintName = [](const char *Name) -> std::string {
173 return std::string(Name);
174 };
175
176 llvm::SmallVector<OpText> Code;
177 size_t LongestAddr = 0;
178 size_t LongestOp = 0;
179
180 for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
181 size_t Addr = PC - Start;
182 OpText Text;
183 auto Op = PC.read<Opcode>();
184 Text.Addr = Addr;
185 Text.IsJump = isJumpOpcode(Op);
186 Text.CurrentOp = (PC == OpPC);
187 switch (Op) {
188#define GET_DISASM
189#include "Opcodes.inc"
190#undef GET_DISASM
191 }
192 Code.push_back(Text);
193 LongestOp = std::max(Text.Op.size(), LongestOp);
194 LongestAddr = std::max(getNumDisplayWidth(Addr), LongestAddr);
195 }
196
197 // Record jumps and their targets.
198 struct JmpData {
199 size_t From;
200 size_t To;
201 };
202 llvm::SmallVector<JmpData> Jumps;
203 for (auto &Text : Code) {
204 if (Text.IsJump)
205 Jumps.push_back({Text.Addr, Text.Addr + std::stoi(Text.Args[0]) +
206 align(sizeof(Opcode)) +
207 align(sizeof(int32_t))});
208 }
209
210 llvm::SmallVector<std::string> Text;
211 Text.reserve(Code.size());
212 size_t LongestLine = 0;
213 // Print code to a string, one at a time.
214 for (const auto &C : Code) {
215 std::string Line;
216 llvm::raw_string_ostream LS(Line);
217 if (OpPC) {
218 if (C.CurrentOp)
219 LS << " * ";
220 else
221 LS << " ";
222 }
223 LS << C.Addr;
224 LS.indent(LongestAddr - getNumDisplayWidth(C.Addr) + 4);
225 LS << C.Op;
226 LS.indent(LongestOp - C.Op.size() + 4);
227 for (auto &Arg : C.Args) {
228 LS << Arg << ' ';
229 }
230 Text.push_back(Line);
231 LongestLine = std::max(Line.size(), LongestLine);
232 }
233
234 assert(Code.size() == Text.size());
235
236 auto spaces = [](unsigned N) -> std::string {
237 std::string S;
238 for (unsigned I = 0; I != N; ++I)
239 S += ' ';
240 return S;
241 };
242
243 // Now, draw the jump lines.
244 for (auto &J : Jumps) {
245 if (J.To > J.From) {
246 bool FoundStart = false;
247 for (size_t LineIndex = 0; LineIndex != Text.size(); ++LineIndex) {
248 Text[LineIndex] += spaces(LongestLine - Text[LineIndex].size());
249
250 if (Code[LineIndex].Addr == J.From) {
251 Text[LineIndex] += " --+";
252 FoundStart = true;
253 } else if (Code[LineIndex].Addr == J.To) {
254 Text[LineIndex] += " <-+";
255 break;
256 } else if (FoundStart) {
257 Text[LineIndex] += " |";
258 }
259 }
260 LongestLine += 5;
261 } else {
262 bool FoundStart = false;
263 for (ssize_t LineIndex = Text.size() - 1; LineIndex >= 0; --LineIndex) {
264 Text[LineIndex] += spaces(LongestLine - Text[LineIndex].size());
265 if (Code[LineIndex].Addr == J.From) {
266 Text[LineIndex] += " --+";
267 FoundStart = true;
268 } else if (Code[LineIndex].Addr == J.To) {
269 Text[LineIndex] += " <-+";
270 break;
271 } else if (FoundStart) {
272 Text[LineIndex] += " |";
273 }
274 }
275 LongestLine += 5;
276 }
277 }
278
279 for (auto &Line : Text)
280 OS << Line << '\n';
281}
282
283LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }
284
285static const char *primTypeToString(PrimType T) {
286 switch (T) {
287 case PT_Sint8:
288 return "Sint8";
289 case PT_Uint8:
290 return "Uint8";
291 case PT_Sint16:
292 return "Sint16";
293 case PT_Uint16:
294 return "Uint16";
295 case PT_Sint32:
296 return "Sint32";
297 case PT_Uint32:
298 return "Uint32";
299 case PT_Sint64:
300 return "Sint64";
301 case PT_Uint64:
302 return "Uint64";
303 case PT_IntAP:
304 return "IntAP";
305 case PT_IntAPS:
306 return "IntAPS";
307 case PT_Bool:
308 return "Bool";
309 case PT_Float:
310 return "Float";
311 case PT_Ptr:
312 return "Ptr";
313 case PT_MemberPtr:
314 return "MemberPtr";
315 case PT_FixedPoint:
316 return "FixedPoint";
317 }
318 llvm_unreachable("Unhandled PrimType");
319}
320
321static std::string formatBytes(size_t B) {
322 std::string Result;
323 llvm::raw_string_ostream SS(Result);
324
325 if (B < (1u << 10u))
326 SS << B << " B";
327 else if (B < (1u << 20u))
328 SS << llvm::formatv("{0:F2}", B / 1024.) << " KB";
329 else
330 SS << llvm::formatv("{0:F2}", B / 1024. / 1024.) << " MB";
331
332 return Result;
333}
334
335LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
336 {
337 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
338 OS << "\n:: Program\n";
339 }
340
341 {
342 ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
343 size_t Bytes = 0;
344 Bytes += Allocator.getTotalMemory();
345 // All the maps.
346 Bytes += GlobalIndices.getMemorySize();
347 Bytes += Records.getMemorySize();
348
349 // All Records.
350 // They are allocated using the program allocator, so only get the size from
351 // the BaseMap.
352 for (const Record *R : Records.values())
353 Bytes += R->BaseMap.getMemorySize();
354
355 // Globals are allocated via the allocator, so already counted.
356
357 OS << "Total memory : " << formatBytes(Bytes) << '\n';
358 OS << "Global Variables: " << Globals.size() << '\n';
359 }
360 unsigned GI = 0;
361 for (const Global *G : Globals) {
362 const Descriptor *Desc = G->block()->getDescriptor();
363 Pointer GP = getPtrGlobal(GI);
364
365 OS << GI << ": " << (const void *)G->block() << " ";
366 {
367 ColorScope SC(OS, true,
368 GP.isInitialized()
369 ? TerminalColor{llvm::raw_ostream::GREEN, false}
370 : TerminalColor{llvm::raw_ostream::RED, false});
371 OS << (GP.isInitialized() ? "initialized " : "uninitialized ");
372 }
373 Desc->dump(OS);
374
375 if (GP.isInitialized() && Desc->IsTemporary) {
376 if (const auto *MTE =
377 dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->asExpr());
378 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
379 if (const APValue *V =
380 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
381 OS << " (global temporary value: ";
382 {
383 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_MAGENTA, true});
384 std::string VStr;
385 llvm::raw_string_ostream SS(VStr);
386 V->dump(SS, Ctx.getASTContext());
387
388 for (unsigned I = 0; I != VStr.size(); ++I) {
389 if (VStr[I] == '\n')
390 VStr[I] = ' ';
391 }
392 VStr.pop_back(); // Remove the newline (or now space) at the end.
393 OS << VStr;
394 }
395 OS << ')';
396 }
397 }
398 }
399
400 OS << "\n";
401 if (GP.isInitialized() && Desc->isPrimitive()) {
402 OS << " ";
403 {
404 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
405 OS << primTypeToString(Desc->getPrimType()) << " ";
406 }
407 TYPE_SWITCH(Desc->getPrimType(), { GP.deref<T>().print(OS); });
408 OS << "\n";
409 }
410 ++GI;
411 }
412
413 {
414 ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
415 OS << "Functions: " << Funcs.size() << "\n";
416 }
417 for (const auto &Func : Funcs) {
418 Func.second->dump();
419 }
420 for (const auto &Anon : AnonFuncs) {
421 Anon->dump();
422 }
423}
424
425LLVM_DUMP_METHOD void Descriptor::dump() const {
426 dump(llvm::errs());
427 llvm::errs() << '\n';
428}
429
430LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
431 // Source
432 {
433 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
434 if (const auto *ND = dyn_cast_if_present<NamedDecl>(asDecl()))
435 ND->printQualifiedName(OS);
436 else if (asExpr())
437 OS << "Expr " << (const void *)asExpr();
438 }
439
440 // Print a few interesting bits about the descriptor.
441 if (isPrimitiveArray())
442 OS << " primitive-array " << getNumElems() << ' '
444 else if (isCompositeArray())
445 OS << " composite-array " << getNumElems();
446 else if (isUnion())
447 OS << " union(" << ElemRecord->getName() << ")";
448 else if (isRecord())
449 OS << " record(" << ElemRecord->getName() << ")";
450 else if (isPrimitive())
451 OS << " primitive " << primTypeToString(getPrimType());
452
453 if (isZeroSizeArray())
454 OS << " zero-size-array";
455 else if (isUnknownSizeArray())
456 OS << " unknown-size-array";
457
459 OS << " constexpr-unknown";
460}
461
462/// Dump descriptor, including all valid offsets.
463LLVM_DUMP_METHOD void Descriptor::dumpFull(unsigned Offset,
464 unsigned Indent) const {
465 unsigned Spaces = Indent * 2;
466 llvm::raw_ostream &OS = llvm::errs();
467 OS.indent(Spaces);
468 dump(OS);
469 OS << '\n';
470 OS.indent(Spaces) << "Size: " << getSize() << " bytes\n";
471 OS.indent(Spaces) << "AllocSize: " << getAllocSize() << " bytes\n";
472 if (isCompositeArray()) {
473 OS.indent(Spaces) << "Elements: " << getNumElems() << '\n';
474 unsigned FO = Offset;
475 for (unsigned I = 0; I != getNumElems(); ++I) {
476 FO += sizeof(InlineDescriptor);
477 OS.indent(Spaces) << "Element " << I << " offset: " << FO << '\n';
478 ElemDesc->dumpFull(FO, Indent + 1);
479
480 FO += ElemDesc->getAllocSize();
481 }
482 } else if (isPrimitiveArray()) {
483 OS.indent(Spaces) << "Elements: " << getNumElems() << '\n';
484 OS.indent(Spaces) << "Element type: " << primTypeToString(getPrimType())
485 << '\n';
486 unsigned FO = Offset + sizeof(InitMapPtr);
487 for (unsigned I = 0; I != getNumElems(); ++I) {
488 OS.indent(Spaces) << "Element " << I << " offset: " << FO << '\n';
489 FO += getElemSize();
490 }
491 } else if (isRecord()) {
492 ElemRecord->dump(OS, Indent + 1, Offset);
493 unsigned I = 0;
494 for (const Record::Field &F : ElemRecord->fields()) {
495 OS.indent(Spaces) << "- Field " << I << ": ";
496 {
497 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
498 OS << F.Decl->getName();
499 }
500 OS << ". Offset " << (Offset + F.Offset) << "\n";
501 F.Desc->dumpFull(Offset + F.Offset, Indent + 1);
502 ++I;
503 }
504 } else if (isPrimitive()) {
505 } else {
506 }
507
508 OS << '\n';
509}
510
511LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const {
512 {
513 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
514 OS << "InlineDescriptor " << (const void *)this << "\n";
515 }
516 OS << "Offset: " << Offset << "\n";
517 OS << "IsConst: " << IsConst << "\n";
518 OS << "IsInitialized: " << IsInitialized << "\n";
519 OS << "IsBase: " << IsBase << "\n";
520 OS << "IsActive: " << IsActive << "\n";
521 OS << "InUnion: " << InUnion << "\n";
522 OS << "IsFieldMutable: " << IsFieldMutable << "\n";
523 OS << "IsArrayElement: " << IsArrayElement << "\n";
524 OS << "IsConstInMutable: " << IsConstInMutable << '\n';
525 OS << "Desc: ";
526 if (Desc)
527 Desc->dump(OS);
528 else
529 OS << "nullptr";
530 OS << "\n";
531}
532
533LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream &OS,
534 unsigned Indent) const {
535 unsigned Spaces = Indent * 2;
536 {
537 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
538 OS.indent(Spaces);
539 if (getCallee())
540 describe(OS);
541 else
542 OS << "Frame (Depth: " << getDepth() << ")";
543 OS << "\n";
544 }
545 OS.indent(Spaces) << "Function: " << getFunction();
546 if (const Function *F = getFunction()) {
547 OS << " (" << F->getName() << ")";
548 }
549 OS << "\n";
550 if (hasThisPointer())
551 OS.indent(Spaces) << "This: " << getThis() << "\n";
552 else
553 OS.indent(Spaces) << "This: -\n";
554 if (Func && Func->hasRVO())
555 OS.indent(Spaces) << "RVO: " << getRVOPtr() << "\n";
556 else
557 OS.indent(Spaces) << "RVO: -\n";
558 OS.indent(Spaces) << "Depth: " << Depth << "\n";
559 OS.indent(Spaces) << "ArgSize: " << ArgSize << "\n";
560 OS.indent(Spaces) << "Args: " << (void *)Args << "\n";
561#ifndef NDEBUG
562 OS.indent(Spaces) << "FrameOffset: " << FrameOffset << "\n";
563#endif
564 OS.indent(Spaces) << "FrameSize: " << (Func ? Func->getFrameSize() : 0)
565 << "\n";
566
567 for (const InterpFrame *F = this->Caller; F; F = F->Caller) {
568 F->dump(OS, Indent + 1);
569 }
570}
571
572LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
573 unsigned Offset) const {
574 unsigned Indent = Indentation * 2;
575 OS.indent(Indent);
576 {
577 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
578 OS << getName() << "\n";
579 }
580
581 unsigned I = 0;
582 for (const Record::Base &B : bases()) {
583 OS.indent(Indent) << "- Base " << I << ". Offset " << (Offset + B.Offset)
584 << "\n";
585 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
586 ++I;
587 }
588
589 I = 0;
590 for (const Record::Field &F : fields()) {
591 OS.indent(Indent) << "- Field " << I << ": ";
592 {
593 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
594 OS << F.Decl->getName();
595 }
596 OS << ". Offset " << (Offset + F.Offset) << "\n";
597 ++I;
598 }
599
600 I = 0;
601 for (const Record::Base &B : virtual_bases()) {
602 OS.indent(Indent) << "- Virtual Base " << I << ". Offset "
603 << (Offset + B.Offset) << "\n";
604 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
605 ++I;
606 }
607}
608
609LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
610 {
611 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});
612 OS << "Block " << (const void *)this;
613 }
614 OS << " (";
615 Desc->dump(OS);
616 OS << ")\n";
617 unsigned NPointers = 0;
618 for (const Pointer *P = Pointers; P; P = P->asBlockPointer().Next) {
619 ++NPointers;
620 }
621 OS << " EvalID: " << EvalID << '\n';
622 OS << " DeclID: ";
623 if (DeclID)
624 OS << *DeclID << '\n';
625 else
626 OS << "-\n";
627 OS << " Pointers: " << NPointers << "\n";
628 OS << " Dead: " << isDead() << "\n";
629 OS << " Static: " << IsStatic << "\n";
630 OS << " Extern: " << isExtern() << "\n";
631 OS << " Initialized: " << IsInitialized << "\n";
632 OS << " Weak: " << isWeak() << "\n";
633 OS << " Dynamic: " << isDynamic() << "\n";
634 OS << " Metadata: " << MDSize << '\n';
635}
636
637LLVM_DUMP_METHOD void EvaluationResult::dump() const {
638 auto &OS = llvm::errs();
639
640 if (empty()) {
641 OS << "Empty\n";
642 } else if (isInvalid()) {
643 OS << "Invalid\n";
644 } else {
645 OS << "Value: ";
646#ifndef NDEBUG
647 assert(Ctx);
648 Value.dump(OS, Ctx->getASTContext());
649#endif
650 }
651}
#define V(N, I)
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....
static std::string formatBytes(size_t B)
Definition Disasm.cpp:321
static const char * primTypeToString(PrimType T)
Definition Disasm.cpp:285
static std::string printArg(CodePtr &OpPC)
Definition Disasm.cpp:36
static size_t getNumDisplayWidth(size_t N)
Definition Disasm.cpp:131
static bool isJumpOpcode(Opcode Op)
Definition Disasm.cpp:127
std::string printArg< Floating >(CodePtr &OpPC)
Definition Disasm.cpp:65
std::string printArg< FixedPoint >(CodePtr &OpPC)
Definition Disasm.cpp:117
Defines the clang::Expr interface and subclasses for C++ expressions.
FormatToken * Next
The next token in the unwrapped line.
Result
Implement __builtin_bit_cast and related operations.
#define TYPE_SWITCH(Expr, B)
Definition PrimType.h:235
static bool isInvalid(LocType Loc, bool *Invalid)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
Represents a function declaration or definition.
Definition Decl.h:2059
bool isExtern() const
Checks if the block is extern.
Definition InterpBlock.h:77
friend class Pointer
bool isDead() const
Definition InterpBlock.h:84
bool isDynamic() const
Definition InterpBlock.h:83
bool isWeak() const
Definition InterpBlock.h:82
Pointer into the code segment.
Definition Source.h:31
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Definition Source.h:60
void dump() const
Dump to stderr.
Definition Disasm.cpp:637
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:212
static void deserialize(const std::byte *Buff, Floating *Result)
Definition Floating.h:216
Bytecode function.
Definition Function.h:98
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Definition Function.h:334
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition IntegralAP.h:36
InterpFrame(InterpState &S)
Bottom Frame.
InterpFrame * Caller
The frame of the previous function.
const Pointer & getThis() const
Returns the 'this' pointer.
const Function * getFunction() const
Returns the current function.
Definition InterpFrame.h:90
unsigned getDepth() const
const Pointer & getRVOPtr() const
Returns the RVO pointer, if the Function has one.
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:531
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:716
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Definition Program.cpp:20
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Definition Disasm.cpp:283
Structure/Class descriptor.
Definition Record.h:27
std::string getName() const
Returns the name of the underlying declaration.
Definition Record.cpp:26
llvm::iterator_range< const_base_iter > bases() const
Definition Record.h:107
llvm::iterator_range< const_base_iter > virtual_bases() const
Definition Record.h:123
llvm::iterator_range< const_field_iter > fields() const
Definition Record.h:92
static const FunctionDecl * getCallee(const CXXConstructExpr &D)
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:213
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
Top level wrappers for InstallAPI frontend operations.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
Definition JsonSupport.h:21
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
A quantity in bytes.
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:237
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition Descriptor.h:246
unsigned getSize() const
Returns the size of the object without metadata.
Definition Descriptor.h:226
void dumpFull(unsigned Offset=0, unsigned Indent=0) const
Dump descriptor, including all valid offsets.
Definition Disasm.cpp:463
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition Descriptor.h:260
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition Descriptor.h:253
const Decl * asDecl() const
Definition Descriptor.h:201
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition Descriptor.h:148
bool isUnknownSizeArray() const
Checks if the descriptor is of an array of unknown size.
Definition Descriptor.h:257
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
Definition Descriptor.h:239
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition Descriptor.h:251
bool isZeroSizeArray() const
Checks if the descriptor is of an array of zero size.
Definition Descriptor.h:255
PrimType getPrimType() const
Definition Descriptor.h:231
bool isRecord() const
Checks if the descriptor is of a record.
Definition Descriptor.h:265
const bool IsTemporary
Flag indicating if the block is a temporary.
Definition Descriptor.h:158
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:146
bool isUnion() const
Checks if the descriptor is of a union.
const Expr * asExpr() const
Definition Descriptor.h:202
A pointer-sized struct we use to allocate into data storage.
Definition InitMap.h:79
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