30#include "llvm/Support/Compiler.h"
31#include "llvm/Support/FormatVariadic.h"
37 if constexpr (std::is_pointer_v<T>) {
40 llvm::raw_string_ostream SS(
Result);
41 SS << reinterpret_cast<void *>(Ptr);
45 llvm::raw_string_ostream SS(
Result);
46 auto Arg = OpPC.
read<
T>();
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);
53 SS << static_cast<uint32_t>(Arg);
68 unsigned BitWidth = llvm::APFloatBase::semanticsSizeInBits(
69 llvm::APFloatBase::EnumToSemantics(Sem));
71 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
78 llvm::raw_string_ostream SS(S);
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);
95 llvm::raw_string_ostream SS(Str);
102 uint32_t BitWidth = T::deserializeSize(*OpPC);
104 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
106 T Result(Memory.get(), BitWidth);
107 T::deserialize(*OpPC, &
Result);
112 llvm::raw_string_ostream SS(Str);
119 OpPC +=
align(F.bytesToSerialize());
122 llvm::raw_string_ostream SS(
Result);
128 return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt;
132 unsigned L = 1u, M = 10u;
133 while (M <= N && ++L != std::numeric_limits<size_t>::digits10 + 1)
140 dump(llvm::errs(), PC);
146 assert(OpPC >= getCodeBegin());
147 assert(OpPC <= getCodeEnd());
150 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_GREEN,
true});
152 FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
157 OS <<
" " << (
const void *)
this <<
"\n";
159 OS <<
"frame size: " << getFrameSize() <<
"\n";
160 OS <<
"arg size: " << getArgSize() <<
"\n";
161 OS <<
"rvo: " << hasRVO() <<
"\n";
162 OS <<
"this arg: " << hasThisPointer() <<
"\n";
168 bool CurrentOp =
false;
169 llvm::SmallVector<std::string> Args;
172 auto PrintName = [](
const char *Name) -> std::string {
173 return std::string(Name);
176 llvm::SmallVector<OpText> Code;
177 size_t LongestAddr = 0;
178 size_t LongestOp = 0;
180 for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
181 size_t Addr = PC - Start;
183 auto Op = PC.read<
Opcode>();
186 Text.CurrentOp = (PC == OpPC);
189#include "Opcodes.inc"
192 Code.push_back(
Text);
193 LongestOp = std::max(
Text.Op.size(), LongestOp);
202 llvm::SmallVector<JmpData> Jumps;
203 for (
auto &
Text : Code) {
205 Jumps.push_back({
Text.Addr,
Text.Addr + std::stoi(
Text.Args[0]) +
210 llvm::SmallVector<std::string>
Text;
211 Text.reserve(Code.size());
212 size_t LongestLine = 0;
214 for (
const auto &
C : Code) {
216 llvm::raw_string_ostream LS(
Line);
226 LS.indent(LongestOp -
C.Op.size() + 4);
227 for (
auto &Arg :
C.Args) {
231 LongestLine = std::max(
Line.size(), LongestLine);
234 assert(Code.size() ==
Text.size());
236 auto spaces = [](
unsigned N) -> std::string {
238 for (
unsigned I = 0; I != N; ++I)
244 for (
auto &J : Jumps) {
246 bool FoundStart =
false;
247 for (
size_t LineIndex = 0; LineIndex !=
Text.size(); ++LineIndex) {
248 Text[LineIndex] += spaces(LongestLine -
Text[LineIndex].size());
250 if (Code[LineIndex].
Addr == J.From) {
251 Text[LineIndex] +=
" --+";
253 }
else if (Code[LineIndex].
Addr == J.To) {
254 Text[LineIndex] +=
" <-+";
256 }
else if (FoundStart) {
257 Text[LineIndex] +=
" |";
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] +=
" --+";
268 }
else if (Code[LineIndex].
Addr == J.To) {
269 Text[LineIndex] +=
" <-+";
271 }
else if (FoundStart) {
272 Text[LineIndex] +=
" |";
318 llvm_unreachable(
"Unhandled PrimType");
323 llvm::raw_string_ostream SS(
Result);
327 else if (B < (1u << 20u))
328 SS << llvm::formatv(
"{0:F2}", B / 1024.) <<
" KB";
330 SS << llvm::formatv(
"{0:F2}", B / 1024. / 1024.) <<
" MB";
337 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
338 OS <<
"\n:: Program\n";
342 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
344 Bytes += Allocator.getTotalMemory();
346 Bytes += GlobalIndices.getMemorySize();
347 Bytes += Records.getMemorySize();
352 for (
const Record *R : Records.values())
353 Bytes += R->BaseMap.getMemorySize();
358 OS <<
"Global Variables: " << Globals.size() <<
'\n';
361 for (
const Global *G : Globals) {
362 const Descriptor *Desc = G->block()->getDescriptor();
365 OS << GI <<
": " << (
const void *)G->block() <<
" ";
371 OS << (GP.
isInitialized() ?
"initialized " :
"uninitialized ");
376 if (
const auto *MTE =
377 dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->
asExpr());
378 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
380 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
381 OS <<
" (global temporary value: ";
383 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_MAGENTA,
true});
385 llvm::raw_string_ostream SS(VStr);
386 V->dump(SS, Ctx.getASTContext());
388 for (
unsigned I = 0; I != VStr.size(); ++I) {
404 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_CYAN,
false});
414 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
415 OS <<
"Functions: " << Funcs.size() <<
"\n";
417 for (
const auto &
Func : Funcs) {
420 for (
const auto &Anon : AnonFuncs) {
427 llvm::errs() <<
'\n';
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);
437 OS <<
"Expr " << (
const void *)
asExpr();
447 OS <<
" union(" <<
ElemRecord->getName() <<
")";
449 OS <<
" record(" <<
ElemRecord->getName() <<
")";
454 OS <<
" zero-size-array";
456 OS <<
" unknown-size-array";
459 OS <<
" constexpr-unknown";
465 unsigned Spaces =
Indent * 2;
466 llvm::raw_ostream &OS = llvm::errs();
470 OS.indent(Spaces) <<
"Size: " <<
getSize() <<
" bytes\n";
471 OS.indent(Spaces) <<
"AllocSize: " <<
getAllocSize() <<
" bytes\n";
473 OS.indent(Spaces) <<
"Elements: " <<
getNumElems() <<
'\n';
474 unsigned FO = Offset;
477 OS.indent(Spaces) <<
"Element " << I <<
" offset: " << FO <<
'\n';
483 OS.indent(Spaces) <<
"Elements: " <<
getNumElems() <<
'\n';
488 OS.indent(Spaces) <<
"Element " << I <<
" offset: " << FO <<
'\n';
494 for (
const Record::Field &F :
ElemRecord->fields()) {
495 OS.indent(Spaces) <<
"- Field " << I <<
": ";
497 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
498 OS << F.Decl->getName();
500 OS <<
". Offset " << (Offset + F.Offset) <<
"\n";
501 F.Desc->dumpFull(Offset + F.Offset,
Indent + 1);
513 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
514 OS <<
"InlineDescriptor " << (
const void *)
this <<
"\n";
516 OS <<
"Offset: " <<
Offset <<
"\n";
517 OS <<
"IsConst: " <<
IsConst <<
"\n";
519 OS <<
"IsBase: " <<
IsBase <<
"\n";
520 OS <<
"IsActive: " <<
IsActive <<
"\n";
521 OS <<
"InUnion: " <<
InUnion <<
"\n";
535 unsigned Spaces =
Indent * 2;
537 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
542 OS <<
"Frame (Depth: " <<
getDepth() <<
")";
545 OS.indent(Spaces) <<
"Function: " <<
getFunction();
547 OS <<
" (" << F->getName() <<
")";
551 OS.indent(Spaces) <<
"This: " <<
getThis() <<
"\n";
553 OS.indent(Spaces) <<
"This: -\n";
554 if (Func && Func->hasRVO())
555 OS.indent(Spaces) <<
"RVO: " <<
getRVOPtr() <<
"\n";
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";
562 OS.indent(Spaces) <<
"FrameOffset: " << FrameOffset <<
"\n";
564 OS.indent(Spaces) <<
"FrameSize: " << (Func ? Func->getFrameSize() : 0)
572LLVM_DUMP_METHOD
void Record::dump(llvm::raw_ostream &OS,
unsigned Indentation,
573 unsigned Offset)
const {
574 unsigned Indent = Indentation * 2;
577 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
582 for (
const Record::Base &B :
bases()) {
583 OS.indent(
Indent) <<
"- Base " << I <<
". Offset " << (Offset + B.Offset)
585 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
590 for (
const Record::Field &F :
fields()) {
591 OS.indent(
Indent) <<
"- Field " << I <<
": ";
593 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
594 OS << F.Decl->getName();
596 OS <<
". Offset " << (Offset + F.Offset) <<
"\n";
602 OS.indent(
Indent) <<
"- Virtual Base " << I <<
". Offset "
603 << (Offset + B.Offset) <<
"\n";
604 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
611 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_BLUE,
true});
612 OS <<
"Block " << (
const void *)
this;
617 unsigned NPointers = 0;
618 for (
const Pointer *P = Pointers; P; P = P->asBlockPointer().
Next) {
621 OS <<
" EvalID: " << EvalID <<
'\n';
624 OS << *DeclID <<
'\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';
638 auto &OS = llvm::errs();
648 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....
static std::string formatBytes(size_t B)
static const char * primTypeToString(PrimType T)
static std::string printArg(CodePtr &OpPC)
static size_t getNumDisplayWidth(size_t N)
static bool isJumpOpcode(Opcode Op)
std::string printArg< Floating >(CodePtr &OpPC)
std::string printArg< FixedPoint >(CodePtr &OpPC)
Defines the clang::Expr interface and subclasses for C++ expressions.
Result
Implement __builtin_bit_cast and related operations.
#define TYPE_SWITCH(Expr, B)
static bool isInvalid(LocType Loc, bool *Invalid)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Represents a function declaration or definition.
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.
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Structure/Class descriptor.
std::string getName() const
Returns the name of the underlying declaration.
llvm::iterator_range< const_base_iter > bases() const
llvm::iterator_range< const_base_iter > virtual_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,...
StringRef getName(const HeaderType T)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
PrimType
Enumeration of the primitive types of the VM.
Top level wrappers for InstallAPI frontend operations.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
@ Result
The result type of a method or function.
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
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.
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).