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 "Floating.h"
14 #include "Function.h"
15 #include "Opcode.h"
16 #include "PrimType.h"
17 #include "Program.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/Format.h"
21 
22 using namespace clang;
23 using namespace clang::interp;
24 
ReadArg(Program & P,CodePtr & OpPC)25 template <typename T> inline T ReadArg(Program &P, CodePtr &OpPC) {
26   if constexpr (std::is_pointer_v<T>) {
27     uint32_t ID = OpPC.read<uint32_t>();
28     return reinterpret_cast<T>(P.getNativePointer(ID));
29   } else {
30     return OpPC.read<T>();
31   }
32 }
33 
ReadArg(Program & P,CodePtr & OpPC)34 template <> inline Floating ReadArg<Floating>(Program &P, CodePtr &OpPC) {
35   Floating F = Floating::deserialize(*OpPC);
36   OpPC += align(F.bytesToSerialize());
37   return F;
38 }
39 
dump() const40 LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }
41 
dump(llvm::raw_ostream & OS) const42 LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const {
43   OS << getName() << " " << (const void *)this << "\n";
44   OS << "frame size: " << getFrameSize() << "\n";
45   OS << "arg size:   " << getArgSize() << "\n";
46   OS << "rvo:        " << hasRVO() << "\n";
47   OS << "this arg:   " << hasThisPointer() << "\n";
48 
49   auto PrintName = [&OS](const char *Name) {
50     OS << Name;
51     long N = 30 - strlen(Name);
52     if (N > 0)
53       OS.indent(N);
54   };
55 
56   for (CodePtr Start = getCodeBegin(), PC = Start; PC != getCodeEnd();) {
57     size_t Addr = PC - Start;
58     auto Op = PC.read<Opcode>();
59     OS << llvm::format("%8d", Addr) << " ";
60     switch (Op) {
61 #define GET_DISASM
62 #include "Opcodes.inc"
63 #undef GET_DISASM
64     }
65   }
66 }
67 
dump() const68 LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }
69 
dump(llvm::raw_ostream & OS) const70 LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
71   OS << ":: Program\n";
72   OS << "Global Variables: " << Globals.size() << "\n";
73   OS << "Functions: " << Funcs.size() << "\n";
74   OS << "\n";
75   for (auto &Func : Funcs) {
76     Func.second->dump();
77   }
78   for (auto &Anon : AnonFuncs) {
79     Anon->dump();
80   }
81 }
82