summaryrefslogtreecommitdiff
path: root/chromium/v8/src/wasm/wasm-disassembler-impl.h
blob: 3530969218a7aa63db2de79b9c998223bc3ffd8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if !V8_ENABLE_WEBASSEMBLY
#error This header should only be included if WebAssembly is enabled.
#endif  // !V8_ENABLE_WEBASSEMBLY

#ifndef V8_WASM_WASM_DISASSEMBLER_IMPL_H_
#define V8_WASM_WASM_DISASSEMBLER_IMPL_H_

#include <iomanip>

#include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/names-provider.h"
#include "src/wasm/string-builder-multiline.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/zone/zone.h"

namespace v8 {
namespace internal {
namespace wasm {

template <Decoder::ValidateFlag validate>
class ImmediatesPrinter;

using IndexAsComment = NamesProvider::IndexAsComment;

////////////////////////////////////////////////////////////////////////////////
// Configuration flags for aspects of behavior where we might want to change
// our minds. {true} is the legacy DevTools behavior.
constexpr bool kSkipFunctionTypesInTypeSection = true;
constexpr IndexAsComment kIndicesAsComments = NamesProvider::kIndexAsComment;
constexpr bool kSkipDataSegmentNames = true;

////////////////////////////////////////////////////////////////////////////////
// Helpers.

class Indentation {
 public:
  Indentation(int current, int delta) : current_(current), delta_(delta) {
    DCHECK_GE(current, 0);
    DCHECK_GE(delta, 0);
  }

  Indentation Extra(int extra) { return {current_ + extra, delta_}; }

  void increase() { current_ += delta_; }
  void decrease() {
    DCHECK_GE(current_, delta_);
    current_ -= delta_;
  }
  int current() { return current_; }

 private:
  int current_;
  int delta_;
};

inline StringBuilder& operator<<(StringBuilder& sb, Indentation indentation) {
  char* ptr = sb.allocate(indentation.current());
  memset(ptr, ' ', indentation.current());
  return sb;
}

V8_EXPORT_PRIVATE void PrintSignatureOneLine(
    StringBuilder& out, const FunctionSig* sig, uint32_t func_index,
    NamesProvider* names, bool param_names,
    IndexAsComment indices_as_comments = NamesProvider::kDontPrintIndex);

class OffsetsProvider;

////////////////////////////////////////////////////////////////////////////////
// FunctionBodyDisassembler.

class V8_EXPORT_PRIVATE FunctionBodyDisassembler
    : public WasmDecoder<Decoder::kFullValidation> {
 public:
  static constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation;
  enum FunctionHeader : bool { kSkipHeader = false, kPrintHeader = true };

  FunctionBodyDisassembler(Zone* zone, const WasmModule* module,
                           uint32_t func_index, WasmFeatures* detected,
                           const FunctionSig* sig, const byte* start,
                           const byte* end, uint32_t offset,
                           NamesProvider* names)
      : WasmDecoder<validate>(zone, module, WasmFeatures::All(), detected, sig,
                              start, end, offset),
        func_index_(func_index),
        names_(names) {}

  void DecodeAsWat(MultiLineStringBuilder& out, Indentation indentation,
                   FunctionHeader include_header = kPrintHeader,
                   uint32_t* first_instruction_offset = nullptr);

  void DecodeGlobalInitializer(StringBuilder& out);

  std::set<uint32_t>& used_types() { return used_types_; }

 protected:
  WasmOpcode GetOpcode();

  uint32_t PrintImmediatesAndGetLength(StringBuilder& out);

  void PrintHexNumber(StringBuilder& out, uint64_t number);

  LabelInfo& label_info(int depth) {
    return label_stack_[label_stack_.size() - 1 - depth];
  }

  friend class ImmediatesPrinter<validate>;
  uint32_t func_index_;
  WasmOpcode current_opcode_ = kExprUnreachable;
  NamesProvider* names_;
  std::set<uint32_t> used_types_;
  std::vector<LabelInfo> label_stack_;
  MultiLineStringBuilder* out_;
  // Labels use two different indexing systems: for looking them up in the
  // name section, they're indexed by order of occurrence; for generating names
  // like "$label0", the order in which they show up as targets of branch
  // instructions is used for generating consecutive names.
  // (This is legacy wasmparser behavior; we could change it.)
  uint32_t label_occurrence_index_ = 0;
  uint32_t label_generation_index_ = 0;
};

////////////////////////////////////////////////////////////////////////////////
// ModuleDisassembler.

class ModuleDisassembler {
 public:
  V8_EXPORT_PRIVATE ModuleDisassembler(
      MultiLineStringBuilder& out, const WasmModule* module,
      NamesProvider* names, const ModuleWireBytes wire_bytes,
      AccountingAllocator* allocator,
      // When non-nullptr, doubles as a sentinel that bytecode offsets should be
      // stored for each line of disassembly.
      std::vector<int>* function_body_offsets = nullptr);
  V8_EXPORT_PRIVATE ~ModuleDisassembler();

  V8_EXPORT_PRIVATE void PrintTypeDefinition(uint32_t type_index,
                                             Indentation indendation,
                                             IndexAsComment index_as_comment);
  V8_EXPORT_PRIVATE void PrintModule(Indentation indentation);

 private:
  void PrintImportName(const WasmImport& import);
  void PrintExportName(ImportExportKindCode kind, uint32_t index);
  void PrintMutableType(bool mutability, ValueType type);
  void PrintTable(const WasmTable& table);
  void PrintMemory();
  void PrintGlobal(const WasmGlobal& global);
  void PrintInitExpression(const ConstantExpression& init,
                           ValueType expected_type);
  void PrintTagSignature(const FunctionSig* sig);
  void PrintString(WireBytesRef ref);
  void PrintStringAsJSON(WireBytesRef ref);
  void LineBreakOrSpace(bool break_lines, Indentation indentation,
                        uint32_t byte_offset);

  MultiLineStringBuilder& out_;
  const WasmModule* module_;
  NamesProvider* names_;
  const ModuleWireBytes wire_bytes_;
  const byte* start_;
  Zone zone_;
  std::unique_ptr<OffsetsProvider> offsets_;
  std::vector<int>* function_body_offsets_;
};

}  // namespace wasm
}  // namespace internal
}  // namespace v8

#endif  // V8_WASM_WASM_DISASSEMBLER_IMPL_H_