30#include "llvm/Support/Compiler.h"
31#include "llvm/Support/Format.h"
37 if constexpr (std::is_pointer_v<T>) {
38 uint32_t ID = OpPC.
read<uint32_t>();
39 return reinterpret_cast<T>(
P.getNativePointer(ID));
41 return OpPC.
read<
T>();
71LLVM_DUMP_METHOD
void Function::dump()
const {
dump(llvm::errs()); }
73LLVM_DUMP_METHOD
void Function::dump(llvm::raw_ostream &OS)
const {
75 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_GREEN,
true});
76 OS <<
getName() <<
" " << (
const void *)
this <<
"\n";
78 OS <<
"frame size: " << getFrameSize() <<
"\n";
79 OS <<
"arg size: " << getArgSize() <<
"\n";
80 OS <<
"rvo: " << hasRVO() <<
"\n";
81 OS <<
"this arg: " << hasThisPointer() <<
"\n";
83 auto PrintName = [&OS](
const char *Name) {
85 long N = 30 - strlen(Name);
90 for (
CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
91 size_t Addr = PC - Start;
92 auto Op = PC.read<
Opcode>();
93 OS << llvm::format(
"%8d", Addr) <<
" ";
139 llvm_unreachable(
"Unhandled PrimType");
144 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
145 OS <<
"\n:: Program\n";
149 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
150 OS <<
"Total memory : " << Allocator.getTotalMemory() <<
" bytes\n";
151 OS <<
"Global Variables: " << Globals.size() <<
"\n";
154 for (
const Global *G : Globals) {
155 const Descriptor *Desc = G->block()->getDescriptor();
158 OS << GI <<
": " << (
const void *)G->block() <<
" ";
164 OS << (GP.
isInitialized() ?
"initialized " :
"uninitialized ");
169 if (
const auto *MTE =
170 dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->
asExpr());
171 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
173 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
174 OS <<
" (global temporary value: ";
176 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_MAGENTA,
true});
178 llvm::raw_string_ostream SS(VStr);
181 for (
unsigned I = 0; I != VStr.size(); ++I) {
197 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_CYAN,
false});
207 ColorScope SC(OS,
true, {llvm::raw_ostream::WHITE,
true});
208 OS <<
"Functions: " << Funcs.size() <<
"\n";
210 for (
const auto &
Func : Funcs) {
213 for (
const auto &Anon : AnonFuncs) {
220 llvm::errs() <<
'\n';
226 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
227 if (
const auto *ND = dyn_cast_if_present<NamedDecl>(
asDecl()))
228 ND->printQualifiedName(OS);
230 OS <<
"Expr " << (
const void *)
asExpr();
235 OS <<
" primitive-array";
237 OS <<
" composite-array";
246 OS <<
" zero-size-array";
248 OS <<
" unknown-size-array";
256 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
257 OS <<
"InlineDescriptor " << (
const void *)
this <<
"\n";
259 OS <<
"Offset: " <<
Offset <<
"\n";
260 OS <<
"IsConst: " <<
IsConst <<
"\n";
262 OS <<
"IsBase: " <<
IsBase <<
"\n";
263 OS <<
"IsActive: " <<
IsActive <<
"\n";
264 OS <<
"InUnion: " <<
InUnion <<
"\n";
275 unsigned Indent)
const {
276 unsigned Spaces = Indent * 2;
278 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
283 OS <<
"Frame (Depth: " <<
getDepth() <<
")";
286 OS.indent(Spaces) <<
"Function: " <<
getFunction();
288 OS <<
" (" << F->getName() <<
")";
291 OS.indent(Spaces) <<
"This: " <<
getThis() <<
"\n";
292 OS.indent(Spaces) <<
"RVO: " <<
getRVOPtr() <<
"\n";
293 OS.indent(Spaces) <<
"Depth: " << Depth <<
"\n";
294 OS.indent(Spaces) <<
"ArgSize: " << ArgSize <<
"\n";
295 OS.indent(Spaces) <<
"Args: " << (
void *)Args <<
"\n";
296 OS.indent(Spaces) <<
"FrameOffset: " << FrameOffset <<
"\n";
297 OS.indent(Spaces) <<
"FrameSize: " << (Func ? Func->
getFrameSize() : 0)
301 F->dump(OS, Indent + 1);
305LLVM_DUMP_METHOD
void Record::dump(llvm::raw_ostream &OS,
unsigned Indentation,
306 unsigned Offset)
const {
307 unsigned Indent = Indentation * 2;
310 ColorScope SC(OS,
true, {llvm::raw_ostream::BLUE,
true});
315 for (
const Record::Base &B :
bases()) {
316 OS.indent(Indent) <<
"- Base " << I <<
". Offset " << (Offset + B.Offset)
318 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
323 for (
const Record::Field &F :
fields()) {
324 OS.indent(Indent) <<
"- Field " << I <<
": ";
326 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_RED,
true});
327 OS << F.Decl->getName();
329 OS <<
". Offset " << (Offset + F.Offset) <<
"\n";
335 OS.indent(Indent) <<
"- Virtual Base " << I <<
". Offset "
336 << (Offset + B.Offset) <<
"\n";
337 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
344 ColorScope SC(OS,
true, {llvm::raw_ostream::BRIGHT_BLUE,
true});
345 OS <<
"Block " << (
const void *)
this;
350 unsigned NPointers = 0;
351 for (
const Pointer *
P = Pointers;
P;
P =
P->Next) {
354 OS <<
" Pointers: " << NPointers <<
"\n";
355 OS <<
" Dead: " << IsDead <<
"\n";
356 OS <<
" Static: " << IsStatic <<
"\n";
357 OS <<
" Extern: " << IsExtern <<
"\n";
358 OS <<
" Initialized: " << IsInitialized <<
"\n";
363 auto &OS = llvm::errs();
372 std::get<APValue>(
Value).dump(OS, ASTCtx);
377 if (
const auto *
D = dyn_cast<const Decl *>(Source)) {
378 if (
const auto *VD = dyn_cast<ValueDecl>(
D))
379 SourceType = VD->getType();
380 }
else if (
const auto *
E = dyn_cast<const Expr *>(Source)) {
385 if (
const auto *
P = std::get_if<Pointer>(&
Value))
386 P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
387 else if (
const auto *FP = std::get_if<FunctionPointer>(&
Value))
388 FP->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
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 const char * primTypeToString(PrimType T)
FixedPoint ReadArg< FixedPoint >(Program &P, CodePtr &OpPC)
Floating ReadArg< Floating >(Program &P, CodePtr &OpPC)
static T ReadArg(Program &P, CodePtr &OpPC)
Defines the clang::Expr interface and subclasses for C++ expressions.
#define TYPE_SWITCH(Expr, B)
static std::string getName(const CallEvent &Call)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
A (possibly-)qualified type.
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.
Wrapper around fixed point types.
static FixedPoint deserialize(const std::byte *Buff)
size_t bytesToSerialize() const
static Floating deserialize(const std::byte *Buff)
size_t bytesToSerialize() const
unsigned getFrameSize() const
Returns the size of the function's local stack.
static IntegralAP< Signed > deserialize(const std::byte *Buff)
size_t bytesToSerialize() const
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().
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.
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
bool isDummy() const
Checks if this is a dummy descriptor.
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.
bool isUnion() const
Checks if the descriptor is of a union.
const Expr * asExpr() const
unsigned IsActive
Flag indicating if the field is the active member of a union.
unsigned IsBase
Flag indicating if the field is an embedded base class.
unsigned InUnion
Flat 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 IsFieldMutable
Flag indicating if the field is mutable (if in a record).