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);
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));
75 OpPC +=
align(Result.bytesToSerialize());
78 llvm::raw_string_ostream SS(S);
79 SS << std::move(Result);
86 uint32_t BitWidth = T::deserializeSize(*OpPC);
88 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
90 T Result(Memory.get(), BitWidth);
91 T::deserialize(*OpPC, &Result);
93 OpPC +=
align(Result.bytesToSerialize());
96 llvm::raw_string_ostream SS(Str);
97 SS << std::move(Result);
104 uint32_t BitWidth = T::deserializeSize(*OpPC);
106 std::make_unique<uint64_t[]>(llvm::APInt::getNumWords(BitWidth));
108 T Result(Memory.get(), BitWidth);
109 T::deserialize(*OpPC, &Result);
111 OpPC +=
align(Result.bytesToSerialize());
114 llvm::raw_string_ostream SS(Str);
115 SS << std::move(Result);
121 OpPC +=
align(F.bytesToSerialize());
124 llvm::raw_string_ostream SS(Result);
130 return Op == OP_Jmp || Op == OP_Jf || Op == OP_Jt;
134 unsigned L = 1u, M = 10u;
135 while (M <= N && ++L != std::numeric_limits<size_t>::digits10 + 1)
145 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_GREEN,
true});
146 OS <<
getName() <<
" " << (
const void *)
this <<
"\n";
150 OS <<
"rvo: " <<
hasRVO() <<
"\n";
160 auto PrintName = [](
const char *Name) -> std::string {
161 return std::string(Name);
165 size_t LongestAddr = 0;
166 size_t LongestOp = 0;
169 size_t Addr = PC - Start;
171 auto Op = PC.read<
Opcode>();
176#include "Opcodes.inc"
179 Code.push_back(
Text);
180 LongestOp = std::max(
Text.Op.size(), LongestOp);
190 for (
auto &
Text : Code) {
192 Jumps.push_back({
Text.Addr,
Text.Addr + std::stoi(
Text.Args[0]) +
194 align(
sizeof(int32_t))});
198 Text.reserve(Code.size());
199 size_t LongestLine = 0;
201 for (
auto C : Code) {
203 llvm::raw_string_ostream LS(
Line);
207 LS.indent(LongestOp -
C.Op.size() + 4);
208 for (
auto &Arg :
C.Args) {
212 LongestLine = std::max(
Line.size(), LongestLine);
215 assert(Code.size() ==
Text.size());
217 auto spaces = [](
unsigned N) -> std::string {
219 for (
unsigned I = 0; I != N; ++I)
225 for (
auto &J : Jumps) {
227 bool FoundStart =
false;
228 for (
size_t LineIndex = 0; LineIndex !=
Text.size(); ++LineIndex) {
229 Text[LineIndex] += spaces(LongestLine -
Text[LineIndex].size());
231 if (Code[LineIndex].
Addr == J.From) {
232 Text[LineIndex] +=
" --+";
234 }
else if (Code[LineIndex].
Addr == J.To) {
235 Text[LineIndex] +=
" <-+";
237 }
else if (FoundStart) {
238 Text[LineIndex] +=
" |";
243 bool FoundStart =
false;
244 for (ssize_t LineIndex =
Text.size() - 1; LineIndex >= 0; --LineIndex) {
245 Text[LineIndex] += spaces(LongestLine -
Text[LineIndex].size());
246 if (Code[LineIndex].
Addr == J.From) {
247 Text[LineIndex] +=
" --+";
249 }
else if (Code[LineIndex].
Addr == J.To) {
250 Text[LineIndex] +=
" <-+";
252 }
else if (FoundStart) {
253 Text[LineIndex] +=
" |";
299 llvm_unreachable(
"Unhandled PrimType");
304 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
305 OS <<
"\n:: Program\n";
309 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
310 OS <<
"Total memory : " << Allocator.getTotalMemory() <<
" bytes\n";
311 OS <<
"Global Variables: " << Globals.size() <<
"\n";
314 for (
const Global *G : Globals) {
315 const Descriptor *Desc = G->block()->getDescriptor();
318 OS << GI <<
": " << (
const void *)G->block() <<
" ";
324 OS << (GP.
isInitialized() ?
"initialized " :
"uninitialized ");
331 if (
const auto *MTE =
332 dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->
asExpr());
333 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
335 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
336 OS <<
" (global temporary value: ";
338 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_MAGENTA,
true});
340 llvm::raw_string_ostream SS(VStr);
341 V->dump(SS, Ctx.getASTContext());
343 for (
unsigned I = 0; I != VStr.size(); ++I) {
359 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_CYAN,
false});
369 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
370 OS <<
"Functions: " << Funcs.size() <<
"\n";
372 for (
const auto &
Func : Funcs) {
375 for (
const auto &Anon : AnonFuncs) {
382 llvm::errs() <<
'\n';
388 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
389 if (
const auto *ND = dyn_cast_if_present<NamedDecl>(
asDecl()))
390 ND->printQualifiedName(OS);
392 OS <<
"Expr " << (
const void *)
asExpr();
397 OS <<
" primitive-array";
399 OS <<
" composite-array";
408 OS <<
" zero-size-array";
410 OS <<
" unknown-size-array";
413 OS <<
" constexpr-unknown";
419 unsigned Spaces =
Indent * 2;
420 llvm::raw_ostream &OS = llvm::errs();
425 OS.indent(Spaces) <<
"Size: " <<
getSize() <<
" bytes\n";
426 OS.indent(Spaces) <<
"AllocSize: " <<
getAllocSize() <<
" bytes\n";
429 OS.indent(Spaces) <<
"Elements: " <<
getNumElems() <<
'\n';
430 unsigned FO = Offset;
433 assert(
ElemDesc->getMetadataSize() == 0);
434 OS.indent(Spaces) <<
"Element " << I <<
" offset: " << FO <<
'\n';
450 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
451 OS <<
"InlineDescriptor " << (
const void *)
this <<
"\n";
453 OS <<
"Offset: " <<
Offset <<
"\n";
454 OS <<
"IsConst: " <<
IsConst <<
"\n";
456 OS <<
"IsBase: " <<
IsBase <<
"\n";
457 OS <<
"IsActive: " <<
IsActive <<
"\n";
458 OS <<
"InUnion: " <<
InUnion <<
"\n";
472 unsigned Spaces =
Indent * 2;
474 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
479 OS <<
"Frame (Depth: " <<
getDepth() <<
")";
482 OS.indent(Spaces) <<
"Function: " <<
getFunction();
484 OS <<
" (" << F->getName() <<
")";
487 OS.indent(Spaces) <<
"This: " <<
getThis() <<
"\n";
488 OS.indent(Spaces) <<
"RVO: " <<
getRVOPtr() <<
"\n";
489 OS.indent(Spaces) <<
"Depth: " << Depth <<
"\n";
490 OS.indent(Spaces) <<
"ArgSize: " << ArgSize <<
"\n";
491 OS.indent(Spaces) <<
"Args: " << (
void *)Args <<
"\n";
492 OS.indent(Spaces) <<
"FrameOffset: " << FrameOffset <<
"\n";
493 OS.indent(Spaces) <<
"FrameSize: " << (Func ? Func->getFrameSize() : 0)
501LLVM_DUMP_METHOD
void Record::dump(llvm::raw_ostream &OS,
unsigned Indentation,
502 unsigned Offset)
const {
503 unsigned Indent = Indentation * 2;
506 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
511 for (
const Record::Base &B :
bases()) {
512 OS.indent(
Indent) <<
"- Base " << I <<
". Offset " << (Offset + B.Offset)
514 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
519 for (
const Record::Field &F :
fields()) {
520 OS.indent(
Indent) <<
"- Field " << I <<
": ";
522 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
523 OS << F.Decl->getName();
525 OS <<
". Offset " << (Offset + F.Offset) <<
"\n";
531 OS.indent(
Indent) <<
"- Virtual Base " << I <<
". Offset "
532 << (Offset + B.Offset) <<
"\n";
533 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
540 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_BLUE,
true});
541 OS <<
"Block " << (
const void *)
this;
546 unsigned NPointers = 0;
547 for (
const Pointer *P = Pointers; P; P = P->asBlockPointer().
Next) {
550 OS <<
" EvalID: " << EvalID <<
'\n';
553 OS << *DeclID <<
'\n';
556 OS <<
" Pointers: " << NPointers <<
"\n";
557 OS <<
" Dead: " <<
isDead() <<
"\n";
558 OS <<
" Static: " << IsStatic <<
"\n";
559 OS <<
" Extern: " <<
isExtern() <<
"\n";
560 OS <<
" Initialized: " << IsInitialized <<
"\n";
561 OS <<
" Weak: " <<
isWeak() <<
"\n";
562 OS <<
" Dummy: " <<
isDummy() <<
'\n';
563 OS <<
" Dynamic: " <<
isDynamic() <<
"\n";
567 auto &OS = llvm::errs();
577 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)
CodePtr getCodeBegin() const
Returns a pointer to the start of the code.
CodePtr getCodeEnd() const
Returns a pointer to the end of the code.
std::string getName() const
Returns the name of the function decl this code was generated for.
unsigned getFrameSize() const
Returns the size of the function's local stack.
bool hasThisPointer() const
void dump() const
Dumps the disassembled bytecode to llvm::errs().
unsigned getArgSize() const
Returns the size of the argument stack.
bool hasRVO() const
Checks if the first argument is a RVO pointer.
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.
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.
const void * getNativePointer(unsigned Idx)
Returns the value of a marshalled native pointer.
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
void dump() const
Dumps the disassembled bytecode to llvm::errs().
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)
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.
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).