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> inline T ReadArg(Program &P, CodePtr &OpPC) {
25   if constexpr (std::is_pointer_v<T>) {
26     uint32_t ID = OpPC.read<uint32_t>();
27     return reinterpret_cast<T>(P.getNativePointer(ID));
28   } else {
29     return OpPC.read<T>();
30   }
31 }
32 
33 LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }
34 
35 LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {
36   if (F) {
37     if (auto *Cons = dyn_cast<CXXConstructorDecl>(F)) {
38       DeclarationName Name = Cons->getParent()->getDeclName();
39       OS << Name << "::" << Name;
40     } else {
41       OS << F->getDeclName();
42     }
43     OS << " " << (const void*)this << ":\n";
44   } else {
45     OS << "<<expr>>\n";
46   }
47 
48   OS << "frame size: " << getFrameSize() << "\n";
49   OS << "arg size:   " << getArgSize() << "\n";
50   OS << "rvo:        " << hasRVO() << "\n";
51   OS << "this arg:   " << hasThisPointer() << "\n";
52 
53   auto PrintName = [&OS](const char *Name) {
54     OS << Name;
55     for (long I = 0, N = strlen(Name); I < 30 - N; ++I) {
56       OS << ' ';
57     }
58   };
59 
60   for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
61     size_t Addr = PC - Start;
62     auto Op = PC.read<Opcode>();
63     OS << llvm::format("%8d", Addr) << " ";
64     switch (Op) {
65 #define GET_DISASM
66 #include "Opcodes.inc"
67 #undef GET_DISASM
68     }
69   }
70 }
71 
72 LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }
73 
74 LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
75   OS << ":: Program\n";
76   OS << "Global Variables: " << Globals.size() << "\n";
77   OS << "Functions: " << Funcs.size() << "\n";
78   OS << "\n";
79   for (auto &Func : Funcs) {
80     Func.second->dump();
81   }
82   for (auto &Anon : AnonFuncs) {
83     Anon->dump();
84   }
85 }
86