clang: lib/AST/ByteCode/Disasm.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
30#include "llvm/Support/Compiler.h"
31#include "llvm/Support/Format.h"
32
33using namespace clang;
35
37 if constexpr (std::is_pointer_v) {
38 uint32_t ID = OpPC.read<uint32_t>();
39 return reinterpret_cast<T>(P.getNativePointer(ID));
40 } else {
42 }
43}
44
48 return F;
49}
50
51template <>
55 return I;
56}
57
58template <>
62 return I;
63}
64
68 return I;
69}
70
71LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }
72
73LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {
74 {
75 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_GREEN, true});
76 OS << getName() << " " << (const void *)this << "\n";
77 }
78 OS << "frame size: " << getFrameSize() << "\n";
79 OS << "arg size: " << getArgSize() << "\n";
80 OS << "rvo: " << hasRVO() << "\n";
81 OS << "this arg: " << hasThisPointer() << "\n";
82
83 auto PrintName = [&OS](const char *Name) {
84 OS << Name;
85 long N = 30 - strlen(Name);
86 if (N > 0)
87 OS.indent(N);
88 };
89
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) << " ";
94 switch (Op) {
95#define GET_DISASM
96#include "Opcodes.inc"
97#undef GET_DISASM
98 }
99 }
100}
101
103
105 switch (T) {
107 return "Sint8";
109 return "Uint8";
111 return "Sint16";
113 return "Uint16";
115 return "Sint32";
117 return "Uint32";
119 return "Sint64";
121 return "Uint64";
123 return "IntAP";
125 return "IntAPS";
127 return "Bool";
129 return "Float";
131 return "Ptr";
133 return "FnPtr";
135 return "MemberPtr";
137 return "FixedPoint";
138 }
139 llvm_unreachable("Unhandled PrimType");
140}
141
142LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
143 {
144 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
145 OS << "\n:: Program\n";
146 }
147
148 {
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";
152 }
153 unsigned GI = 0;
154 for (const Global *G : Globals) {
155 const Descriptor *Desc = G->block()->getDescriptor();
157
158 OS << GI << ": " << (const void *)G->block() << " ";
159 {
164 OS << (GP.isInitialized() ? "initialized " : "uninitialized ");
165 }
166 Desc->dump(OS);
167
169 if (const auto *MTE =
170 dyn_cast_if_present(Desc->asExpr());
171 MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
173 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
174 OS << " (global temporary value: ";
175 {
176 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_MAGENTA, true});
177 std::string VStr;
178 llvm::raw_string_ostream SS(VStr);
180
181 for (unsigned I = 0; I != VStr.size(); ++I) {
182 if (VStr[I] == '\n')
183 VStr[I] = ' ';
184 }
185 VStr.pop_back();
186 OS << VStr;
187 }
188 OS << ')';
189 }
190 }
191 }
192
193 OS << "\n";
195 OS << " ";
196 {
197 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
199 }
201 OS << "\n";
202 }
203 ++GI;
204 }
205
206 {
207 ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
208 OS << "Functions: " << Funcs.size() << "\n";
209 }
210 for (const auto &Func : Funcs) {
211 Func.second->dump();
212 }
213 for (const auto &Anon : AnonFuncs) {
214 Anon->dump();
215 }
216}
217
219 dump(llvm::errs());
220 llvm::errs() << '\n';
221}
222
224
225 {
226 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
227 if (const auto *ND = dyn_cast_if_present(asDecl()))
228 ND->printQualifiedName(OS);
230 OS << "Expr " << (const void *)asExpr();
231 }
232
233
235 OS << " primitive-array";
237 OS << " composite-array";
239 OS << " union";
241 OS << " record";
243 OS << " primitive";
244
246 OS << " zero-size-array";
248 OS << " unknown-size-array";
249
251 OS << " dummy";
252}
253
255 {
256 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
257 OS << "InlineDescriptor " << (const void *)this << "\n";
258 }
259 OS << "Offset: " << Offset << "\n";
260 OS << "IsConst: " << IsConst << "\n";
261 OS << "IsInitialized: " << IsInitialized << "\n";
262 OS << "IsBase: " << IsBase << "\n";
263 OS << "IsActive: " << IsActive << "\n";
264 OS << "InUnion: " << InUnion << "\n";
266 OS << "Desc: ";
269 else
270 OS << "nullptr";
271 OS << "\n";
272}
273
275 unsigned Indent) const {
276 unsigned Spaces = Indent * 2;
277 {
278 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
279 OS.indent(Spaces);
282 else
283 OS << "Frame (Depth: " << getDepth() << ")";
284 OS << "\n";
285 }
286 OS.indent(Spaces) << "Function: " << getFunction();
288 OS << " (" << F->getName() << ")";
289 }
290 OS << "\n";
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)
298 << "\n";
299
301 F->dump(OS, Indent + 1);
302 }
303}
304
305LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
306 unsigned Offset) const {
307 unsigned Indent = Indentation * 2;
308 OS.indent(Indent);
309 {
310 ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
312 }
313
314 unsigned I = 0;
315 for (const Record::Base &B : bases()) {
316 OS.indent(Indent) << "- Base " << I << ". Offset " << (Offset + B.Offset)
317 << "\n";
318 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
319 ++I;
320 }
321
322 I = 0;
323 for (const Record::Field &F : fields()) {
324 OS.indent(Indent) << "- Field " << I << ": ";
325 {
326 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
327 OS << F.Decl->getName();
328 }
329 OS << ". Offset " << (Offset + F.Offset) << "\n";
330 ++I;
331 }
332
333 I = 0;
335 OS.indent(Indent) << "- Virtual Base " << I << ". Offset "
336 << (Offset + B.Offset) << "\n";
337 B.R->dump(OS, Indentation + 1, Offset + B.Offset);
338 ++I;
339 }
340}
341
342LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
343 {
344 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});
345 OS << "Block " << (const void *)this;
346 }
347 OS << " (";
348 Desc->dump(OS);
349 OS << ")\n";
350 unsigned NPointers = 0;
351 for (const Pointer *P = Pointers; P; P = P->Next) {
352 ++NPointers;
353 }
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";
359}
360
362 assert(Ctx);
363 auto &OS = llvm::errs();
365
366 switch (Kind) {
368 OS << "Empty\n";
369 break;
371 OS << "RValue: ";
372 std::get(Value).dump(OS, ASTCtx);
373 break;
375 assert(Source);
377 if (const auto *D = dyn_cast<const Decl *>(Source)) {
378 if (const auto *VD = dyn_cast(D))
379 SourceType = VD->getType();
380 } else if (const auto *E = dyn_cast<const Expr *>(Source)) {
382 }
383
384 OS << "LValue: ";
385 if (const auto *P = std::get_if(&Value))
386 P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
387 else if (const auto *FP = std::get_if(&Value))
388 FP->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
389 OS << "\n";
390 break;
391 }
393 OS << "Invalid\n";
394 break;
396 OS << "Valid\n";
397 break;
398 }
399}
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).