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>
ReadArg(Program & P,CodePtr OpPC)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>
ReadArg(Program & P,CodePtr OpPC)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
dump() const37 LLVM_DUMP_METHOD void Function::dump() const { dump(llvm::errs()); }
38
dump(llvm::raw_ostream & OS) const39 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
dump() const74 LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); }
75
dump(llvm::raw_ostream & OS) const76 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