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