29#include "llvm/Support/Compiler.h"
36 if constexpr (std::is_pointer_v<T>) {
37 uint32_t ID = OpPC.
read<uint32_t>();
39 llvm::raw_string_ostream SS(Result);
44 llvm::raw_string_ostream SS(Result);
45 auto Arg = OpPC.
read<T>();
47 if constexpr (std::is_integral_v<T>) {
48 if constexpr (
sizeof(T) == 1) {
49 if constexpr (std::is_signed_v<T>)
50 SS <<
static_cast<int32_t
>(Arg);
52 SS << static_cast<uint32_t>(Arg);
67 unsigned BitWidth = llvm::APFloatBase::semanticsSizeInBits(
68 llvm::APFloatBase::EnumToSemantics(Sem));
70 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
74 OpPC +=
align(Result.bytesToSerialize());
77 llvm::raw_string_ostream SS(S);
78 SS << std::move(Result);
85 uint32_t BitWidth = T::deserializeSize(*OpPC);
87 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
89 T
Result(Memory.get(), BitWidth);
90 T::deserialize(*OpPC, &Result);
92 OpPC +=
align(Result.bytesToSerialize());
95 llvm::raw_string_ostream SS(Str);
96 SS << std::move(Result);
103 uint32_t BitWidth = T::deserializeSize(*OpPC);
105 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
107 T
Result(Memory.get(), BitWidth);
108 T::deserialize(*OpPC, &Result);
110 OpPC +=
align(Result.bytesToSerialize());
113 llvm::raw_string_ostream SS(Str);
114 SS << std::move(Result);
120 OpPC +=
align(F.bytesToSerialize());
123 llvm::raw_string_ostream SS(Result);
129 return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt;
133 unsigned L = 1u, M = 10u;
134 while (M <= N && ++L != std::numeric_limits<size_t>::digits10 + 1)
141 dump(llvm::errs(), PC);
147 assert(OpPC >= getCodeBegin());
148 assert(OpPC <= getCodeEnd());
151 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_GREEN,
true});
152 OS << getName() <<
" " << (
const void *)
this <<
"\n";
154 OS <<
"frame size: " << getFrameSize() <<
"\n";
155 OS <<
"arg size: " << getArgSize() <<
"\n";
156 OS <<
"rvo: " << hasRVO() <<
"\n";
157 OS <<
"this arg: " << hasThisPointer() <<
"\n";
163 bool CurrentOp =
false;
164 llvm::SmallVector<std::string> Args;
167 auto PrintName = [](
const char *Name) -> std::string {
168 return std::string(Name);
171 llvm::SmallVector<OpText> Code;
172 size_t LongestAddr = 0;
173 size_t LongestOp = 0;
175 for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
176 size_t Addr = PC - Start;
178 auto Op = PC.read<
Opcode>();
181 Text.CurrentOp = (PC == OpPC);
184#include "Opcodes.inc"
187 Code.push_back(
Text);
188 LongestOp = std::max(
Text.Op.size(), LongestOp);
197 llvm::SmallVector<JmpData> Jumps;
198 for (
auto &
Text : Code) {
200 Jumps.push_back({
Text.Addr,
Text.Addr + std::stoi(
Text.Args[0]) +
202 align(
sizeof(int32_t))});
205 llvm::SmallVector<std::string>
Text;
206 Text.reserve(Code.size());
207 size_t LongestLine = 0;
209 for (
const auto &
C : Code) {
211 llvm::raw_string_ostream LS(
Line);
221 LS.indent(LongestOp -
C.Op.size() + 4);
222 for (
auto &Arg :
C.Args) {
226 LongestLine = std::max(
Line.size(), LongestLine);
229 assert(Code.size() ==
Text.size());
231 auto spaces = [](
unsigned N) -> std::string {
233 for (
unsigned I = 0; I != N; ++I)
239 for (
auto &J : Jumps) {
241 bool FoundStart =
false;
242 for (
size_t LineIndex = 0; LineIndex !=
Text.size(); ++LineIndex) {
243 Text[LineIndex] += spaces(LongestLine -
Text[LineIndex].size());
245 if (Code[LineIndex].
Addr == J.From) {
246 Text[LineIndex] +=
" --+";
248 }
else if (Code[LineIndex].
Addr == J.To) {
249 Text[LineIndex] +=
" <-+";
251 }
else if (FoundStart) {
252 Text[LineIndex] +=
" |";
257 bool FoundStart =
false;
258 for (ssize_t LineIndex =
Text.size() - 1; LineIndex >= 0; --LineIndex) {
259 Text[LineIndex] += spaces(LongestLine -
Text[LineIndex].size());
260 if (Code[LineIndex].
Addr == J.From) {
261 Text[LineIndex] +=
" --+";
263 }
else if (Code[LineIndex].
Addr == J.To) {
264 Text[LineIndex] +=
" <-+";
266 }
else if (FoundStart) {
267 Text[LineIndex] +=
" |";
313 llvm_unreachable(
"Unhandled PrimType");
318 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
319 OS <<
"\n:: Program\n";
323 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
324 OS <<
"Total memory : " << Allocator.getTotalMemory() <<
" bytes\n";
325 OS <<
"Global Variables: " << Globals.size() <<
"\n";
328 for (
const Global *G : Globals) {
329 const Descriptor *Desc = G->block()->getDescriptor();
332 OS << GI <<
": " << (
const void *)G->block() <<
" ";
338 OS << (GP.
isInitialized() ?
"initialized " :
"uninitialized ");
345 if (
const auto *MTE =
346 dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->
asExpr());
347 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
349 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
350 OS <<
" (global temporary value: ";
352 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_MAGENTA,
true});
354 llvm::raw_string_ostream SS(VStr);
355 V->dump(SS, Ctx.getASTContext());
357 for (
unsigned I = 0; I != VStr.size(); ++I) {
373 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_CYAN,
false});
383 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
384 OS <<
"Functions: " << Funcs.size() <<
"\n";
386 for (
const auto &
Func : Funcs) {
389 for (
const auto &Anon : AnonFuncs) {
396 llvm::errs() <<
'\n';
402 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
403 if (
const auto *ND = dyn_cast_if_present<NamedDecl>(
asDecl()))
404 ND->printQualifiedName(OS);
406 OS <<
"Expr " << (
const void *)
asExpr();
411 OS <<
" primitive-array";
413 OS <<
" composite-array";
422 OS <<
" zero-size-array";
424 OS <<
" unknown-size-array";
427 OS <<
" constexpr-unknown";
433 unsigned Spaces =
Indent * 2;
434 llvm::raw_ostream &OS = llvm::errs();
439 OS.indent(Spaces) <<
"Size: " <<
getSize() <<
" bytes\n";
440 OS.indent(Spaces) <<
"AllocSize: " <<
getAllocSize() <<
" bytes\n";
443 OS.indent(Spaces) <<
"Elements: " <<
getNumElems() <<
'\n';
444 unsigned FO = Offset;
447 assert(
ElemDesc->getMetadataSize() == 0);
448 OS.indent(Spaces) <<
"Element " << I <<
" offset: " << FO <<
'\n';
454 OS.indent(Spaces) <<
"Elements: " <<
getNumElems() <<
'\n';
459 OS.indent(Spaces) <<
"Element " << I <<
" offset: " << FO <<
'\n';
465 for (
const Record::Field &F :
ElemRecord->fields()) {
466 OS.indent(Spaces) <<
"- Field " << I <<
": ";
468 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
469 OS << F.Decl->getName();
471 OS <<
". Offset " << (Offset + F.Offset) <<
"\n";
472 F.Desc->dumpFull(Offset + F.Offset,
Indent + 1);
484 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
485 OS <<
"InlineDescriptor " << (
const void *)
this <<
"\n";
487 OS <<
"Offset: " <<
Offset <<
"\n";
488 OS <<
"IsConst: " <<
IsConst <<
"\n";
490 OS <<
"IsBase: " <<
IsBase <<
"\n";
491 OS <<
"IsActive: " <<
IsActive <<
"\n";
492 OS <<
"InUnion: " <<
InUnion <<
"\n";
506 unsigned Spaces =
Indent * 2;
508 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
513 OS <<
"Frame (Depth: " <<
getDepth() <<
")";
516 OS.indent(Spaces) <<
"Function: " <<
getFunction();
518 OS <<
" (" << F->getName() <<
")";
522 OS.indent(Spaces) <<
"This: " <<
getThis() <<
"\n";
524 OS.indent(Spaces) <<
"This: -\n";
525 if (Func && Func->hasRVO())
526 OS.indent(Spaces) <<
"RVO: " <<
getRVOPtr() <<
"\n";
528 OS.indent(Spaces) <<
"RVO: -\n";
529 OS.indent(Spaces) <<
"Depth: " << Depth <<
"\n";
530 OS.indent(Spaces) <<
"ArgSize: " << ArgSize <<
"\n";
531 OS.indent(Spaces) <<
"Args: " << (
void *)Args <<
"\n";
532 OS.indent(Spaces) <<
"FrameOffset: " << FrameOffset <<
"\n";
533 OS.indent(Spaces) <<
"FrameSize: " << (Func ? Func->getFrameSize() : 0)
541LLVM_DUMP_METHOD
void Record::dump(llvm::raw_ostream &OS,
unsigned Indentation,
542 unsigned Offset)
const {
543 unsigned Indent = Indentation * 2;
546 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
551 for (
const Record::Base &B :
bases()) {
552 OS.indent(
Indent) <<
"- Base " << I <<
". Offset " << (Offset + B.Offset)
554 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
559 for (
const Record::Field &F :
fields()) {
560 OS.indent(
Indent) <<
"- Field " << I <<
": ";
562 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
563 OS << F.Decl->getName();
565 OS <<
". Offset " << (Offset + F.Offset) <<
"\n";
571 OS.indent(
Indent) <<
"- Virtual Base " << I <<
". Offset "
572 << (Offset + B.Offset) <<
"\n";
573 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
580 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_BLUE,
true});
581 OS <<
"Block " << (
const void *)
this;
586 unsigned NPointers = 0;
587 for (
const Pointer *P = Pointers; P; P = P->asBlockPointer().
Next) {
590 OS <<
" EvalID: " << EvalID <<
'\n';
593 OS << *DeclID <<
'\n';
596 OS <<
" Pointers: " << NPointers <<
"\n";
597 OS <<
" Dead: " <<
isDead() <<
"\n";
598 OS <<
" Static: " << IsStatic <<
"\n";
599 OS <<
" Extern: " <<
isExtern() <<
"\n";
600 OS <<
" Initialized: " << IsInitialized <<
"\n";
601 OS <<
" Weak: " <<
isWeak() <<
"\n";
602 OS <<
" Dummy: " <<
isDummy() <<
'\n';
603 OS <<
" Dynamic: " <<
isDynamic() <<
"\n";
607 auto &OS = llvm::errs();
617 Value.dump(OS, Ctx->getASTContext());
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)
static const char * primTypeToString(PrimType T)
static size_t getNumDisplayWidth(size_t N)
static bool isJumpOpcode(Opcode Op)
std::string printArg< FixedPoint >(Program &P, CodePtr &OpPC)
static std::string printArg(Program &P, CodePtr &OpPC)
Defines the clang::Expr interface and subclasses for C++ expressions.
#define TYPE_SWITCH(Expr, B)
static bool isInvalid(LocType Loc, bool *Invalid)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
bool isExtern() const
Checks if the block is extern.
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
void dump() const
Dump to stderr.
static FixedPoint deserialize(const std::byte *Buff)
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
static llvm::APFloatBase::Semantics deserializeSemantics(const std::byte *Buff)
static void deserialize(const std::byte *Buff, Floating *Result)
void dump() const
Dumps the disassembled bytecode to llvm::errs().
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
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.
bool hasThisPointer() const
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.
bool isInitialized() const
Checks if an object was initialized.
const Block * block() const
The program contains and links the bytecode for all functions.
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
void dump() const
Dumps the disassembled bytecode to llvm::errs().
const void * getNativePointer(unsigned Idx) const
Returns the value of a marshalled native pointer.
std::string getName() const
Returns the name of the underlying declaration.
llvm::iterator_range< const_virtual_iter > virtual_bases() const
llvm::iterator_range< const_base_iter > bases() const
llvm::iterator_range< const_field_iter > fields() const
static const FunctionDecl * getCallee(const CXXConstructExpr &D)
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
PrimType
Enumeration of the primitive types of the VM.
The JSON file list parser is used to communicate input to InstallAPI.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
@ Result
The result type of a method or function.
Describes a memory block created by an allocation site.
unsigned getAllocSize() const
Returns the allocated size, including metadata.
unsigned getNumElems() const
Returns the number of elements stored in the block.
unsigned getSize() const
Returns the size of the object without metadata.
void dumpFull(unsigned Offset=0, unsigned Indent=0) const
Dump descriptor, including all valid offsets.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
const Decl * asDecl() const
const Descriptor *const ElemDesc
Descriptor of the array element.
unsigned getMetadataSize() const
Returns the size of the metadata.
bool isUnknownSizeArray() const
Checks if the descriptor is of an array of unknown size.
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
bool isZeroSizeArray() const
Checks if the descriptor is of an array of zero size.
PrimType getPrimType() const
bool isRecord() const
Checks if the descriptor is of a record.
const bool IsTemporary
Flag indicating if the block is a temporary.
const Record *const ElemRecord
Pointer to the record, if block contains records.
bool isUnion() const
Checks if the descriptor is of a union.
const Expr * asExpr() const
A pointer-sized struct we use to allocate into data storage.
Inline descriptor embedded in structures and arrays.
unsigned IsActive
Flag indicating if the field is the active member of a union.
unsigned IsConstInMutable
Flag indicating if this field is a const field nested in a mutable parent field.
unsigned IsBase
Flag indicating if the field is an embedded base class.
unsigned InUnion
Flag indicating if this field is in a union (even if nested).
unsigned Offset
Offset inside the structure/array.
unsigned IsInitialized
For primitive fields, it indicates if the field was initialized.
unsigned IsConst
Flag indicating if the storage is constant or not.
unsigned IsArrayElement
Flag indicating if the field is an element of a composite array.
unsigned IsFieldMutable
Flag indicating if the field is mutable (if in a record).