xref: /llvm-project/clang/lib/AST/ByteCode/Disasm.cpp (revision b5c9cba3f33512014a18622a0e3479851faf4ce9)
1a07aba5dSTimm Baeder //===--- Disasm.cpp - Disassembler for bytecode functions -------*- C++ -*-===//
2a07aba5dSTimm Baeder //
3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information.
5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a07aba5dSTimm Baeder //
7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
8a07aba5dSTimm Baeder //
9a07aba5dSTimm Baeder // Dump method for Function which disassembles the bytecode.
10a07aba5dSTimm Baeder //
11a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
12a07aba5dSTimm Baeder 
13a07aba5dSTimm Baeder #include "Boolean.h"
14a07aba5dSTimm Baeder #include "Context.h"
15a07aba5dSTimm Baeder #include "EvaluationResult.h"
16048bc672STimm Baeder #include "FixedPoint.h"
17a07aba5dSTimm Baeder #include "Floating.h"
18a07aba5dSTimm Baeder #include "Function.h"
19a07aba5dSTimm Baeder #include "FunctionPointer.h"
20a07aba5dSTimm Baeder #include "Integral.h"
21a07aba5dSTimm Baeder #include "IntegralAP.h"
22a07aba5dSTimm Baeder #include "InterpFrame.h"
23a07aba5dSTimm Baeder #include "MemberPointer.h"
24a07aba5dSTimm Baeder #include "Opcode.h"
25a07aba5dSTimm Baeder #include "PrimType.h"
26a07aba5dSTimm Baeder #include "Program.h"
27a07aba5dSTimm Baeder #include "clang/AST/ASTDumperUtils.h"
28a07aba5dSTimm Baeder #include "clang/AST/DeclCXX.h"
29a07aba5dSTimm Baeder #include "clang/AST/ExprCXX.h"
30a07aba5dSTimm Baeder #include "llvm/Support/Compiler.h"
31a07aba5dSTimm Baeder #include "llvm/Support/Format.h"
32a07aba5dSTimm Baeder 
33a07aba5dSTimm Baeder using namespace clang;
34a07aba5dSTimm Baeder using namespace clang::interp;
35a07aba5dSTimm Baeder 
36cbdd14eeSCongcong Cai template <typename T> inline static T ReadArg(Program &P, CodePtr &OpPC) {
37a07aba5dSTimm Baeder   if constexpr (std::is_pointer_v<T>) {
38a07aba5dSTimm Baeder     uint32_t ID = OpPC.read<uint32_t>();
39a07aba5dSTimm Baeder     return reinterpret_cast<T>(P.getNativePointer(ID));
40a07aba5dSTimm Baeder   } else {
41a07aba5dSTimm Baeder     return OpPC.read<T>();
42a07aba5dSTimm Baeder   }
43a07aba5dSTimm Baeder }
44a07aba5dSTimm Baeder 
45a07aba5dSTimm Baeder template <> inline Floating ReadArg<Floating>(Program &P, CodePtr &OpPC) {
46a07aba5dSTimm Baeder   Floating F = Floating::deserialize(*OpPC);
47a07aba5dSTimm Baeder   OpPC += align(F.bytesToSerialize());
48a07aba5dSTimm Baeder   return F;
49a07aba5dSTimm Baeder }
50a07aba5dSTimm Baeder 
51a07aba5dSTimm Baeder template <>
52a07aba5dSTimm Baeder inline IntegralAP<false> ReadArg<IntegralAP<false>>(Program &P, CodePtr &OpPC) {
53a07aba5dSTimm Baeder   IntegralAP<false> I = IntegralAP<false>::deserialize(*OpPC);
54a07aba5dSTimm Baeder   OpPC += align(I.bytesToSerialize());
55a07aba5dSTimm Baeder   return I;
56a07aba5dSTimm Baeder }
57a07aba5dSTimm Baeder 
58a07aba5dSTimm Baeder template <>
59a07aba5dSTimm Baeder inline IntegralAP<true> ReadArg<IntegralAP<true>>(Program &P, CodePtr &OpPC) {
60a07aba5dSTimm Baeder   IntegralAP<true> I = IntegralAP<true>::deserialize(*OpPC);
61a07aba5dSTimm Baeder   OpPC += align(I.bytesToSerialize());
62a07aba5dSTimm Baeder   return I;
63a07aba5dSTimm Baeder }
64a07aba5dSTimm Baeder 
65*b5c9cba3STimm Baeder template <> inline FixedPoint ReadArg<FixedPoint>(Program &P, CodePtr &OpPC) {
66*b5c9cba3STimm Baeder   FixedPoint I = FixedPoint::deserialize(*OpPC);
67*b5c9cba3STimm Baeder   OpPC += align(I.bytesToSerialize());
68*b5c9cba3STimm Baeder   return I;
69*b5c9cba3STimm Baeder }
70*b5c9cba3STimm Baeder 
71a07aba5dSTimm Baeder LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }
72a07aba5dSTimm Baeder 
73a07aba5dSTimm Baeder LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {
74a07aba5dSTimm Baeder   {
75a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_GREEN, true});
76a07aba5dSTimm Baeder     OS << getName() << " " << (const void *)this << "\n";
77a07aba5dSTimm Baeder   }
78a07aba5dSTimm Baeder   OS << "frame size: " << getFrameSize() << "\n";
79a07aba5dSTimm Baeder   OS << "arg size:   " << getArgSize() << "\n";
80a07aba5dSTimm Baeder   OS << "rvo:        " << hasRVO() << "\n";
81a07aba5dSTimm Baeder   OS << "this arg:   " << hasThisPointer() << "\n";
82a07aba5dSTimm Baeder 
83a07aba5dSTimm Baeder   auto PrintName = [&OS](const char *Name) {
84a07aba5dSTimm Baeder     OS << Name;
85a07aba5dSTimm Baeder     long N = 30 - strlen(Name);
86a07aba5dSTimm Baeder     if (N > 0)
87a07aba5dSTimm Baeder       OS.indent(N);
88a07aba5dSTimm Baeder   };
89a07aba5dSTimm Baeder 
90a07aba5dSTimm Baeder   for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
91a07aba5dSTimm Baeder     size_t Addr = PC - Start;
92a07aba5dSTimm Baeder     auto Op = PC.read<Opcode>();
93a07aba5dSTimm Baeder     OS << llvm::format("%8d", Addr) << " ";
94a07aba5dSTimm Baeder     switch (Op) {
95a07aba5dSTimm Baeder #define GET_DISASM
96a07aba5dSTimm Baeder #include "Opcodes.inc"
97a07aba5dSTimm Baeder #undef GET_DISASM
98a07aba5dSTimm Baeder     }
99a07aba5dSTimm Baeder   }
100a07aba5dSTimm Baeder }
101a07aba5dSTimm Baeder 
102a07aba5dSTimm Baeder LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }
103a07aba5dSTimm Baeder 
104a07aba5dSTimm Baeder static const char *primTypeToString(PrimType T) {
105a07aba5dSTimm Baeder   switch (T) {
106a07aba5dSTimm Baeder   case PT_Sint8:
107a07aba5dSTimm Baeder     return "Sint8";
108a07aba5dSTimm Baeder   case PT_Uint8:
109a07aba5dSTimm Baeder     return "Uint8";
110a07aba5dSTimm Baeder   case PT_Sint16:
111a07aba5dSTimm Baeder     return "Sint16";
112a07aba5dSTimm Baeder   case PT_Uint16:
113a07aba5dSTimm Baeder     return "Uint16";
114a07aba5dSTimm Baeder   case PT_Sint32:
115a07aba5dSTimm Baeder     return "Sint32";
116a07aba5dSTimm Baeder   case PT_Uint32:
117a07aba5dSTimm Baeder     return "Uint32";
118a07aba5dSTimm Baeder   case PT_Sint64:
119a07aba5dSTimm Baeder     return "Sint64";
120a07aba5dSTimm Baeder   case PT_Uint64:
121a07aba5dSTimm Baeder     return "Uint64";
122a07aba5dSTimm Baeder   case PT_IntAP:
123a07aba5dSTimm Baeder     return "IntAP";
124a07aba5dSTimm Baeder   case PT_IntAPS:
125a07aba5dSTimm Baeder     return "IntAPS";
126a07aba5dSTimm Baeder   case PT_Bool:
127a07aba5dSTimm Baeder     return "Bool";
128a07aba5dSTimm Baeder   case PT_Float:
129a07aba5dSTimm Baeder     return "Float";
130a07aba5dSTimm Baeder   case PT_Ptr:
131a07aba5dSTimm Baeder     return "Ptr";
132a07aba5dSTimm Baeder   case PT_FnPtr:
133a07aba5dSTimm Baeder     return "FnPtr";
134a07aba5dSTimm Baeder   case PT_MemberPtr:
135a07aba5dSTimm Baeder     return "MemberPtr";
136048bc672STimm Baeder   case PT_FixedPoint:
137048bc672STimm Baeder     return "FixedPoint";
138a07aba5dSTimm Baeder   }
139a07aba5dSTimm Baeder   llvm_unreachable("Unhandled PrimType");
140a07aba5dSTimm Baeder }
141a07aba5dSTimm Baeder 
142a07aba5dSTimm Baeder LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
143a07aba5dSTimm Baeder   {
144a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
145a07aba5dSTimm Baeder     OS << "\n:: Program\n";
146a07aba5dSTimm Baeder   }
147a07aba5dSTimm Baeder 
148a07aba5dSTimm Baeder   {
149a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
150a07aba5dSTimm Baeder     OS << "Total memory : " << Allocator.getTotalMemory() << " bytes\n";
151a07aba5dSTimm Baeder     OS << "Global Variables: " << Globals.size() << "\n";
152a07aba5dSTimm Baeder   }
153a07aba5dSTimm Baeder   unsigned GI = 0;
154a07aba5dSTimm Baeder   for (const Global *G : Globals) {
155a07aba5dSTimm Baeder     const Descriptor *Desc = G->block()->getDescriptor();
156a07aba5dSTimm Baeder     Pointer GP = getPtrGlobal(GI);
157a07aba5dSTimm Baeder 
158a07aba5dSTimm Baeder     OS << GI << ": " << (const void *)G->block() << " ";
159a07aba5dSTimm Baeder     {
160a07aba5dSTimm Baeder       ColorScope SC(OS, true,
161a07aba5dSTimm Baeder                     GP.isInitialized()
162a07aba5dSTimm Baeder                         ? TerminalColor{llvm::raw_ostream::GREEN, false}
163a07aba5dSTimm Baeder                         : TerminalColor{llvm::raw_ostream::RED, false});
164a07aba5dSTimm Baeder       OS << (GP.isInitialized() ? "initialized " : "uninitialized ");
165a07aba5dSTimm Baeder     }
166a07aba5dSTimm Baeder     Desc->dump(OS);
167a07aba5dSTimm Baeder 
168a07aba5dSTimm Baeder     if (GP.isInitialized() && Desc->IsTemporary) {
169a07aba5dSTimm Baeder       if (const auto *MTE =
170a07aba5dSTimm Baeder               dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->asExpr());
171a07aba5dSTimm Baeder           MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
172a07aba5dSTimm Baeder         if (const APValue *V =
173a07aba5dSTimm Baeder                 MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
174a07aba5dSTimm Baeder           OS << " (global temporary value: ";
175a07aba5dSTimm Baeder           {
176a07aba5dSTimm Baeder             ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_MAGENTA, true});
177a07aba5dSTimm Baeder             std::string VStr;
178a07aba5dSTimm Baeder             llvm::raw_string_ostream SS(VStr);
179a07aba5dSTimm Baeder             V->dump(SS, Ctx.getASTContext());
180a07aba5dSTimm Baeder 
181a07aba5dSTimm Baeder             for (unsigned I = 0; I != VStr.size(); ++I) {
182a07aba5dSTimm Baeder               if (VStr[I] == '\n')
183a07aba5dSTimm Baeder                 VStr[I] = ' ';
184a07aba5dSTimm Baeder             }
185a07aba5dSTimm Baeder             VStr.pop_back(); // Remove the newline (or now space) at the end.
186a07aba5dSTimm Baeder             OS << VStr;
187a07aba5dSTimm Baeder           }
188a07aba5dSTimm Baeder           OS << ')';
189a07aba5dSTimm Baeder         }
190a07aba5dSTimm Baeder       }
191a07aba5dSTimm Baeder     }
192a07aba5dSTimm Baeder 
193a07aba5dSTimm Baeder     OS << "\n";
194a07aba5dSTimm Baeder     if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) {
195a07aba5dSTimm Baeder       OS << "   ";
196a07aba5dSTimm Baeder       {
197a07aba5dSTimm Baeder         ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
198a07aba5dSTimm Baeder         OS << primTypeToString(Desc->getPrimType()) << " ";
199a07aba5dSTimm Baeder       }
200a07aba5dSTimm Baeder       TYPE_SWITCH(Desc->getPrimType(), { GP.deref<T>().print(OS); });
201a07aba5dSTimm Baeder       OS << "\n";
202a07aba5dSTimm Baeder     }
203a07aba5dSTimm Baeder     ++GI;
204a07aba5dSTimm Baeder   }
205a07aba5dSTimm Baeder 
206a07aba5dSTimm Baeder   {
207a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});
208a07aba5dSTimm Baeder     OS << "Functions: " << Funcs.size() << "\n";
209a07aba5dSTimm Baeder   }
210a07aba5dSTimm Baeder   for (const auto &Func : Funcs) {
211a07aba5dSTimm Baeder     Func.second->dump();
212a07aba5dSTimm Baeder   }
213a07aba5dSTimm Baeder   for (const auto &Anon : AnonFuncs) {
214a07aba5dSTimm Baeder     Anon->dump();
215a07aba5dSTimm Baeder   }
216a07aba5dSTimm Baeder }
217a07aba5dSTimm Baeder 
218a07aba5dSTimm Baeder LLVM_DUMP_METHOD void Descriptor::dump() const {
219a07aba5dSTimm Baeder   dump(llvm::errs());
220a07aba5dSTimm Baeder   llvm::errs() << '\n';
221a07aba5dSTimm Baeder }
222a07aba5dSTimm Baeder 
223a07aba5dSTimm Baeder LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {
224a07aba5dSTimm Baeder   // Source
225a07aba5dSTimm Baeder   {
226a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
227a07aba5dSTimm Baeder     if (const auto *ND = dyn_cast_if_present<NamedDecl>(asDecl()))
228a07aba5dSTimm Baeder       ND->printQualifiedName(OS);
229a07aba5dSTimm Baeder     else if (asExpr())
230a07aba5dSTimm Baeder       OS << "Expr " << (const void *)asExpr();
231a07aba5dSTimm Baeder   }
232a07aba5dSTimm Baeder 
233a07aba5dSTimm Baeder   // Print a few interesting bits about the descriptor.
234a07aba5dSTimm Baeder   if (isPrimitiveArray())
235a07aba5dSTimm Baeder     OS << " primitive-array";
236a07aba5dSTimm Baeder   else if (isCompositeArray())
237a07aba5dSTimm Baeder     OS << " composite-array";
238a07aba5dSTimm Baeder   else if (isUnion())
239a07aba5dSTimm Baeder     OS << " union";
240a07aba5dSTimm Baeder   else if (isRecord())
241a07aba5dSTimm Baeder     OS << " record";
242a07aba5dSTimm Baeder   else if (isPrimitive())
243a07aba5dSTimm Baeder     OS << " primitive";
244a07aba5dSTimm Baeder 
245a07aba5dSTimm Baeder   if (isZeroSizeArray())
246a07aba5dSTimm Baeder     OS << " zero-size-array";
247a07aba5dSTimm Baeder   else if (isUnknownSizeArray())
248a07aba5dSTimm Baeder     OS << " unknown-size-array";
249a07aba5dSTimm Baeder 
250a07aba5dSTimm Baeder   if (isDummy())
251a07aba5dSTimm Baeder     OS << " dummy";
252a07aba5dSTimm Baeder }
253a07aba5dSTimm Baeder 
254a07aba5dSTimm Baeder LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const {
255a07aba5dSTimm Baeder   {
256a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
257a07aba5dSTimm Baeder     OS << "InlineDescriptor " << (const void *)this << "\n";
258a07aba5dSTimm Baeder   }
259a07aba5dSTimm Baeder   OS << "Offset: " << Offset << "\n";
260a07aba5dSTimm Baeder   OS << "IsConst: " << IsConst << "\n";
261a07aba5dSTimm Baeder   OS << "IsInitialized: " << IsInitialized << "\n";
262a07aba5dSTimm Baeder   OS << "IsBase: " << IsBase << "\n";
263a07aba5dSTimm Baeder   OS << "IsActive: " << IsActive << "\n";
264a07aba5dSTimm Baeder   OS << "InUnion: " << InUnion << "\n";
265a07aba5dSTimm Baeder   OS << "IsFieldMutable: " << IsFieldMutable << "\n";
266a07aba5dSTimm Baeder   OS << "Desc: ";
267a07aba5dSTimm Baeder   if (Desc)
268a07aba5dSTimm Baeder     Desc->dump(OS);
269a07aba5dSTimm Baeder   else
270a07aba5dSTimm Baeder     OS << "nullptr";
271a07aba5dSTimm Baeder   OS << "\n";
272a07aba5dSTimm Baeder }
273a07aba5dSTimm Baeder 
274a07aba5dSTimm Baeder LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream &OS,
275a07aba5dSTimm Baeder                                         unsigned Indent) const {
276a07aba5dSTimm Baeder   unsigned Spaces = Indent * 2;
277a07aba5dSTimm Baeder   {
278a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
279a07aba5dSTimm Baeder     OS.indent(Spaces);
280a07aba5dSTimm Baeder     if (getCallee())
281a07aba5dSTimm Baeder       describe(OS);
282a07aba5dSTimm Baeder     else
283a07aba5dSTimm Baeder       OS << "Frame (Depth: " << getDepth() << ")";
284a07aba5dSTimm Baeder     OS << "\n";
285a07aba5dSTimm Baeder   }
286a07aba5dSTimm Baeder   OS.indent(Spaces) << "Function: " << getFunction();
287a07aba5dSTimm Baeder   if (const Function *F = getFunction()) {
288a07aba5dSTimm Baeder     OS << " (" << F->getName() << ")";
289a07aba5dSTimm Baeder   }
290a07aba5dSTimm Baeder   OS << "\n";
291a07aba5dSTimm Baeder   OS.indent(Spaces) << "This: " << getThis() << "\n";
292a07aba5dSTimm Baeder   OS.indent(Spaces) << "RVO: " << getRVOPtr() << "\n";
293a07aba5dSTimm Baeder   OS.indent(Spaces) << "Depth: " << Depth << "\n";
294a07aba5dSTimm Baeder   OS.indent(Spaces) << "ArgSize: " << ArgSize << "\n";
295a07aba5dSTimm Baeder   OS.indent(Spaces) << "Args: " << (void *)Args << "\n";
296a07aba5dSTimm Baeder   OS.indent(Spaces) << "FrameOffset: " << FrameOffset << "\n";
297a07aba5dSTimm Baeder   OS.indent(Spaces) << "FrameSize: " << (Func ? Func->getFrameSize() : 0)
298a07aba5dSTimm Baeder                     << "\n";
299a07aba5dSTimm Baeder 
300a07aba5dSTimm Baeder   for (const InterpFrame *F = this->Caller; F; F = F->Caller) {
301a07aba5dSTimm Baeder     F->dump(OS, Indent + 1);
302a07aba5dSTimm Baeder   }
303a07aba5dSTimm Baeder }
304a07aba5dSTimm Baeder 
305a07aba5dSTimm Baeder LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
306a07aba5dSTimm Baeder                                    unsigned Offset) const {
307a07aba5dSTimm Baeder   unsigned Indent = Indentation * 2;
308a07aba5dSTimm Baeder   OS.indent(Indent);
309a07aba5dSTimm Baeder   {
310a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});
311a07aba5dSTimm Baeder     OS << getName() << "\n";
312a07aba5dSTimm Baeder   }
313a07aba5dSTimm Baeder 
314a07aba5dSTimm Baeder   unsigned I = 0;
315a07aba5dSTimm Baeder   for (const Record::Base &B : bases()) {
316a07aba5dSTimm Baeder     OS.indent(Indent) << "- Base " << I << ". Offset " << (Offset + B.Offset)
317a07aba5dSTimm Baeder                       << "\n";
318a07aba5dSTimm Baeder     B.R->dump(OS, Indentation + 1, Offset + B.Offset);
319a07aba5dSTimm Baeder     ++I;
320a07aba5dSTimm Baeder   }
321a07aba5dSTimm Baeder 
322a07aba5dSTimm Baeder   I = 0;
323a07aba5dSTimm Baeder   for (const Record::Field &F : fields()) {
324a07aba5dSTimm Baeder     OS.indent(Indent) << "- Field " << I << ": ";
325a07aba5dSTimm Baeder     {
326a07aba5dSTimm Baeder       ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});
327a07aba5dSTimm Baeder       OS << F.Decl->getName();
328a07aba5dSTimm Baeder     }
329a07aba5dSTimm Baeder     OS << ". Offset " << (Offset + F.Offset) << "\n";
330a07aba5dSTimm Baeder     ++I;
331a07aba5dSTimm Baeder   }
332a07aba5dSTimm Baeder 
333a07aba5dSTimm Baeder   I = 0;
334a07aba5dSTimm Baeder   for (const Record::Base &B : virtual_bases()) {
335a07aba5dSTimm Baeder     OS.indent(Indent) << "- Virtual Base " << I << ". Offset "
336a07aba5dSTimm Baeder                       << (Offset + B.Offset) << "\n";
337a07aba5dSTimm Baeder     B.R->dump(OS, Indentation + 1, Offset + B.Offset);
338a07aba5dSTimm Baeder     ++I;
339a07aba5dSTimm Baeder   }
340a07aba5dSTimm Baeder }
341a07aba5dSTimm Baeder 
342a07aba5dSTimm Baeder LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
343a07aba5dSTimm Baeder   {
344a07aba5dSTimm Baeder     ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});
345a07aba5dSTimm Baeder     OS << "Block " << (const void *)this;
346a07aba5dSTimm Baeder   }
347a07aba5dSTimm Baeder   OS << " (";
348a07aba5dSTimm Baeder   Desc->dump(OS);
349a07aba5dSTimm Baeder   OS << ")\n";
350a07aba5dSTimm Baeder   unsigned NPointers = 0;
351a07aba5dSTimm Baeder   for (const Pointer *P = Pointers; P; P = P->Next) {
352a07aba5dSTimm Baeder     ++NPointers;
353a07aba5dSTimm Baeder   }
354a07aba5dSTimm Baeder   OS << "  Pointers: " << NPointers << "\n";
355a07aba5dSTimm Baeder   OS << "  Dead: " << IsDead << "\n";
356a07aba5dSTimm Baeder   OS << "  Static: " << IsStatic << "\n";
357a07aba5dSTimm Baeder   OS << "  Extern: " << IsExtern << "\n";
358a07aba5dSTimm Baeder   OS << "  Initialized: " << IsInitialized << "\n";
359a07aba5dSTimm Baeder }
360a07aba5dSTimm Baeder 
361a07aba5dSTimm Baeder LLVM_DUMP_METHOD void EvaluationResult::dump() const {
362a07aba5dSTimm Baeder   assert(Ctx);
363a07aba5dSTimm Baeder   auto &OS = llvm::errs();
364a07aba5dSTimm Baeder   const ASTContext &ASTCtx = Ctx->getASTContext();
365a07aba5dSTimm Baeder 
366a07aba5dSTimm Baeder   switch (Kind) {
367a07aba5dSTimm Baeder   case Empty:
368a07aba5dSTimm Baeder     OS << "Empty\n";
369a07aba5dSTimm Baeder     break;
370a07aba5dSTimm Baeder   case RValue:
371a07aba5dSTimm Baeder     OS << "RValue: ";
372a07aba5dSTimm Baeder     std::get<APValue>(Value).dump(OS, ASTCtx);
373a07aba5dSTimm Baeder     break;
374a07aba5dSTimm Baeder   case LValue: {
375a07aba5dSTimm Baeder     assert(Source);
376a07aba5dSTimm Baeder     QualType SourceType;
3772b961b06SKazu Hirata     if (const auto *D = dyn_cast<const Decl *>(Source)) {
378a07aba5dSTimm Baeder       if (const auto *VD = dyn_cast<ValueDecl>(D))
379a07aba5dSTimm Baeder         SourceType = VD->getType();
3802b961b06SKazu Hirata     } else if (const auto *E = dyn_cast<const Expr *>(Source)) {
381a07aba5dSTimm Baeder       SourceType = E->getType();
382a07aba5dSTimm Baeder     }
383a07aba5dSTimm Baeder 
384a07aba5dSTimm Baeder     OS << "LValue: ";
385a07aba5dSTimm Baeder     if (const auto *P = std::get_if<Pointer>(&Value))
386a07aba5dSTimm Baeder       P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
387a07aba5dSTimm Baeder     else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope
388a07aba5dSTimm Baeder       FP->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
389a07aba5dSTimm Baeder     OS << "\n";
390a07aba5dSTimm Baeder     break;
391a07aba5dSTimm Baeder   }
392a07aba5dSTimm Baeder   case Invalid:
393a07aba5dSTimm Baeder     OS << "Invalid\n";
394a07aba5dSTimm Baeder     break;
395a07aba5dSTimm Baeder   case Valid:
396a07aba5dSTimm Baeder     OS << "Valid\n";
397a07aba5dSTimm Baeder     break;
398a07aba5dSTimm Baeder   }
399a07aba5dSTimm Baeder }
400