Path: blob/main/contrib/llvm-project/clang/lib/AST/Interp/Disasm.cpp
35291 views
//===--- Disasm.cpp - Disassembler for bytecode functions -------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Dump method for Function which disassembles the bytecode.9//10//===----------------------------------------------------------------------===//1112#include "Boolean.h"13#include "Context.h"14#include "EvaluationResult.h"15#include "Floating.h"16#include "Function.h"17#include "FunctionPointer.h"18#include "Integral.h"19#include "IntegralAP.h"20#include "InterpFrame.h"21#include "MemberPointer.h"22#include "Opcode.h"23#include "PrimType.h"24#include "Program.h"25#include "clang/AST/ASTDumperUtils.h"26#include "clang/AST/DeclCXX.h"27#include "clang/AST/ExprCXX.h"28#include "llvm/Support/Compiler.h"29#include "llvm/Support/Format.h"3031using namespace clang;32using namespace clang::interp;3334template <typename T> inline T ReadArg(Program &P, CodePtr &OpPC) {35if constexpr (std::is_pointer_v<T>) {36uint32_t ID = OpPC.read<uint32_t>();37return reinterpret_cast<T>(P.getNativePointer(ID));38} else {39return OpPC.read<T>();40}41}4243template <> inline Floating ReadArg<Floating>(Program &P, CodePtr &OpPC) {44Floating F = Floating::deserialize(*OpPC);45OpPC += align(F.bytesToSerialize());46return F;47}4849template <>50inline IntegralAP<false> ReadArg<IntegralAP<false>>(Program &P, CodePtr &OpPC) {51IntegralAP<false> I = IntegralAP<false>::deserialize(*OpPC);52OpPC += align(I.bytesToSerialize());53return I;54}5556template <>57inline IntegralAP<true> ReadArg<IntegralAP<true>>(Program &P, CodePtr &OpPC) {58IntegralAP<true> I = IntegralAP<true>::deserialize(*OpPC);59OpPC += align(I.bytesToSerialize());60return I;61}6263LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }6465LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {66{67ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_GREEN, true});68OS << getName() << " " << (const void *)this << "\n";69}70OS << "frame size: " << getFrameSize() << "\n";71OS << "arg size: " << getArgSize() << "\n";72OS << "rvo: " << hasRVO() << "\n";73OS << "this arg: " << hasThisPointer() << "\n";7475auto PrintName = [&OS](const char *Name) {76OS << Name;77long N = 30 - strlen(Name);78if (N > 0)79OS.indent(N);80};8182for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {83size_t Addr = PC - Start;84auto Op = PC.read<Opcode>();85OS << llvm::format("%8d", Addr) << " ";86switch (Op) {87#define GET_DISASM88#include "Opcodes.inc"89#undef GET_DISASM90}91}92}9394LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }9596static const char *primTypeToString(PrimType T) {97switch (T) {98case PT_Sint8:99return "Sint8";100case PT_Uint8:101return "Uint8";102case PT_Sint16:103return "Sint16";104case PT_Uint16:105return "Uint16";106case PT_Sint32:107return "Sint32";108case PT_Uint32:109return "Uint32";110case PT_Sint64:111return "Sint64";112case PT_Uint64:113return "Uint64";114case PT_IntAP:115return "IntAP";116case PT_IntAPS:117return "IntAPS";118case PT_Bool:119return "Bool";120case PT_Float:121return "Float";122case PT_Ptr:123return "Ptr";124case PT_FnPtr:125return "FnPtr";126case PT_MemberPtr:127return "MemberPtr";128}129llvm_unreachable("Unhandled PrimType");130}131132LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {133{134ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});135OS << "\n:: Program\n";136}137138{139ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});140OS << "Total memory : " << Allocator.getTotalMemory() << " bytes\n";141OS << "Global Variables: " << Globals.size() << "\n";142}143unsigned GI = 0;144for (const Global *G : Globals) {145const Descriptor *Desc = G->block()->getDescriptor();146Pointer GP = getPtrGlobal(GI);147148OS << GI << ": " << (const void *)G->block() << " ";149{150ColorScope SC(OS, true,151GP.isInitialized()152? TerminalColor{llvm::raw_ostream::GREEN, false}153: TerminalColor{llvm::raw_ostream::RED, false});154OS << (GP.isInitialized() ? "initialized " : "uninitialized ");155}156Desc->dump(OS);157158if (GP.isInitialized() && Desc->IsTemporary) {159if (const auto *MTE =160dyn_cast_if_present<MaterializeTemporaryExpr>(Desc->asExpr());161MTE && MTE->getLifetimeExtendedTemporaryDecl()) {162if (const APValue *V =163MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {164OS << " (global temporary value: ";165{166ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_MAGENTA, true});167std::string VStr;168llvm::raw_string_ostream SS(VStr);169V->dump(SS, Ctx.getASTContext());170171for (unsigned I = 0; I != VStr.size(); ++I) {172if (VStr[I] == '\n')173VStr[I] = ' ';174}175VStr.pop_back(); // Remove the newline (or now space) at the end.176OS << VStr;177}178OS << ')';179}180}181}182183OS << "\n";184if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) {185OS << " ";186{187ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});188OS << primTypeToString(Desc->getPrimType()) << " ";189}190TYPE_SWITCH(Desc->getPrimType(), { GP.deref<T>().print(OS); });191OS << "\n";192}193++GI;194}195196{197ColorScope SC(OS, true, {llvm::raw_ostream::WHITE, true});198OS << "Functions: " << Funcs.size() << "\n";199}200for (const auto &Func : Funcs) {201Func.second->dump();202}203for (const auto &Anon : AnonFuncs) {204Anon->dump();205}206}207208LLVM_DUMP_METHOD void Descriptor::dump() const {209dump(llvm::errs());210llvm::errs() << '\n';211}212213LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const {214// Source215{216ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});217if (const auto *ND = dyn_cast_if_present<NamedDecl>(asDecl()))218ND->printQualifiedName(OS);219else if (asExpr())220OS << "Expr " << (const void *)asExpr();221}222223// Print a few interesting bits about the descriptor.224if (isPrimitiveArray())225OS << " primitive-array";226else if (isCompositeArray())227OS << " composite-array";228else if (isRecord())229OS << " record";230else if (isPrimitive())231OS << " primitive";232233if (isZeroSizeArray())234OS << " zero-size-array";235else if (isUnknownSizeArray())236OS << " unknown-size-array";237238if (isDummy())239OS << " dummy";240}241242LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const {243{244ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});245OS << "InlineDescriptor " << (const void *)this << "\n";246}247OS << "Offset: " << Offset << "\n";248OS << "IsConst: " << IsConst << "\n";249OS << "IsInitialized: " << IsInitialized << "\n";250OS << "IsBase: " << IsBase << "\n";251OS << "IsActive: " << IsActive << "\n";252OS << "IsFieldMutable: " << IsFieldMutable << "\n";253OS << "Desc: ";254if (Desc)255Desc->dump(OS);256else257OS << "nullptr";258OS << "\n";259}260261LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream &OS,262unsigned Indent) const {263unsigned Spaces = Indent * 2;264{265ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});266OS.indent(Spaces);267if (getCallee())268describe(OS);269else270OS << "Frame (Depth: " << getDepth() << ")";271OS << "\n";272}273OS.indent(Spaces) << "Function: " << getFunction();274if (const Function *F = getFunction()) {275OS << " (" << F->getName() << ")";276}277OS << "\n";278OS.indent(Spaces) << "This: " << getThis() << "\n";279OS.indent(Spaces) << "RVO: " << getRVOPtr() << "\n";280281while (const InterpFrame *F = this->Caller) {282F->dump(OS, Indent + 1);283F = F->Caller;284}285}286287LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,288unsigned Offset) const {289unsigned Indent = Indentation * 2;290OS.indent(Indent);291{292ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true});293OS << getName() << "\n";294}295296unsigned I = 0;297for (const Record::Base &B : bases()) {298OS.indent(Indent) << "- Base " << I << ". Offset " << (Offset + B.Offset)299<< "\n";300B.R->dump(OS, Indentation + 1, Offset + B.Offset);301++I;302}303304I = 0;305for (const Record::Field &F : fields()) {306OS.indent(Indent) << "- Field " << I << ": ";307{308ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true});309OS << F.Decl->getName();310}311OS << ". Offset " << (Offset + F.Offset) << "\n";312++I;313}314315I = 0;316for (const Record::Base &B : virtual_bases()) {317OS.indent(Indent) << "- Virtual Base " << I << ". Offset "318<< (Offset + B.Offset) << "\n";319B.R->dump(OS, Indentation + 1, Offset + B.Offset);320++I;321}322}323324LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {325{326ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});327OS << "Block " << (const void *)this;328}329OS << " (";330Desc->dump(OS);331OS << ")\n";332unsigned NPointers = 0;333for (const Pointer *P = Pointers; P; P = P->Next) {334++NPointers;335}336OS << " Pointers: " << NPointers << "\n";337OS << " Dead: " << IsDead << "\n";338OS << " Static: " << IsStatic << "\n";339OS << " Extern: " << IsExtern << "\n";340OS << " Initialized: " << IsInitialized << "\n";341}342343LLVM_DUMP_METHOD void EvaluationResult::dump() const {344assert(Ctx);345auto &OS = llvm::errs();346const ASTContext &ASTCtx = Ctx->getASTContext();347348switch (Kind) {349case Empty:350OS << "Empty\n";351break;352case RValue:353OS << "RValue: ";354std::get<APValue>(Value).dump(OS, ASTCtx);355break;356case LValue: {357assert(Source);358QualType SourceType;359if (const auto *D = Source.dyn_cast<const Decl *>()) {360if (const auto *VD = dyn_cast<ValueDecl>(D))361SourceType = VD->getType();362} else if (const auto *E = Source.dyn_cast<const Expr *>()) {363SourceType = E->getType();364}365366OS << "LValue: ";367if (const auto *P = std::get_if<Pointer>(&Value))368P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);369else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope370FP->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);371OS << "\n";372break;373}374case Invalid:375OS << "Invalid\n";376break;377case Valid:378OS << "Valid\n";379break;380}381}382383384