30#include "llvm/Support/Compiler.h"
37 if constexpr (std::is_pointer_v<T>) {
38 uint32_t ID = OpPC.
read<uint32_t>();
40 llvm::raw_string_ostream SS(Result);
41 SS << reinterpret_cast<T>(
P.getNativePointer(ID));
45 llvm::raw_string_ostream SS(Result);
46 auto Arg = OpPC.
read<
T>();
55 unsigned BitWidth = llvm::APFloatBase::semanticsSizeInBits(
56 llvm::APFloatBase::EnumToSemantics(Sem));
58 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
62 OpPC +=
align(Result.bytesToSerialize());
65 llvm::raw_string_ostream SS(S);
66 SS << std::move(Result);
73 uint32_t BitWidth = T::deserializeSize(*OpPC);
75 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
77 T Result(Memory.get(), BitWidth);
78 T::deserialize(*OpPC, &Result);
80 OpPC +=
align(Result.bytesToSerialize());
83 llvm::raw_string_ostream SS(Str);
84 SS << std::move(Result);
91 uint32_t BitWidth = T::deserializeSize(*OpPC);
93 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
95 T Result(Memory.get(), BitWidth);
96 T::deserialize(*OpPC, &Result);
98 OpPC +=
align(Result.bytesToSerialize());
101 llvm::raw_string_ostream SS(Str);
102 SS << std::move(Result);
108 OpPC +=
align(F.bytesToSerialize());
111 llvm::raw_string_ostream SS(Result);
117 return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt;
121 unsigned L = 1u, M = 10u;
122 while (M <= N && ++L != std::numeric_limits<size_t>::digits10 + 1)
128LLVM_DUMP_METHOD
void Function::dump()
const {
dump(llvm::errs()); }
130LLVM_DUMP_METHOD
void Function::dump(llvm::raw_ostream &OS)
const {
132 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_GREEN,
true});
133 OS << getName() <<
" " << (
const void *)
this <<
"\n";
135 OS <<
"frame size: " << getFrameSize() <<
"\n";
136 OS <<
"arg size: " << getArgSize() <<
"\n";
137 OS <<
"rvo: " << hasRVO() <<
"\n";
138 OS <<
"this arg: " << hasThisPointer() <<
"\n";
147 auto PrintName = [](
const char *Name) -> std::string {
148 return std::string(Name);
152 size_t LongestAddr = 0;
153 size_t LongestOp = 0;
155 for (
CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
156 size_t Addr = PC - Start;
158 auto Op = PC.read<
Opcode>();
163#include "Opcodes.inc"
166 Code.push_back(
Text);
167 LongestOp = std::max(
Text.Op.size(), LongestOp);
177 for (
auto &
Text : Code) {
179 Jumps.push_back({
Text.Addr,
Text.Addr + std::stoi(
Text.Args[0]) +
181 align(
sizeof(int32_t))});
185 Text.reserve(Code.size());
186 size_t LongestLine = 0;
188 for (
auto C : Code) {
190 llvm::raw_string_ostream LS(Line);
194 LS.indent(LongestOp -
C.Op.size() + 4);
195 for (
auto &Arg :
C.Args) {
198 Text.push_back(Line);
199 LongestLine = std::max(Line.size(), LongestLine);
202 assert(Code.size() ==
Text.size());
204 auto spaces = [](
unsigned N) -> std::string {
206 for (
unsigned I = 0; I != N; ++I)
212 for (
auto &J : Jumps) {
214 bool FoundStart =
false;
215 for (
size_t LineIndex = 0; LineIndex !=
Text.size(); ++LineIndex) {
216 Text[LineIndex] += spaces(LongestLine -
Text[LineIndex].size());
218 if (Code[LineIndex].
Addr == J.From) {
219 Text[LineIndex] +=
" --+";
221 }
else if (Code[LineIndex].
Addr == J.To) {
222 Text[LineIndex] +=
" <-+";
224 }
else if (FoundStart) {
225 Text[LineIndex] +=
" |";
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] +=
" --+";
236 }
else if (Code[LineIndex].
Addr == J.To) {
237 Text[LineIndex] +=
" <-+";
239 }
else if (FoundStart) {
240 Text[LineIndex] +=
" |";
247 for (
auto &Line :
Text)
286 llvm_unreachable(
"Unhandled PrimType");
291 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
292 OS <<
"\n:: Program\n";
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";
301 for (
const Global *G : Globals) {
302 const Descriptor *Desc = G->block()->getDescriptor();
305 OS << GI <<
": " << (
const void *)G->block() <<
" ";
311 OS << (GP.
isInitialized() ?
"initialized " :
"uninitialized ");
316 if (
const auto *MTE =
317 dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->
asExpr());
318 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
320 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
321 OS <<
" (global temporary value: ";
323 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_MAGENTA,
true});
325 llvm::raw_string_ostream SS(VStr);
328 for (
unsigned I = 0; I != VStr.size(); ++I) {
344 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_CYAN,
false});
354 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
355 OS <<
"Functions: " << Funcs.size() <<
"\n";
357 for (
const auto &
Func : Funcs) {
360 for (
const auto &Anon : AnonFuncs) {
367 llvm::errs() <<
'\n';
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);
377 OS <<
"Expr " << (
const void *)
asExpr();
382 OS <<
" primitive-array";
384 OS <<
" composite-array";
393 OS <<
" zero-size-array";
395 OS <<
" unknown-size-array";
398 OS <<
" constexpr-unknown";
403 unsigned Indent)
const {
404 unsigned Spaces = Indent * 2;
405 llvm::raw_ostream &OS = llvm::errs();
410 OS.indent(Spaces) <<
"Size: " <<
getSize() <<
" bytes\n";
411 OS.indent(Spaces) <<
"AllocSize: " <<
getAllocSize() <<
" bytes\n";
414 OS.indent(Spaces) <<
"Elements: " <<
getNumElems() <<
'\n';
415 unsigned FO = Offset;
419 OS.indent(Spaces) <<
"Element " << I <<
" offset: " << FO <<
'\n';
435 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
436 OS <<
"InlineDescriptor " << (
const void *)
this <<
"\n";
438 OS <<
"Offset: " <<
Offset <<
"\n";
439 OS <<
"IsConst: " <<
IsConst <<
"\n";
441 OS <<
"IsBase: " <<
IsBase <<
"\n";
442 OS <<
"IsActive: " <<
IsActive <<
"\n";
443 OS <<
"InUnion: " <<
InUnion <<
"\n";
456 unsigned Indent)
const {
457 unsigned Spaces = Indent * 2;
459 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
464 OS <<
"Frame (Depth: " <<
getDepth() <<
")";
467 OS.indent(Spaces) <<
"Function: " <<
getFunction();
469 OS <<
" (" << F->getName() <<
")";
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)
482 F->dump(OS, Indent + 1);
486LLVM_DUMP_METHOD
void Record::dump(llvm::raw_ostream &OS,
unsigned Indentation,
487 unsigned Offset)
const {
488 unsigned Indent = Indentation * 2;
491 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
496 for (
const Record::Base &B :
bases()) {
497 OS.indent(Indent) <<
"- Base " << I <<
". Offset " << (Offset + B.Offset)
499 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
504 for (
const Record::Field &F :
fields()) {
505 OS.indent(Indent) <<
"- Field " << I <<
": ";
507 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
508 OS << F.Decl->getName();
510 OS <<
". Offset " << (Offset + F.Offset) <<
"\n";
516 OS.indent(Indent) <<
"- Virtual Base " << I <<
". Offset "
517 << (Offset + B.Offset) <<
"\n";
518 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
525 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_BLUE,
true});
526 OS <<
"Block " << (
const void *)
this;
531 unsigned NPointers = 0;
532 for (
const Pointer *
P = Pointers;
P;
P =
P->asBlockPointer().Next) {
535 OS <<
" EvalID: " << EvalID <<
'\n';
538 OS << *DeclID <<
'\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";
552 auto &OS = llvm::errs();
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)
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.
ASTContext & getASTContext() const
Returns the AST context.
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)
unsigned getFrameSize() const
Returns the size of the function's local stack.
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Frame storing local variables.
InterpFrame * Caller
The frame of the previous function.
const Pointer & getThis() const
Returns the 'this' pointer.
const Function * getFunction() const
Returns the current function.
unsigned getDepth() const
const Pointer & getRVOPtr() const
Returns the RVO pointer, if the Function has one.
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.
bool isInitialized() const
Checks if an object was initialized.
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().
void dump(llvm::raw_ostream &OS, unsigned Indentation=0, unsigned Offset=0) const
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
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.
const FunctionProtoType * 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.
unsigned getMetadataSize() const
Returns the size of the metadata.
bool isUnknownSizeArray() const
Checks if the descriptor is of an array of unknown size.
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
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).