V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
function-body-decoder.cc
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/wasm/function-body-decoder.h"
6 
7 #include "src/flags.h"
8 #include "src/handles.h"
9 #include "src/objects-inl.h"
10 #include "src/ostreams.h"
11 #include "src/wasm/decoder.h"
12 #include "src/wasm/function-body-decoder-impl.h"
13 #include "src/wasm/wasm-limits.h"
14 #include "src/wasm/wasm-linkage.h"
15 #include "src/wasm/wasm-module.h"
16 #include "src/wasm/wasm-opcodes.h"
17 
18 namespace v8 {
19 namespace internal {
20 namespace wasm {
21 
22 bool DecodeLocalDecls(const WasmFeatures& enabled, BodyLocalDecls* decls,
23  const byte* start, const byte* end) {
24  Decoder decoder(start, end);
25  if (WasmDecoder<Decoder::kValidate>::DecodeLocals(enabled, &decoder, nullptr,
26  &decls->type_list)) {
27  DCHECK(decoder.ok());
28  decls->encoded_size = decoder.pc_offset();
29  return true;
30  }
31  return false;
32 }
33 
34 BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
35  BodyLocalDecls* decls)
36  : Decoder(start, end) {
37  if (decls != nullptr) {
38  if (DecodeLocalDecls(kAllWasmFeatures, decls, start, end)) {
39  pc_ += decls->encoded_size;
40  if (pc_ > end_) pc_ = end_;
41  }
42  }
43 }
44 
45 DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
46  const WasmFeatures& enabled,
47  const WasmModule* module, WasmFeatures* detected,
48  FunctionBody& body) {
49  Zone zone(allocator, ZONE_NAME);
50  WasmFullDecoder<Decoder::kValidate, EmptyInterface> decoder(
51  &zone, module, enabled, detected, body);
52  decoder.Decode();
53  return decoder.toResult(nullptr);
54 }
55 
56 unsigned OpcodeLength(const byte* pc, const byte* end) {
57  Decoder decoder(pc, end);
58  return WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, pc);
59 }
60 
61 std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
62  FunctionSig* sig, const byte* pc,
63  const byte* end) {
64  WasmFeatures unused_detected_features;
65  WasmDecoder<Decoder::kNoValidate> decoder(
66  module, kAllWasmFeatures, &unused_detected_features, sig, pc, end);
67  return decoder.StackEffect(pc);
68 }
69 
70 void PrintRawWasmCode(const byte* start, const byte* end) {
71  AccountingAllocator allocator;
72  PrintRawWasmCode(&allocator, FunctionBody{nullptr, 0, start, end}, nullptr,
73  kPrintLocals);
74 }
75 
76 namespace {
77 const char* RawOpcodeName(WasmOpcode opcode) {
78  switch (opcode) {
79 #define DECLARE_NAME_CASE(name, opcode, sig) \
80  case kExpr##name: \
81  return "kExpr" #name;
82  FOREACH_OPCODE(DECLARE_NAME_CASE)
83 #undef DECLARE_NAME_CASE
84  default:
85  break;
86  }
87  return "Unknown";
88 }
89 } // namespace
90 
91 bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
92  const WasmModule* module, PrintLocals print_locals) {
93  StdoutStream os;
94  return PrintRawWasmCode(allocator, body, module, print_locals, os);
95 }
96 
97 bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
98  const WasmModule* module, PrintLocals print_locals,
99  std::ostream& os, std::vector<int>* line_numbers) {
100  Zone zone(allocator, ZONE_NAME);
101  WasmFeatures unused_detected_features;
102  WasmDecoder<Decoder::kNoValidate> decoder(module, kAllWasmFeatures,
103  &unused_detected_features, body.sig,
104  body.start, body.end);
105  int line_nr = 0;
106  constexpr int kNoByteCode = -1;
107 
108  // Print the function signature.
109  if (body.sig) {
110  os << "// signature: " << *body.sig << std::endl;
111  if (line_numbers) line_numbers->push_back(kNoByteCode);
112  ++line_nr;
113  }
114 
115  // Print the local declarations.
116  BodyLocalDecls decls(&zone);
117  BytecodeIterator i(body.start, body.end, &decls);
118  if (body.start != i.pc() && print_locals == kPrintLocals) {
119  os << "// locals: ";
120  if (!decls.type_list.empty()) {
121  ValueType type = decls.type_list[0];
122  uint32_t count = 0;
123  for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
124  if (decls.type_list[pos] == type) {
125  ++count;
126  } else {
127  os << " " << count << " " << ValueTypes::TypeName(type);
128  type = decls.type_list[pos];
129  count = 1;
130  }
131  }
132  }
133  os << std::endl;
134  if (line_numbers) line_numbers->push_back(kNoByteCode);
135  ++line_nr;
136 
137  for (const byte* locals = body.start; locals < i.pc(); locals++) {
138  os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
139  }
140  os << std::endl;
141  if (line_numbers) line_numbers->push_back(kNoByteCode);
142  ++line_nr;
143  }
144 
145  os << "// body: " << std::endl;
146  if (line_numbers) line_numbers->push_back(kNoByteCode);
147  ++line_nr;
148  unsigned control_depth = 0;
149  for (; i.has_next(); i.next()) {
150  unsigned length =
151  WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, i.pc());
152 
153  WasmOpcode opcode = i.current();
154  if (line_numbers) line_numbers->push_back(i.position());
155  if (opcode == kExprElse) control_depth--;
156 
157  int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
158 
159  // 64 whitespaces
160  const char* padding =
161  " ";
162  os.write(padding, num_whitespaces);
163 
164  os << RawOpcodeName(opcode) << ",";
165 
166  if (opcode == kExprLoop || opcode == kExprIf || opcode == kExprBlock ||
167  opcode == kExprTry) {
168  DCHECK_EQ(2, length);
169 
170  switch (i.pc()[1]) {
171 #define CASE_LOCAL_TYPE(local_name, type_name) \
172  case kLocal##local_name: \
173  os << " kWasm" #type_name ","; \
174  break;
175 
176  CASE_LOCAL_TYPE(I32, I32)
177  CASE_LOCAL_TYPE(I64, I64)
178  CASE_LOCAL_TYPE(F32, F32)
179  CASE_LOCAL_TYPE(F64, F64)
180  CASE_LOCAL_TYPE(S128, S128)
181  CASE_LOCAL_TYPE(Void, Stmt)
182  default:
183  os << " 0x" << AsHex(i.pc()[1], 2) << ",";
184  break;
185  }
186 #undef CASE_LOCAL_TYPE
187  } else {
188  for (unsigned j = 1; j < length; ++j) {
189  os << " 0x" << AsHex(i.pc()[j], 2) << ",";
190  }
191  }
192 
193  switch (opcode) {
194  case kExprElse:
195  os << " // @" << i.pc_offset();
196  control_depth++;
197  break;
198  case kExprLoop:
199  case kExprIf:
200  case kExprBlock:
201  case kExprTry: {
202  BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
203  i.pc());
204  os << " // @" << i.pc_offset();
205  if (decoder.Complete(imm)) {
206  for (uint32_t i = 0; i < imm.out_arity(); i++) {
207  os << " " << ValueTypes::TypeName(imm.out_type(i));
208  }
209  }
210  control_depth++;
211  break;
212  }
213  case kExprEnd:
214  os << " // @" << i.pc_offset();
215  control_depth--;
216  break;
217  case kExprBr: {
218  BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
219  os << " // depth=" << imm.depth;
220  break;
221  }
222  case kExprBrIf: {
223  BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
224  os << " // depth=" << imm.depth;
225  break;
226  }
227  case kExprBrTable: {
228  BranchTableImmediate<Decoder::kNoValidate> imm(&i, i.pc());
229  os << " // entries=" << imm.table_count;
230  break;
231  }
232  case kExprCallIndirect: {
233  CallIndirectImmediate<Decoder::kNoValidate> imm(&i, i.pc());
234  os << " // sig #" << imm.sig_index;
235  if (decoder.Complete(i.pc(), imm)) {
236  os << ": " << *imm.sig;
237  }
238  break;
239  }
240  case kExprCallFunction: {
241  CallFunctionImmediate<Decoder::kNoValidate> imm(&i, i.pc());
242  os << " // function #" << imm.index;
243  if (decoder.Complete(i.pc(), imm)) {
244  os << ": " << *imm.sig;
245  }
246  break;
247  }
248  default:
249  break;
250  }
251  os << std::endl;
252  ++line_nr;
253  }
254  DCHECK(!line_numbers || line_numbers->size() == static_cast<size_t>(line_nr));
255 
256  return decoder.ok();
257 }
258 
259 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
260  const byte* start, const byte* end) {
261  Decoder decoder(start, end);
262  return WasmDecoder<Decoder::kValidate>::AnalyzeLoopAssignment(
263  &decoder, start, static_cast<uint32_t>(num_locals), zone);
264 }
265 
266 } // namespace wasm
267 } // namespace internal
268 } // namespace v8
Definition: libplatform.h:13