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