1e5dd7070Spatrick //===--- Disasm.cpp - Disassembler for bytecode functions -------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // Dump method for Function which disassembles the bytecode. 10e5dd7070Spatrick // 11e5dd7070Spatrick //===----------------------------------------------------------------------===// 12e5dd7070Spatrick 13e5dd7070Spatrick #include "Function.h" 14e5dd7070Spatrick #include "Opcode.h" 15e5dd7070Spatrick #include "PrimType.h" 16e5dd7070Spatrick #include "Program.h" 17e5dd7070Spatrick #include "clang/AST/DeclCXX.h" 18e5dd7070Spatrick #include "llvm/Support/Compiler.h" 19ec727ea7Spatrick #include "llvm/Support/Format.h" 20e5dd7070Spatrick 21e5dd7070Spatrick using namespace clang; 22e5dd7070Spatrick using namespace clang::interp; 23e5dd7070Spatrick ReadArg(Program & P,CodePtr & OpPC)24*12c85518Sroberttemplate <typename T> inline T ReadArg(Program &P, CodePtr &OpPC) { 25*12c85518Srobert if constexpr (std::is_pointer_v<T>) { 26*12c85518Srobert uint32_t ID = OpPC.read<uint32_t>(); 27*12c85518Srobert return reinterpret_cast<T>(P.getNativePointer(ID)); 28*12c85518Srobert } else { 29*12c85518Srobert return OpPC.read<T>(); 30*12c85518Srobert } 31*12c85518Srobert } 32*12c85518Srobert dump() const33e5dd7070SpatrickLLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); } 34e5dd7070Spatrick dump(llvm::raw_ostream & OS) const35e5dd7070SpatrickLLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const { 36e5dd7070Spatrick if (F) { 37e5dd7070Spatrick if (auto *Cons = dyn_cast<CXXConstructorDecl>(F)) { 38a9ac8606Spatrick DeclarationName Name = Cons->getParent()->getDeclName(); 39*12c85518Srobert OS << Name << "::" << Name; 40e5dd7070Spatrick } else { 41*12c85518Srobert OS << F->getDeclName(); 42e5dd7070Spatrick } 43*12c85518Srobert OS << " " << (const void*)this << ":\n"; 44e5dd7070Spatrick } else { 45e5dd7070Spatrick OS << "<<expr>>\n"; 46e5dd7070Spatrick } 47e5dd7070Spatrick 48e5dd7070Spatrick OS << "frame size: " << getFrameSize() << "\n"; 49e5dd7070Spatrick OS << "arg size: " << getArgSize() << "\n"; 50e5dd7070Spatrick OS << "rvo: " << hasRVO() << "\n"; 51*12c85518Srobert OS << "this arg: " << hasThisPointer() << "\n"; 52e5dd7070Spatrick 53e5dd7070Spatrick auto PrintName = [&OS](const char *Name) { 54e5dd7070Spatrick OS << Name; 55e5dd7070Spatrick for (long I = 0, N = strlen(Name); I < 30 - N; ++I) { 56e5dd7070Spatrick OS << ' '; 57e5dd7070Spatrick } 58e5dd7070Spatrick }; 59e5dd7070Spatrick 60e5dd7070Spatrick for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) { 61e5dd7070Spatrick size_t Addr = PC - Start; 62e5dd7070Spatrick auto Op = PC.read<Opcode>(); 63e5dd7070Spatrick OS << llvm::format("%8d", Addr) << " "; 64e5dd7070Spatrick switch (Op) { 65e5dd7070Spatrick #define GET_DISASM 66e5dd7070Spatrick #include "Opcodes.inc" 67e5dd7070Spatrick #undef GET_DISASM 68e5dd7070Spatrick } 69e5dd7070Spatrick } 70e5dd7070Spatrick } 71e5dd7070Spatrick dump() const72e5dd7070SpatrickLLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); } 73e5dd7070Spatrick dump(llvm::raw_ostream & OS) const74e5dd7070SpatrickLLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const { 75*12c85518Srobert OS << ":: Program\n"; 76*12c85518Srobert OS << "Global Variables: " << Globals.size() << "\n"; 77*12c85518Srobert OS << "Functions: " << Funcs.size() << "\n"; 78*12c85518Srobert OS << "\n"; 79e5dd7070Spatrick for (auto &Func : Funcs) { 80e5dd7070Spatrick Func.second->dump(); 81e5dd7070Spatrick } 82e5dd7070Spatrick for (auto &Anon : AnonFuncs) { 83e5dd7070Spatrick Anon->dump(); 84e5dd7070Spatrick } 85e5dd7070Spatrick } 86