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