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