1 // Copyright 2017 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 #ifndef V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
6 #define V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
7
8 // Do only include this header for implementing new Interface of the
9 // WasmFullDecoder.
10
11 #include "src/bit-vector.h"
12 #include "src/wasm/decoder.h"
13 #include "src/wasm/function-body-decoder.h"
14 #include "src/wasm/wasm-limits.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 struct WasmGlobal;
23 struct WasmException;
24
25 #define TRACE(...) \
26 do { \
27 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
28 } while (false)
29
30 #define TRACE_INST_FORMAT " @%-8d #%-20s|"
31
32 // Return the evaluation of `condition` if validate==true, DCHECK that it's
33 // true and always return true otherwise.
34 #define VALIDATE(condition) \
35 (validate ? (condition) : [&] { \
36 DCHECK(condition); \
37 return true; \
38 }())
39
40 #define RET_ON_PROTOTYPE_OPCODE(flag) \
41 DCHECK(!this->module_ || !this->module_->is_asm_js()); \
42 if (!FLAG_experimental_wasm_##flag) { \
43 this->error("Invalid opcode (enable with --experimental-wasm-" #flag ")"); \
44 }
45
46 #define CHECK_PROTOTYPE_OPCODE(flag) \
47 DCHECK(!this->module_ || !this->module_->is_asm_js()); \
48 if (!FLAG_experimental_wasm_##flag) { \
49 this->error("Invalid opcode (enable with --experimental-wasm-" #flag ")"); \
50 break; \
51 }
52
53 #define OPCODE_ERROR(opcode, message) \
54 (this->errorf(this->pc_, "%s: %s", WasmOpcodes::OpcodeName(opcode), \
55 (message)))
56
57 #define ATOMIC_OP_LIST(V) \
58 V(I32AtomicLoad, Uint32) \
59 V(I64AtomicLoad, Uint64) \
60 V(I32AtomicLoad8U, Uint8) \
61 V(I32AtomicLoad16U, Uint16) \
62 V(I64AtomicLoad8U, Uint8) \
63 V(I64AtomicLoad16U, Uint16) \
64 V(I64AtomicLoad32U, Uint32) \
65 V(I32AtomicAdd, Uint32) \
66 V(I32AtomicAdd8U, Uint8) \
67 V(I32AtomicAdd16U, Uint16) \
68 V(I64AtomicAdd, Uint64) \
69 V(I64AtomicAdd8U, Uint8) \
70 V(I64AtomicAdd16U, Uint16) \
71 V(I64AtomicAdd32U, Uint32) \
72 V(I32AtomicSub, Uint32) \
73 V(I64AtomicSub, Uint64) \
74 V(I32AtomicSub8U, Uint8) \
75 V(I32AtomicSub16U, Uint16) \
76 V(I64AtomicSub8U, Uint8) \
77 V(I64AtomicSub16U, Uint16) \
78 V(I64AtomicSub32U, Uint32) \
79 V(I32AtomicAnd, Uint32) \
80 V(I64AtomicAnd, Uint64) \
81 V(I32AtomicAnd8U, Uint8) \
82 V(I32AtomicAnd16U, Uint16) \
83 V(I64AtomicAnd8U, Uint8) \
84 V(I64AtomicAnd16U, Uint16) \
85 V(I64AtomicAnd32U, Uint32) \
86 V(I32AtomicOr, Uint32) \
87 V(I64AtomicOr, Uint64) \
88 V(I32AtomicOr8U, Uint8) \
89 V(I32AtomicOr16U, Uint16) \
90 V(I64AtomicOr8U, Uint8) \
91 V(I64AtomicOr16U, Uint16) \
92 V(I64AtomicOr32U, Uint32) \
93 V(I32AtomicXor, Uint32) \
94 V(I64AtomicXor, Uint64) \
95 V(I32AtomicXor8U, Uint8) \
96 V(I32AtomicXor16U, Uint16) \
97 V(I64AtomicXor8U, Uint8) \
98 V(I64AtomicXor16U, Uint16) \
99 V(I64AtomicXor32U, Uint32) \
100 V(I32AtomicExchange, Uint32) \
101 V(I64AtomicExchange, Uint64) \
102 V(I32AtomicExchange8U, Uint8) \
103 V(I32AtomicExchange16U, Uint16) \
104 V(I64AtomicExchange8U, Uint8) \
105 V(I64AtomicExchange16U, Uint16) \
106 V(I64AtomicExchange32U, Uint32) \
107 V(I32AtomicCompareExchange, Uint32) \
108 V(I64AtomicCompareExchange, Uint64) \
109 V(I32AtomicCompareExchange8U, Uint8) \
110 V(I32AtomicCompareExchange16U, Uint16) \
111 V(I64AtomicCompareExchange8U, Uint8) \
112 V(I64AtomicCompareExchange16U, Uint16) \
113 V(I64AtomicCompareExchange32U, Uint32)
114
115 #define ATOMIC_STORE_OP_LIST(V) \
116 V(I32AtomicStore, Uint32) \
117 V(I64AtomicStore, Uint64) \
118 V(I32AtomicStore8U, Uint8) \
119 V(I32AtomicStore16U, Uint16) \
120 V(I64AtomicStore8U, Uint8) \
121 V(I64AtomicStore16U, Uint16) \
122 V(I64AtomicStore32U, Uint32)
123
124 template <typename T, typename Allocator>
vec2vec(std::vector<T,Allocator> & vec)125 Vector<T> vec2vec(std::vector<T, Allocator>& vec) {
126 return Vector<T>(vec.data(), vec.size());
127 }
128
129 // Helpers for decoding different kinds of immediates which follow bytecodes.
130 template <Decoder::ValidateFlag validate>
131 struct LocalIndexImmediate {
132 uint32_t index;
133 ValueType type = kWasmStmt;
134 unsigned length;
135
LocalIndexImmediateLocalIndexImmediate136 inline LocalIndexImmediate(Decoder* decoder, const byte* pc) {
137 index = decoder->read_u32v<validate>(pc + 1, &length, "local index");
138 }
139 };
140
141 template <Decoder::ValidateFlag validate>
142 struct ExceptionIndexImmediate {
143 uint32_t index;
144 const WasmException* exception = nullptr;
145 unsigned length;
146
ExceptionIndexImmediateExceptionIndexImmediate147 inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) {
148 index = decoder->read_u32v<validate>(pc + 1, &length, "exception index");
149 }
150 };
151
152 template <Decoder::ValidateFlag validate>
153 struct ImmI32Immediate {
154 int32_t value;
155 unsigned length;
ImmI32ImmediateImmI32Immediate156 inline ImmI32Immediate(Decoder* decoder, const byte* pc) {
157 value = decoder->read_i32v<validate>(pc + 1, &length, "immi32");
158 }
159 };
160
161 template <Decoder::ValidateFlag validate>
162 struct ImmI64Immediate {
163 int64_t value;
164 unsigned length;
ImmI64ImmediateImmI64Immediate165 inline ImmI64Immediate(Decoder* decoder, const byte* pc) {
166 value = decoder->read_i64v<validate>(pc + 1, &length, "immi64");
167 }
168 };
169
170 template <Decoder::ValidateFlag validate>
171 struct ImmF32Immediate {
172 float value;
173 unsigned length = 4;
ImmF32ImmediateImmF32Immediate174 inline ImmF32Immediate(Decoder* decoder, const byte* pc) {
175 // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
176 uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
177 memcpy(&value, &tmp, sizeof(value));
178 }
179 };
180
181 template <Decoder::ValidateFlag validate>
182 struct ImmF64Immediate {
183 double value;
184 unsigned length = 8;
ImmF64ImmediateImmF64Immediate185 inline ImmF64Immediate(Decoder* decoder, const byte* pc) {
186 // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
187 uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
188 memcpy(&value, &tmp, sizeof(value));
189 }
190 };
191
192 template <Decoder::ValidateFlag validate>
193 struct GlobalIndexImmediate {
194 uint32_t index;
195 ValueType type = kWasmStmt;
196 const WasmGlobal* global = nullptr;
197 unsigned length;
198
GlobalIndexImmediateGlobalIndexImmediate199 inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) {
200 index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
201 }
202 };
203
204 template <Decoder::ValidateFlag validate>
205 struct BlockTypeImmediate {
206 unsigned length = 1;
207 ValueType type = kWasmStmt;
208 uint32_t sig_index = 0;
209 FunctionSig* sig = nullptr;
210
BlockTypeImmediateBlockTypeImmediate211 inline BlockTypeImmediate(Decoder* decoder, const byte* pc) {
212 uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
213 if (!decode_local_type(val, &type)) {
214 // Handle multi-value blocks.
215 if (!VALIDATE(FLAG_experimental_wasm_mv)) {
216 decoder->error(pc + 1, "invalid block type");
217 return;
218 }
219 int32_t index =
220 decoder->read_i32v<validate>(pc + 1, &length, "block arity");
221 if (!VALIDATE(length > 0 && index >= 0)) {
222 decoder->error(pc + 1, "invalid block type index");
223 return;
224 }
225 sig_index = static_cast<uint32_t>(index);
226 }
227 }
228
229 // Decode a byte representing a local type. Return {false} if the encoded
230 // byte was invalid or the start of a type index.
decode_local_typeBlockTypeImmediate231 inline bool decode_local_type(uint8_t val, ValueType* result) {
232 switch (static_cast<ValueTypeCode>(val)) {
233 case kLocalVoid:
234 *result = kWasmStmt;
235 return true;
236 case kLocalI32:
237 *result = kWasmI32;
238 return true;
239 case kLocalI64:
240 *result = kWasmI64;
241 return true;
242 case kLocalF32:
243 *result = kWasmF32;
244 return true;
245 case kLocalF64:
246 *result = kWasmF64;
247 return true;
248 case kLocalS128:
249 *result = kWasmS128;
250 return true;
251 case kLocalAnyRef:
252 *result = kWasmAnyRef;
253 return true;
254 default:
255 *result = kWasmVar;
256 return false;
257 }
258 }
259
in_arityBlockTypeImmediate260 uint32_t in_arity() const {
261 if (type != kWasmVar) return 0;
262 return static_cast<uint32_t>(sig->parameter_count());
263 }
out_arityBlockTypeImmediate264 uint32_t out_arity() const {
265 if (type == kWasmStmt) return 0;
266 if (type != kWasmVar) return 1;
267 return static_cast<uint32_t>(sig->return_count());
268 }
in_typeBlockTypeImmediate269 ValueType in_type(uint32_t index) {
270 DCHECK_EQ(kWasmVar, type);
271 return sig->GetParam(index);
272 }
out_typeBlockTypeImmediate273 ValueType out_type(uint32_t index) {
274 if (type == kWasmVar) return sig->GetReturn(index);
275 DCHECK_NE(kWasmStmt, type);
276 DCHECK_EQ(0, index);
277 return type;
278 }
279 };
280
281 template <Decoder::ValidateFlag validate>
282 struct BreakDepthImmediate {
283 uint32_t depth;
284 unsigned length;
BreakDepthImmediateBreakDepthImmediate285 inline BreakDepthImmediate(Decoder* decoder, const byte* pc) {
286 depth = decoder->read_u32v<validate>(pc + 1, &length, "break depth");
287 }
288 };
289
290 template <Decoder::ValidateFlag validate>
291 struct CallIndirectImmediate {
292 uint32_t table_index;
293 uint32_t sig_index;
294 FunctionSig* sig = nullptr;
295 unsigned length = 0;
CallIndirectImmediateCallIndirectImmediate296 inline CallIndirectImmediate(Decoder* decoder, const byte* pc) {
297 unsigned len = 0;
298 sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
299 if (!VALIDATE(decoder->ok())) return;
300 table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
301 if (!VALIDATE(table_index == 0)) {
302 decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
303 table_index);
304 }
305 length = 1 + len;
306 }
307 };
308
309 template <Decoder::ValidateFlag validate>
310 struct CallFunctionImmediate {
311 uint32_t index;
312 FunctionSig* sig = nullptr;
313 unsigned length;
CallFunctionImmediateCallFunctionImmediate314 inline CallFunctionImmediate(Decoder* decoder, const byte* pc) {
315 index = decoder->read_u32v<validate>(pc + 1, &length, "function index");
316 }
317 };
318
319 template <Decoder::ValidateFlag validate>
320 struct MemoryIndexImmediate {
321 uint32_t index;
322 unsigned length = 1;
MemoryIndexImmediateMemoryIndexImmediate323 inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
324 index = decoder->read_u8<validate>(pc + 1, "memory index");
325 if (!VALIDATE(index == 0)) {
326 decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
327 }
328 }
329 };
330
331 template <Decoder::ValidateFlag validate>
332 struct BranchTableImmediate {
333 uint32_t table_count;
334 const byte* start;
335 const byte* table;
BranchTableImmediateBranchTableImmediate336 inline BranchTableImmediate(Decoder* decoder, const byte* pc) {
337 DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
338 start = pc + 1;
339 unsigned len = 0;
340 table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
341 table = pc + 1 + len;
342 }
343 };
344
345 // A helper to iterate over a branch table.
346 template <Decoder::ValidateFlag validate>
347 class BranchTableIterator {
348 public:
cur_index()349 unsigned cur_index() { return index_; }
has_next()350 bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; }
next()351 uint32_t next() {
352 DCHECK(has_next());
353 index_++;
354 unsigned length;
355 uint32_t result =
356 decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
357 pc_ += length;
358 return result;
359 }
360 // length, including the length of the {BranchTableImmediate}, but not the
361 // opcode.
length()362 unsigned length() {
363 while (has_next()) next();
364 return static_cast<unsigned>(pc_ - start_);
365 }
pc()366 const byte* pc() { return pc_; }
367
BranchTableIterator(Decoder * decoder,const BranchTableImmediate<validate> & imm)368 BranchTableIterator(Decoder* decoder,
369 const BranchTableImmediate<validate>& imm)
370 : decoder_(decoder),
371 start_(imm.start),
372 pc_(imm.table),
373 table_count_(imm.table_count) {}
374
375 private:
376 Decoder* decoder_;
377 const byte* start_;
378 const byte* pc_;
379 uint32_t index_ = 0; // the current index.
380 uint32_t table_count_; // the count of entries, not including default.
381 };
382
383 template <Decoder::ValidateFlag validate>
384 struct MemoryAccessImmediate {
385 uint32_t alignment;
386 uint32_t offset;
387 unsigned length = 0;
MemoryAccessImmediateMemoryAccessImmediate388 inline MemoryAccessImmediate(Decoder* decoder, const byte* pc,
389 uint32_t max_alignment) {
390 unsigned alignment_length;
391 alignment =
392 decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
393 if (!VALIDATE(alignment <= max_alignment)) {
394 decoder->errorf(pc + 1,
395 "invalid alignment; expected maximum alignment is %u, "
396 "actual alignment is %u",
397 max_alignment, alignment);
398 }
399 if (!VALIDATE(decoder->ok())) return;
400 unsigned offset_length;
401 offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
402 &offset_length, "offset");
403 length = alignment_length + offset_length;
404 }
405 };
406
407 // Immediate for SIMD lane operations.
408 template <Decoder::ValidateFlag validate>
409 struct SimdLaneImmediate {
410 uint8_t lane;
411 unsigned length = 1;
412
SimdLaneImmediateSimdLaneImmediate413 inline SimdLaneImmediate(Decoder* decoder, const byte* pc) {
414 lane = decoder->read_u8<validate>(pc + 2, "lane");
415 }
416 };
417
418 // Immediate for SIMD shift operations.
419 template <Decoder::ValidateFlag validate>
420 struct SimdShiftImmediate {
421 uint8_t shift;
422 unsigned length = 1;
423
SimdShiftImmediateSimdShiftImmediate424 inline SimdShiftImmediate(Decoder* decoder, const byte* pc) {
425 shift = decoder->read_u8<validate>(pc + 2, "shift");
426 }
427 };
428
429 // Immediate for SIMD S8x16 shuffle operations.
430 template <Decoder::ValidateFlag validate>
431 struct Simd8x16ShuffleImmediate {
432 uint8_t shuffle[kSimd128Size] = {0};
433
Simd8x16ShuffleImmediateSimd8x16ShuffleImmediate434 inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) {
435 for (uint32_t i = 0; i < kSimd128Size; ++i) {
436 shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
437 if (!VALIDATE(decoder->ok())) return;
438 }
439 }
440 };
441
442 // An entry on the value stack.
443 struct ValueBase {
444 const byte* pc;
445 ValueType type;
446
447 // Named constructors.
UnreachableValueBase448 static ValueBase Unreachable(const byte* pc) { return {pc, kWasmVar}; }
449
NewValueBase450 static ValueBase New(const byte* pc, ValueType type) { return {pc, type}; }
451 };
452
453 template <typename Value>
454 struct Merge {
455 uint32_t arity;
456 union {
457 Value* array;
458 Value first;
459 } vals; // Either multiple values or a single value.
460
461 // Tracks whether this merge was ever reached. Uses precise reachability, like
462 // Reachability::kReachable.
463 bool reached;
464
reachedMerge465 Merge(bool reached = false) : reached(reached) {}
466
467 Value& operator[](uint32_t i) {
468 DCHECK_GT(arity, i);
469 return arity == 1 ? vals.first : vals.array[i];
470 }
471 };
472
473 enum ControlKind : uint8_t {
474 kControlIf,
475 kControlIfElse,
476 kControlBlock,
477 kControlLoop,
478 kControlTry,
479 kControlTryCatch
480 };
481
482 enum Reachability : uint8_t {
483 // reachable code.
484 kReachable,
485 // reachable code in unreachable block (implies normal validation).
486 kSpecOnlyReachable,
487 // code unreachable in its own block (implies polymorphic validation).
488 kUnreachable
489 };
490
491 // An entry on the control stack (i.e. if, block, loop, or try).
492 template <typename Value>
493 struct ControlBase {
494 ControlKind kind;
495 uint32_t stack_depth; // stack height at the beginning of the construct.
496 const byte* pc;
497 Reachability reachability = kReachable;
498
499 // Values merged into the start or end of this control construct.
500 Merge<Value> start_merge;
501 Merge<Value> end_merge;
502
503 ControlBase() = default;
ControlBaseControlBase504 ControlBase(ControlKind kind, uint32_t stack_depth, const byte* pc)
505 : kind(kind), stack_depth(stack_depth), pc(pc) {}
506
507 // Check whether the current block is reachable.
reachableControlBase508 bool reachable() const { return reachability == kReachable; }
509
510 // Check whether the rest of the block is unreachable.
511 // Note that this is different from {!reachable()}, as there is also the
512 // "indirect unreachable state", for which both {reachable()} and
513 // {unreachable()} return false.
unreachableControlBase514 bool unreachable() const { return reachability == kUnreachable; }
515
516 // Return the reachability of new control structs started in this block.
innerReachabilityControlBase517 Reachability innerReachability() const {
518 return reachability == kReachable ? kReachable : kSpecOnlyReachable;
519 }
520
is_ifControlBase521 bool is_if() const { return is_onearmed_if() || is_if_else(); }
is_onearmed_ifControlBase522 bool is_onearmed_if() const { return kind == kControlIf; }
is_if_elseControlBase523 bool is_if_else() const { return kind == kControlIfElse; }
is_blockControlBase524 bool is_block() const { return kind == kControlBlock; }
is_loopControlBase525 bool is_loop() const { return kind == kControlLoop; }
is_tryControlBase526 bool is_try() const { return is_incomplete_try() || is_try_catch(); }
is_incomplete_tryControlBase527 bool is_incomplete_try() const { return kind == kControlTry; }
is_try_catchControlBase528 bool is_try_catch() const { return kind == kControlTryCatch; }
529
br_mergeControlBase530 inline Merge<Value>* br_merge() {
531 return is_loop() ? &this->start_merge : &this->end_merge;
532 }
533
534 // Named constructors.
BlockControlBase535 static ControlBase Block(const byte* pc, uint32_t stack_depth) {
536 return {kControlBlock, stack_depth, pc};
537 }
538
IfControlBase539 static ControlBase If(const byte* pc, uint32_t stack_depth) {
540 return {kControlIf, stack_depth, pc};
541 }
542
LoopControlBase543 static ControlBase Loop(const byte* pc, uint32_t stack_depth) {
544 return {kControlLoop, stack_depth, pc};
545 }
546
TryControlBase547 static ControlBase Try(const byte* pc, uint32_t stack_depth) {
548 return {kControlTry, stack_depth, pc};
549 }
550 };
551
552 #define CONCRETE_NAMED_CONSTRUCTOR(concrete_type, abstract_type, name) \
553 template <typename... Args> \
554 static concrete_type name(Args&&... args) { \
555 concrete_type val; \
556 static_cast<abstract_type&>(val) = \
557 abstract_type::name(std::forward<Args>(args)...); \
558 return val; \
559 }
560
561 // Provide the default named constructors, which default-initialize the
562 // ConcreteType and the initialize the fields of ValueBase correctly.
563 // Use like this:
564 // struct Value : public ValueWithNamedConstructors<Value> { int new_field; };
565 template <typename ConcreteType>
566 struct ValueWithNamedConstructors : public ValueBase {
567 // Named constructors.
568 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, Unreachable)
569 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, New)
570 };
571
572 // Provide the default named constructors, which default-initialize the
573 // ConcreteType and the initialize the fields of ControlBase correctly.
574 // Use like this:
575 // struct Control : public ControlWithNamedConstructors<Control, Value> {
576 // int my_uninitialized_field;
577 // char* other_field = nullptr;
578 // };
579 template <typename ConcreteType, typename Value>
580 struct ControlWithNamedConstructors : public ControlBase<Value> {
581 // Named constructors.
582 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Block)
583 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, If)
584 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Loop)
585 CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Try)
586 };
587
588 // This is the list of callback functions that an interface for the
589 // WasmFullDecoder should implement.
590 // F(Name, args...)
591 #define INTERFACE_FUNCTIONS(F) \
592 /* General: */ \
593 F(StartFunction) \
594 F(StartFunctionBody, Control* block) \
595 F(FinishFunction) \
596 F(OnFirstError) \
597 F(NextInstruction, WasmOpcode) \
598 /* Control: */ \
599 F(Block, Control* block) \
600 F(Loop, Control* block) \
601 F(Try, Control* block) \
602 F(If, const Value& cond, Control* if_block) \
603 F(FallThruTo, Control* c) \
604 F(PopControl, Control* block) \
605 F(EndControl, Control* block) \
606 /* Instructions: */ \
607 F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result) \
608 F(BinOp, WasmOpcode opcode, FunctionSig*, const Value& lhs, \
609 const Value& rhs, Value* result) \
610 F(I32Const, Value* result, int32_t value) \
611 F(I64Const, Value* result, int64_t value) \
612 F(F32Const, Value* result, float value) \
613 F(F64Const, Value* result, double value) \
614 F(RefNull, Value* result) \
615 F(Drop, const Value& value) \
616 F(DoReturn, Vector<Value> values, bool implicit) \
617 F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm) \
618 F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm) \
619 F(TeeLocal, const Value& value, Value* result, \
620 const LocalIndexImmediate<validate>& imm) \
621 F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm) \
622 F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \
623 F(Unreachable) \
624 F(Select, const Value& cond, const Value& fval, const Value& tval, \
625 Value* result) \
626 F(Br, Control* target) \
627 F(BrIf, const Value& cond, Control* target) \
628 F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key) \
629 F(Else, Control* if_block) \
630 F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm, \
631 const Value& index, Value* result) \
632 F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm, \
633 const Value& index, const Value& value) \
634 F(CurrentMemoryPages, Value* result) \
635 F(GrowMemory, const Value& value, Value* result) \
636 F(CallDirect, const CallFunctionImmediate<validate>& imm, \
637 const Value args[], Value returns[]) \
638 F(CallIndirect, const Value& index, \
639 const CallIndirectImmediate<validate>& imm, const Value args[], \
640 Value returns[]) \
641 F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result) \
642 F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm, \
643 const Vector<Value> inputs, Value* result) \
644 F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm, \
645 const Value& input, Value* result) \
646 F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm, \
647 const Value& input0, const Value& input1, Value* result) \
648 F(Throw, const ExceptionIndexImmediate<validate>&, Control* block, \
649 const Vector<Value>& args) \
650 F(CatchException, const ExceptionIndexImmediate<validate>& imm, \
651 Control* block, Vector<Value> caught_values) \
652 F(AtomicOp, WasmOpcode opcode, Vector<Value> args, \
653 const MemoryAccessImmediate<validate>& imm, Value* result)
654
655 // Generic Wasm bytecode decoder with utilities for decoding immediates,
656 // lengths, etc.
657 template <Decoder::ValidateFlag validate>
658 class WasmDecoder : public Decoder {
659 public:
660 WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start,
661 const byte* end, uint32_t buffer_offset = 0)
Decoder(start,end,buffer_offset)662 : Decoder(start, end, buffer_offset),
663 module_(module),
664 sig_(sig),
665 local_types_(nullptr) {}
666 const WasmModule* module_;
667 FunctionSig* sig_;
668
669 ZoneVector<ValueType>* local_types_;
670
total_locals()671 uint32_t total_locals() const {
672 return local_types_ == nullptr
673 ? 0
674 : static_cast<uint32_t>(local_types_->size());
675 }
676
DecodeLocals(Decoder * decoder,const FunctionSig * sig,ZoneVector<ValueType> * type_list)677 static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
678 ZoneVector<ValueType>* type_list) {
679 DCHECK_NOT_NULL(type_list);
680 DCHECK_EQ(0, type_list->size());
681 // Initialize from signature.
682 if (sig != nullptr) {
683 type_list->assign(sig->parameters().begin(), sig->parameters().end());
684 }
685 // Decode local declarations, if any.
686 uint32_t entries = decoder->consume_u32v("local decls count");
687 if (decoder->failed()) return false;
688
689 TRACE("local decls count: %u\n", entries);
690 while (entries-- > 0 && VALIDATE(decoder->ok()) && decoder->more()) {
691 uint32_t count = decoder->consume_u32v("local count");
692 if (decoder->failed()) return false;
693
694 DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals);
695 if (count > kV8MaxWasmFunctionLocals - type_list->size()) {
696 decoder->error(decoder->pc() - 1, "local count too large");
697 return false;
698 }
699 byte code = decoder->consume_u8("local type");
700 if (decoder->failed()) return false;
701
702 ValueType type;
703 switch (code) {
704 case kLocalI32:
705 type = kWasmI32;
706 break;
707 case kLocalI64:
708 type = kWasmI64;
709 break;
710 case kLocalF32:
711 type = kWasmF32;
712 break;
713 case kLocalF64:
714 type = kWasmF64;
715 break;
716 case kLocalAnyRef:
717 if (FLAG_experimental_wasm_anyref) {
718 type = kWasmAnyRef;
719 break;
720 }
721 decoder->error(decoder->pc() - 1, "invalid local type");
722 return false;
723 case kLocalS128:
724 if (FLAG_experimental_wasm_simd) {
725 type = kWasmS128;
726 break;
727 }
728 V8_FALLTHROUGH;
729 default:
730 decoder->error(decoder->pc() - 1, "invalid local type");
731 return false;
732 }
733 type_list->insert(type_list->end(), count, type);
734 }
735 DCHECK(decoder->ok());
736 return true;
737 }
738
AnalyzeLoopAssignment(Decoder * decoder,const byte * pc,uint32_t locals_count,Zone * zone)739 static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
740 uint32_t locals_count, Zone* zone) {
741 if (pc >= decoder->end()) return nullptr;
742 if (*pc != kExprLoop) return nullptr;
743
744 // The number of locals_count is augmented by 2 so that 'locals_count - 2'
745 // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
746 BitVector* assigned = new (zone) BitVector(locals_count, zone);
747 int depth = 0;
748 // Iteratively process all AST nodes nested inside the loop.
749 while (pc < decoder->end() && VALIDATE(decoder->ok())) {
750 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
751 unsigned length = 1;
752 switch (opcode) {
753 case kExprLoop:
754 case kExprIf:
755 case kExprBlock:
756 case kExprTry:
757 length = OpcodeLength(decoder, pc);
758 depth++;
759 break;
760 case kExprSetLocal: // fallthru
761 case kExprTeeLocal: {
762 LocalIndexImmediate<Decoder::kValidate> imm(decoder, pc);
763 if (assigned->length() > 0 &&
764 imm.index < static_cast<uint32_t>(assigned->length())) {
765 // Unverified code might have an out-of-bounds index.
766 assigned->Add(imm.index);
767 }
768 length = 1 + imm.length;
769 break;
770 }
771 case kExprGrowMemory:
772 case kExprCallFunction:
773 case kExprCallIndirect:
774 // Add instance cache nodes to the assigned set.
775 // TODO(titzer): make this more clear.
776 assigned->Add(locals_count - 1);
777 length = OpcodeLength(decoder, pc);
778 break;
779 case kExprEnd:
780 depth--;
781 break;
782 default:
783 length = OpcodeLength(decoder, pc);
784 break;
785 }
786 if (depth <= 0) break;
787 pc += length;
788 }
789 return VALIDATE(decoder->ok()) ? assigned : nullptr;
790 }
791
Validate(const byte * pc,LocalIndexImmediate<Decoder::kValidate> & imm)792 inline bool Validate(const byte* pc,
793 LocalIndexImmediate<Decoder::kValidate>& imm) {
794 if (!VALIDATE(imm.index < total_locals())) {
795 errorf(pc + 1, "invalid local index: %u", imm.index);
796 return false;
797 }
798 imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt;
799 return true;
800 }
801
Validate(const byte * pc,ExceptionIndexImmediate<validate> & imm)802 inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
803 if (!VALIDATE(module_ != nullptr &&
804 imm.index < module_->exceptions.size())) {
805 errorf(pc + 1, "Invalid exception index: %u", imm.index);
806 return false;
807 }
808 imm.exception = &module_->exceptions[imm.index];
809 return true;
810 }
811
Validate(const byte * pc,GlobalIndexImmediate<validate> & imm)812 inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
813 if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) {
814 errorf(pc + 1, "invalid global index: %u", imm.index);
815 return false;
816 }
817 imm.global = &module_->globals[imm.index];
818 imm.type = imm.global->type;
819 return true;
820 }
821
Complete(const byte * pc,CallFunctionImmediate<validate> & imm)822 inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) {
823 if (!VALIDATE(module_ != nullptr &&
824 imm.index < module_->functions.size())) {
825 return false;
826 }
827 imm.sig = module_->functions[imm.index].sig;
828 return true;
829 }
830
Validate(const byte * pc,CallFunctionImmediate<validate> & imm)831 inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
832 if (Complete(pc, imm)) {
833 return true;
834 }
835 errorf(pc + 1, "invalid function index: %u", imm.index);
836 return false;
837 }
838
Complete(const byte * pc,CallIndirectImmediate<validate> & imm)839 inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) {
840 if (!VALIDATE(module_ != nullptr &&
841 imm.sig_index < module_->signatures.size())) {
842 return false;
843 }
844 imm.sig = module_->signatures[imm.sig_index];
845 return true;
846 }
847
Validate(const byte * pc,CallIndirectImmediate<validate> & imm)848 inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
849 if (!VALIDATE(module_ != nullptr && !module_->function_tables.empty())) {
850 error("function table has to exist to execute call_indirect");
851 return false;
852 }
853 if (!Complete(pc, imm)) {
854 errorf(pc + 1, "invalid signature index: #%u", imm.sig_index);
855 return false;
856 }
857 return true;
858 }
859
Validate(const byte * pc,BreakDepthImmediate<validate> & imm,size_t control_depth)860 inline bool Validate(const byte* pc, BreakDepthImmediate<validate>& imm,
861 size_t control_depth) {
862 if (!VALIDATE(imm.depth < control_depth)) {
863 errorf(pc + 1, "invalid break depth: %u", imm.depth);
864 return false;
865 }
866 return true;
867 }
868
Validate(const byte * pc,BranchTableImmediate<validate> & imm,size_t block_depth)869 bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
870 size_t block_depth) {
871 if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) {
872 errorf(pc + 1, "invalid table count (> max function size): %u",
873 imm.table_count);
874 return false;
875 }
876 return checkAvailable(imm.table_count);
877 }
878
Validate(const byte * pc,WasmOpcode opcode,SimdLaneImmediate<validate> & imm)879 inline bool Validate(const byte* pc, WasmOpcode opcode,
880 SimdLaneImmediate<validate>& imm) {
881 uint8_t num_lanes = 0;
882 switch (opcode) {
883 case kExprF32x4ExtractLane:
884 case kExprF32x4ReplaceLane:
885 case kExprI32x4ExtractLane:
886 case kExprI32x4ReplaceLane:
887 num_lanes = 4;
888 break;
889 case kExprI16x8ExtractLane:
890 case kExprI16x8ReplaceLane:
891 num_lanes = 8;
892 break;
893 case kExprI8x16ExtractLane:
894 case kExprI8x16ReplaceLane:
895 num_lanes = 16;
896 break;
897 default:
898 UNREACHABLE();
899 break;
900 }
901 if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
902 error(pc_ + 2, "invalid lane index");
903 return false;
904 } else {
905 return true;
906 }
907 }
908
Validate(const byte * pc,WasmOpcode opcode,SimdShiftImmediate<validate> & imm)909 inline bool Validate(const byte* pc, WasmOpcode opcode,
910 SimdShiftImmediate<validate>& imm) {
911 uint8_t max_shift = 0;
912 switch (opcode) {
913 case kExprI32x4Shl:
914 case kExprI32x4ShrS:
915 case kExprI32x4ShrU:
916 max_shift = 32;
917 break;
918 case kExprI16x8Shl:
919 case kExprI16x8ShrS:
920 case kExprI16x8ShrU:
921 max_shift = 16;
922 break;
923 case kExprI8x16Shl:
924 case kExprI8x16ShrS:
925 case kExprI8x16ShrU:
926 max_shift = 8;
927 break;
928 default:
929 UNREACHABLE();
930 break;
931 }
932 if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) {
933 error(pc_ + 2, "invalid shift amount");
934 return false;
935 } else {
936 return true;
937 }
938 }
939
Validate(const byte * pc,Simd8x16ShuffleImmediate<validate> & imm)940 inline bool Validate(const byte* pc,
941 Simd8x16ShuffleImmediate<validate>& imm) {
942 uint8_t max_lane = 0;
943 for (uint32_t i = 0; i < kSimd128Size; ++i)
944 max_lane = std::max(max_lane, imm.shuffle[i]);
945 // Shuffle indices must be in [0..31] for a 16 lane shuffle.
946 if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
947 error(pc_ + 2, "invalid shuffle mask");
948 return false;
949 }
950 return true;
951 }
952
OpcodeLength(Decoder * decoder,const byte * pc)953 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
954 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
955 switch (opcode) {
956 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
957 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
958 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
959 #undef DECLARE_OPCODE_CASE
960 {
961 MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX);
962 return 1 + imm.length;
963 }
964 case kExprBr:
965 case kExprBrIf: {
966 BreakDepthImmediate<validate> imm(decoder, pc);
967 return 1 + imm.length;
968 }
969 case kExprSetGlobal:
970 case kExprGetGlobal: {
971 GlobalIndexImmediate<validate> imm(decoder, pc);
972 return 1 + imm.length;
973 }
974
975 case kExprCallFunction: {
976 CallFunctionImmediate<validate> imm(decoder, pc);
977 return 1 + imm.length;
978 }
979 case kExprCallIndirect: {
980 CallIndirectImmediate<validate> imm(decoder, pc);
981 return 1 + imm.length;
982 }
983
984 case kExprTry:
985 case kExprIf: // fall through
986 case kExprLoop:
987 case kExprBlock: {
988 BlockTypeImmediate<validate> imm(decoder, pc);
989 return 1 + imm.length;
990 }
991
992 case kExprThrow:
993 case kExprCatch: {
994 ExceptionIndexImmediate<validate> imm(decoder, pc);
995 return 1 + imm.length;
996 }
997
998 case kExprSetLocal:
999 case kExprTeeLocal:
1000 case kExprGetLocal: {
1001 LocalIndexImmediate<Decoder::kValidate> imm(decoder, pc);
1002 return 1 + imm.length;
1003 }
1004 case kExprBrTable: {
1005 BranchTableImmediate<validate> imm(decoder, pc);
1006 BranchTableIterator<validate> iterator(decoder, imm);
1007 return 1 + iterator.length();
1008 }
1009 case kExprI32Const: {
1010 ImmI32Immediate<validate> imm(decoder, pc);
1011 return 1 + imm.length;
1012 }
1013 case kExprI64Const: {
1014 ImmI64Immediate<validate> imm(decoder, pc);
1015 return 1 + imm.length;
1016 }
1017 case kExprRefNull: {
1018 return 1;
1019 }
1020 case kExprGrowMemory:
1021 case kExprMemorySize: {
1022 MemoryIndexImmediate<validate> imm(decoder, pc);
1023 return 1 + imm.length;
1024 }
1025 case kExprF32Const:
1026 return 5;
1027 case kExprF64Const:
1028 return 9;
1029 case kNumericPrefix:
1030 return 2;
1031 case kSimdPrefix: {
1032 byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
1033 WasmOpcode opcode =
1034 static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
1035 switch (opcode) {
1036 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1037 FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1038 #undef DECLARE_OPCODE_CASE
1039 return 2;
1040 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1041 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1042 #undef DECLARE_OPCODE_CASE
1043 return 3;
1044 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1045 FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1046 #undef DECLARE_OPCODE_CASE
1047 {
1048 MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
1049 return 2 + imm.length;
1050 }
1051 // Shuffles require a byte per lane, or 16 immediate bytes.
1052 case kExprS8x16Shuffle:
1053 return 2 + kSimd128Size;
1054 default:
1055 decoder->error(pc, "invalid SIMD opcode");
1056 return 2;
1057 }
1058 }
1059 case kAtomicPrefix: {
1060 byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
1061 WasmOpcode opcode =
1062 static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
1063 switch (opcode) {
1064 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1065 FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
1066 #undef DECLARE_OPCODE_CASE
1067 {
1068 MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
1069 return 2 + imm.length;
1070 }
1071 default:
1072 decoder->error(pc, "invalid Atomics opcode");
1073 return 2;
1074 }
1075 }
1076 default:
1077 return 1;
1078 }
1079 }
1080
StackEffect(const byte * pc)1081 std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
1082 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1083 // Handle "simple" opcodes with a fixed signature first.
1084 FunctionSig* sig = WasmOpcodes::Signature(opcode);
1085 if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
1086 if (sig) return {sig->parameter_count(), sig->return_count()};
1087
1088 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1089 // clang-format off
1090 switch (opcode) {
1091 case kExprSelect:
1092 return {3, 1};
1093 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
1094 return {2, 0};
1095 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1096 case kExprTeeLocal:
1097 case kExprGrowMemory:
1098 return {1, 1};
1099 case kExprSetLocal:
1100 case kExprSetGlobal:
1101 case kExprDrop:
1102 case kExprBrIf:
1103 case kExprBrTable:
1104 case kExprIf:
1105 return {1, 0};
1106 case kExprGetLocal:
1107 case kExprGetGlobal:
1108 case kExprI32Const:
1109 case kExprI64Const:
1110 case kExprF32Const:
1111 case kExprF64Const:
1112 case kExprRefNull:
1113 case kExprMemorySize:
1114 return {0, 1};
1115 case kExprCallFunction: {
1116 CallFunctionImmediate<validate> imm(this, pc);
1117 CHECK(Complete(pc, imm));
1118 return {imm.sig->parameter_count(), imm.sig->return_count()};
1119 }
1120 case kExprCallIndirect: {
1121 CallIndirectImmediate<validate> imm(this, pc);
1122 CHECK(Complete(pc, imm));
1123 // Indirect calls pop an additional argument for the table index.
1124 return {imm.sig->parameter_count() + 1,
1125 imm.sig->return_count()};
1126 }
1127 case kExprBr:
1128 case kExprBlock:
1129 case kExprLoop:
1130 case kExprEnd:
1131 case kExprElse:
1132 case kExprNop:
1133 case kExprReturn:
1134 case kExprUnreachable:
1135 return {0, 0};
1136 case kNumericPrefix:
1137 case kAtomicPrefix:
1138 case kSimdPrefix: {
1139 opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
1140 switch (opcode) {
1141 case kExprI32AtomicStore:
1142 case kExprI32AtomicStore8U:
1143 case kExprI32AtomicStore16U:
1144 case kExprS128StoreMem:
1145 return {2, 0};
1146 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1147 return {1, 1};
1148 default: {
1149 sig = WasmOpcodes::Signature(opcode);
1150 if (sig) {
1151 return {sig->parameter_count(), sig->return_count()};
1152 }
1153 }
1154 }
1155 V8_FALLTHROUGH;
1156 }
1157 default:
1158 V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
1159 WasmOpcodes::OpcodeName(opcode));
1160 return {0, 0};
1161 }
1162 #undef DECLARE_OPCODE_CASE
1163 // clang-format on
1164 }
1165 };
1166
1167 #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
1168 #define CALL_INTERFACE_IF_REACHABLE(name, ...) \
1169 do { \
1170 DCHECK(!control_.empty()); \
1171 if (VALIDATE(this->ok()) && control_.back().reachable()) { \
1172 interface_.name(this, ##__VA_ARGS__); \
1173 } \
1174 } while (false)
1175 #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...) \
1176 do { \
1177 DCHECK(!control_.empty()); \
1178 if (VALIDATE(this->ok()) && \
1179 (control_.size() == 1 || control_at(1)->reachable())) { \
1180 interface_.name(this, ##__VA_ARGS__); \
1181 } \
1182 } while (false)
1183
1184 template <Decoder::ValidateFlag validate, typename Interface>
1185 class WasmFullDecoder : public WasmDecoder<validate> {
1186 using Value = typename Interface::Value;
1187 using Control = typename Interface::Control;
1188 using MergeValues = Merge<Value>;
1189
1190 // All Value types should be trivially copyable for performance. We push, pop,
1191 // and store them in local variables.
1192 ASSERT_TRIVIALLY_COPYABLE(Value);
1193
1194 public:
1195 template <typename... InterfaceArgs>
WasmFullDecoder(Zone * zone,const wasm::WasmModule * module,const FunctionBody & body,InterfaceArgs &&...interface_args)1196 WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
1197 const FunctionBody& body, InterfaceArgs&&... interface_args)
1198 : WasmDecoder<validate>(module, body.sig, body.start, body.end,
1199 body.offset),
1200 zone_(zone),
1201 interface_(std::forward<InterfaceArgs>(interface_args)...),
1202 local_type_vec_(zone),
1203 stack_(zone),
1204 control_(zone),
1205 args_(zone),
1206 last_end_found_(false) {
1207 this->local_types_ = &local_type_vec_;
1208 }
1209
interface()1210 Interface& interface() { return interface_; }
1211
Decode()1212 bool Decode() {
1213 DCHECK(stack_.empty());
1214 DCHECK(control_.empty());
1215
1216 base::ElapsedTimer decode_timer;
1217 if (FLAG_trace_wasm_decode_time) {
1218 decode_timer.Start();
1219 }
1220
1221 if (this->end_ < this->pc_) {
1222 this->error("function body end < start");
1223 return false;
1224 }
1225
1226 DCHECK_EQ(0, this->local_types_->size());
1227 WasmDecoder<validate>::DecodeLocals(this, this->sig_, this->local_types_);
1228 CALL_INTERFACE(StartFunction);
1229 DecodeFunctionBody();
1230 if (!this->failed()) CALL_INTERFACE(FinishFunction);
1231
1232 if (this->failed()) return this->TraceFailed();
1233
1234 if (!control_.empty()) {
1235 // Generate a better error message whether the unterminated control
1236 // structure is the function body block or an innner structure.
1237 if (control_.size() > 1) {
1238 this->error(control_.back().pc, "unterminated control structure");
1239 } else {
1240 this->error("function body must end with \"end\" opcode");
1241 }
1242 return TraceFailed();
1243 }
1244
1245 if (!last_end_found_) {
1246 this->error("function body must end with \"end\" opcode");
1247 return false;
1248 }
1249
1250 if (FLAG_trace_wasm_decode_time) {
1251 double ms = decode_timer.Elapsed().InMillisecondsF();
1252 PrintF("wasm-decode %s (%0.3f ms)\n\n",
1253 VALIDATE(this->ok()) ? "ok" : "failed", ms);
1254 } else {
1255 TRACE("wasm-decode %s\n\n", VALIDATE(this->ok()) ? "ok" : "failed");
1256 }
1257
1258 return true;
1259 }
1260
TraceFailed()1261 bool TraceFailed() {
1262 TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_offset_,
1263 this->GetBufferRelativeOffset(this->error_offset_),
1264 this->error_msg_.c_str());
1265 return false;
1266 }
1267
SafeOpcodeNameAt(const byte * pc)1268 const char* SafeOpcodeNameAt(const byte* pc) {
1269 if (pc >= this->end_) return "<end>";
1270 return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
1271 }
1272
zone()1273 inline Zone* zone() const { return zone_; }
1274
NumLocals()1275 inline uint32_t NumLocals() {
1276 return static_cast<uint32_t>(local_type_vec_.size());
1277 }
1278
GetLocalType(uint32_t index)1279 inline ValueType GetLocalType(uint32_t index) {
1280 return local_type_vec_[index];
1281 }
1282
position()1283 inline wasm::WasmCodePosition position() {
1284 int offset = static_cast<int>(this->pc_ - this->start_);
1285 DCHECK_EQ(this->pc_ - this->start_, offset); // overflows cannot happen
1286 return offset;
1287 }
1288
control_depth()1289 inline uint32_t control_depth() const {
1290 return static_cast<uint32_t>(control_.size());
1291 }
1292
control_at(uint32_t depth)1293 inline Control* control_at(uint32_t depth) {
1294 DCHECK_GT(control_.size(), depth);
1295 return &control_.back() - depth;
1296 }
1297
stack_size()1298 inline uint32_t stack_size() const {
1299 DCHECK_GE(kMaxUInt32, stack_.size());
1300 return static_cast<uint32_t>(stack_.size());
1301 }
1302
stack_value(uint32_t depth)1303 inline Value* stack_value(uint32_t depth) {
1304 DCHECK_GT(stack_.size(), depth);
1305 return &stack_[stack_.size() - depth - 1];
1306 }
1307
GetMergeValueFromStack(Control * c,Merge<Value> * merge,uint32_t i)1308 inline Value& GetMergeValueFromStack(
1309 Control* c, Merge<Value>* merge, uint32_t i) {
1310 DCHECK(merge == &c->start_merge || merge == &c->end_merge);
1311 DCHECK_GT(merge->arity, i);
1312 DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
1313 return stack_[stack_.size() - merge->arity + i];
1314 }
1315
1316 private:
1317 static constexpr size_t kErrorMsgSize = 128;
1318
1319 Zone* zone_;
1320
1321 Interface interface_;
1322
1323 ZoneVector<ValueType> local_type_vec_; // types of local variables.
1324 ZoneVector<Value> stack_; // stack of values.
1325 ZoneVector<Control> control_; // stack of blocks, loops, and ifs.
1326 ZoneVector<Value> args_; // parameters of current block or call
1327 bool last_end_found_;
1328
CheckHasMemory()1329 bool CheckHasMemory() {
1330 if (!VALIDATE(this->module_->has_memory)) {
1331 this->error(this->pc_ - 1, "memory instruction with no memory");
1332 return false;
1333 }
1334 return true;
1335 }
1336
CheckHasSharedMemory()1337 bool CheckHasSharedMemory() {
1338 if (!VALIDATE(this->module_->has_shared_memory)) {
1339 this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
1340 return false;
1341 }
1342 return true;
1343 }
1344
1345 class TraceLine {
1346 public:
1347 static constexpr int kMaxLen = 512;
~TraceLine()1348 ~TraceLine() {
1349 if (!FLAG_trace_wasm_decoder) return;
1350 PrintF("%.*s\n", len_, buffer_);
1351 }
1352
1353 // Appends a formatted string.
1354 PRINTF_FORMAT(2, 3)
Append(const char * format,...)1355 void Append(const char* format, ...) {
1356 if (!FLAG_trace_wasm_decoder) return;
1357 va_list va_args;
1358 va_start(va_args, format);
1359 size_t remaining_len = kMaxLen - len_;
1360 Vector<char> remaining_msg_space(buffer_ + len_, remaining_len);
1361 int len = VSNPrintF(remaining_msg_space, format, va_args);
1362 va_end(va_args);
1363 len_ += len < 0 ? remaining_len : len;
1364 }
1365
1366 private:
1367 char buffer_[kMaxLen];
1368 int len_ = 0;
1369 };
1370
1371 // Decodes the body of a function.
DecodeFunctionBody()1372 void DecodeFunctionBody() {
1373 TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
1374 reinterpret_cast<const void*>(this->start()),
1375 reinterpret_cast<const void*>(this->end()), this->pc_offset(),
1376 static_cast<int>(this->end() - this->start()));
1377
1378 // Set up initial function block.
1379 {
1380 auto* c = PushBlock();
1381 InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); });
1382 InitMerge(&c->end_merge,
1383 static_cast<uint32_t>(this->sig_->return_count()),
1384 [&] (uint32_t i) {
1385 return Value::New(this->pc_, this->sig_->GetReturn(i)); });
1386 CALL_INTERFACE(StartFunctionBody, c);
1387 }
1388
1389 while (this->pc_ < this->end_) { // decoding loop.
1390 unsigned len = 1;
1391 WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
1392
1393 CALL_INTERFACE_IF_REACHABLE(NextInstruction, opcode);
1394
1395 #if DEBUG
1396 TraceLine trace_msg;
1397 #define TRACE_PART(...) trace_msg.Append(__VA_ARGS__)
1398 if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
1399 TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1400 WasmOpcodes::OpcodeName(opcode));
1401 }
1402 #else
1403 #define TRACE_PART(...)
1404 #endif
1405
1406 FunctionSig* sig = WasmOpcodes::Signature(opcode);
1407 if (sig) {
1408 BuildSimpleOperator(opcode, sig);
1409 } else {
1410 // Complex bytecode.
1411 switch (opcode) {
1412 case kExprNop:
1413 break;
1414 case kExprBlock: {
1415 BlockTypeImmediate<validate> imm(this, this->pc_);
1416 if (!LookupBlockType(&imm)) break;
1417 PopArgs(imm.sig);
1418 auto* block = PushBlock();
1419 SetBlockType(block, imm);
1420 CALL_INTERFACE_IF_REACHABLE(Block, block);
1421 PushMergeValues(block, &block->start_merge);
1422 len = 1 + imm.length;
1423 break;
1424 }
1425 case kExprRethrow: {
1426 // TODO(kschimpf): Implement.
1427 CHECK_PROTOTYPE_OPCODE(eh);
1428 OPCODE_ERROR(opcode, "not implemented yet");
1429 break;
1430 }
1431 case kExprThrow: {
1432 CHECK_PROTOTYPE_OPCODE(eh);
1433 ExceptionIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1434 len = 1 + imm.length;
1435 if (!this->Validate(this->pc_, imm)) break;
1436 PopArgs(imm.exception->ToFunctionSig());
1437 CALL_INTERFACE_IF_REACHABLE(Throw, imm, &control_.back(),
1438 vec2vec(args_));
1439 EndControl();
1440 break;
1441 }
1442 case kExprTry: {
1443 CHECK_PROTOTYPE_OPCODE(eh);
1444 BlockTypeImmediate<validate> imm(this, this->pc_);
1445 if (!LookupBlockType(&imm)) break;
1446 PopArgs(imm.sig);
1447 auto* try_block = PushTry();
1448 SetBlockType(try_block, imm);
1449 len = 1 + imm.length;
1450 CALL_INTERFACE_IF_REACHABLE(Try, try_block);
1451 PushMergeValues(try_block, &try_block->start_merge);
1452 break;
1453 }
1454 case kExprCatch: {
1455 // TODO(kschimpf): Fix to use type signature of exception.
1456 CHECK_PROTOTYPE_OPCODE(eh);
1457 ExceptionIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1458 len = 1 + imm.length;
1459
1460 if (!this->Validate(this->pc_, imm)) break;
1461
1462 if (!VALIDATE(!control_.empty())) {
1463 this->error("catch does not match any try");
1464 break;
1465 }
1466
1467 Control* c = &control_.back();
1468 if (!VALIDATE(c->is_try())) {
1469 this->error("catch does not match any try");
1470 break;
1471 }
1472
1473 if (!VALIDATE(c->is_incomplete_try())) {
1474 OPCODE_ERROR(opcode, "multiple catch blocks not implemented");
1475 break;
1476 }
1477 c->kind = kControlTryCatch;
1478 FallThruTo(c);
1479 stack_.resize(c->stack_depth);
1480 const WasmExceptionSig* sig = imm.exception->sig;
1481 for (size_t i = 0, e = sig->parameter_count(); i < e; ++i) {
1482 Push(sig->GetParam(i));
1483 }
1484 Vector<Value> values(stack_.data() + c->stack_depth,
1485 sig->parameter_count());
1486 CALL_INTERFACE_IF_PARENT_REACHABLE(CatchException, imm, c, values);
1487 c->reachability = control_at(1)->innerReachability();
1488 break;
1489 }
1490 case kExprCatchAll: {
1491 // TODO(kschimpf): Implement.
1492 CHECK_PROTOTYPE_OPCODE(eh);
1493 OPCODE_ERROR(opcode, "not implemented yet");
1494 break;
1495 }
1496 case kExprLoop: {
1497 BlockTypeImmediate<validate> imm(this, this->pc_);
1498 if (!LookupBlockType(&imm)) break;
1499 PopArgs(imm.sig);
1500 auto* block = PushLoop();
1501 SetBlockType(&control_.back(), imm);
1502 len = 1 + imm.length;
1503 CALL_INTERFACE_IF_REACHABLE(Loop, block);
1504 PushMergeValues(block, &block->start_merge);
1505 break;
1506 }
1507 case kExprIf: {
1508 BlockTypeImmediate<validate> imm(this, this->pc_);
1509 if (!LookupBlockType(&imm)) break;
1510 auto cond = Pop(0, kWasmI32);
1511 PopArgs(imm.sig);
1512 if (!VALIDATE(this->ok())) break;
1513 auto* if_block = PushIf();
1514 SetBlockType(if_block, imm);
1515 CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
1516 len = 1 + imm.length;
1517 PushMergeValues(if_block, &if_block->start_merge);
1518 break;
1519 }
1520 case kExprElse: {
1521 if (!VALIDATE(!control_.empty())) {
1522 this->error("else does not match any if");
1523 break;
1524 }
1525 Control* c = &control_.back();
1526 if (!VALIDATE(c->is_if())) {
1527 this->error(this->pc_, "else does not match an if");
1528 break;
1529 }
1530 if (c->is_if_else()) {
1531 this->error(this->pc_, "else already present for if");
1532 break;
1533 }
1534 FallThruTo(c);
1535 c->kind = kControlIfElse;
1536 CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
1537 PushMergeValues(c, &c->start_merge);
1538 c->reachability = control_at(1)->innerReachability();
1539 break;
1540 }
1541 case kExprEnd: {
1542 if (!VALIDATE(!control_.empty())) {
1543 this->error("end does not match any if, try, or block");
1544 return;
1545 }
1546 Control* c = &control_.back();
1547 if (!VALIDATE(!c->is_incomplete_try())) {
1548 this->error(this->pc_, "missing catch in try");
1549 break;
1550 }
1551 if (c->is_onearmed_if()) {
1552 // Emulate empty else arm.
1553 FallThruTo(c);
1554 if (this->failed()) break;
1555 CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
1556 PushMergeValues(c, &c->start_merge);
1557 c->reachability = control_at(1)->innerReachability();
1558 }
1559
1560 FallThruTo(c);
1561 // A loop just leaves the values on the stack.
1562 if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
1563
1564 if (control_.size() == 1) {
1565 // If at the last (implicit) control, check we are at end.
1566 if (!VALIDATE(this->pc_ + 1 == this->end_)) {
1567 this->error(this->pc_ + 1, "trailing code after function end");
1568 break;
1569 }
1570 last_end_found_ = true;
1571 // The result of the block is the return value.
1572 TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_),
1573 "(implicit) return");
1574 DoReturn(c, true);
1575 }
1576
1577 PopControl(c);
1578 break;
1579 }
1580 case kExprSelect: {
1581 auto cond = Pop(2, kWasmI32);
1582 auto fval = Pop();
1583 auto tval = Pop(0, fval.type);
1584 auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
1585 CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
1586 break;
1587 }
1588 case kExprBr: {
1589 BreakDepthImmediate<validate> imm(this, this->pc_);
1590 if (!this->Validate(this->pc_, imm, control_.size())) break;
1591 Control* c = control_at(imm.depth);
1592 if (!TypeCheckBreak(c)) break;
1593 if (control_.back().reachable()) {
1594 CALL_INTERFACE(Br, c);
1595 c->br_merge()->reached = true;
1596 }
1597 len = 1 + imm.length;
1598 EndControl();
1599 break;
1600 }
1601 case kExprBrIf: {
1602 BreakDepthImmediate<validate> imm(this, this->pc_);
1603 auto cond = Pop(0, kWasmI32);
1604 if (this->failed()) break;
1605 if (!this->Validate(this->pc_, imm, control_.size())) break;
1606 Control* c = control_at(imm.depth);
1607 if (!TypeCheckBreak(c)) break;
1608 if (control_.back().reachable()) {
1609 CALL_INTERFACE(BrIf, cond, c);
1610 c->br_merge()->reached = true;
1611 }
1612 len = 1 + imm.length;
1613 break;
1614 }
1615 case kExprBrTable: {
1616 BranchTableImmediate<validate> imm(this, this->pc_);
1617 BranchTableIterator<validate> iterator(this, imm);
1618 auto key = Pop(0, kWasmI32);
1619 if (this->failed()) break;
1620 if (!this->Validate(this->pc_, imm, control_.size())) break;
1621 uint32_t br_arity = 0;
1622 std::vector<bool> br_targets(control_.size());
1623 while (iterator.has_next()) {
1624 const uint32_t i = iterator.cur_index();
1625 const byte* pos = iterator.pc();
1626 uint32_t target = iterator.next();
1627 if (!VALIDATE(target < control_.size())) {
1628 this->errorf(pos,
1629 "improper branch in br_table target %u (depth %u)",
1630 i, target);
1631 break;
1632 }
1633 // Avoid redundant break target checks.
1634 if (br_targets[target]) continue;
1635 br_targets[target] = true;
1636 // Check that label types match up.
1637 Control* c = control_at(target);
1638 uint32_t arity = c->br_merge()->arity;
1639 if (i == 0) {
1640 br_arity = arity;
1641 } else if (!VALIDATE(br_arity == arity)) {
1642 this->errorf(pos,
1643 "inconsistent arity in br_table target %u"
1644 " (previous was %u, this one %u)",
1645 i, br_arity, arity);
1646 }
1647 if (!TypeCheckBreak(c)) break;
1648 }
1649 if (this->failed()) break;
1650
1651 if (control_.back().reachable()) {
1652 CALL_INTERFACE(BrTable, imm, key);
1653
1654 for (uint32_t depth = control_depth(); depth-- > 0;) {
1655 if (!br_targets[depth]) continue;
1656 control_at(depth)->br_merge()->reached = true;
1657 }
1658 }
1659
1660 len = 1 + iterator.length();
1661 EndControl();
1662 break;
1663 }
1664 case kExprReturn: {
1665 DoReturn(&control_.back(), false);
1666 break;
1667 }
1668 case kExprUnreachable: {
1669 CALL_INTERFACE_IF_REACHABLE(Unreachable);
1670 EndControl();
1671 break;
1672 }
1673 case kExprI32Const: {
1674 ImmI32Immediate<validate> imm(this, this->pc_);
1675 auto* value = Push(kWasmI32);
1676 CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value);
1677 len = 1 + imm.length;
1678 break;
1679 }
1680 case kExprI64Const: {
1681 ImmI64Immediate<validate> imm(this, this->pc_);
1682 auto* value = Push(kWasmI64);
1683 CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value);
1684 len = 1 + imm.length;
1685 break;
1686 }
1687 case kExprF32Const: {
1688 ImmF32Immediate<validate> imm(this, this->pc_);
1689 auto* value = Push(kWasmF32);
1690 CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value);
1691 len = 1 + imm.length;
1692 break;
1693 }
1694 case kExprF64Const: {
1695 ImmF64Immediate<validate> imm(this, this->pc_);
1696 auto* value = Push(kWasmF64);
1697 CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value);
1698 len = 1 + imm.length;
1699 break;
1700 }
1701 case kExprRefNull: {
1702 CHECK_PROTOTYPE_OPCODE(anyref);
1703 auto* value = Push(kWasmAnyRef);
1704 CALL_INTERFACE_IF_REACHABLE(RefNull, value);
1705 len = 1;
1706 break;
1707 }
1708 case kExprGetLocal: {
1709 LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1710 if (!this->Validate(this->pc_, imm)) break;
1711 auto* value = Push(imm.type);
1712 CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm);
1713 len = 1 + imm.length;
1714 break;
1715 }
1716 case kExprSetLocal: {
1717 LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1718 if (!this->Validate(this->pc_, imm)) break;
1719 auto value = Pop(0, local_type_vec_[imm.index]);
1720 CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm);
1721 len = 1 + imm.length;
1722 break;
1723 }
1724 case kExprTeeLocal: {
1725 LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1726 if (!this->Validate(this->pc_, imm)) break;
1727 auto value = Pop(0, local_type_vec_[imm.index]);
1728 auto* result = Push(value.type);
1729 CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm);
1730 len = 1 + imm.length;
1731 break;
1732 }
1733 case kExprDrop: {
1734 auto value = Pop();
1735 CALL_INTERFACE_IF_REACHABLE(Drop, value);
1736 break;
1737 }
1738 case kExprGetGlobal: {
1739 GlobalIndexImmediate<validate> imm(this, this->pc_);
1740 len = 1 + imm.length;
1741 if (!this->Validate(this->pc_, imm)) break;
1742 auto* result = Push(imm.type);
1743 CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm);
1744 break;
1745 }
1746 case kExprSetGlobal: {
1747 GlobalIndexImmediate<validate> imm(this, this->pc_);
1748 len = 1 + imm.length;
1749 if (!this->Validate(this->pc_, imm)) break;
1750 if (!VALIDATE(imm.global->mutability)) {
1751 this->errorf(this->pc_, "immutable global #%u cannot be assigned",
1752 imm.index);
1753 break;
1754 }
1755 auto value = Pop(0, imm.type);
1756 CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm);
1757 break;
1758 }
1759 case kExprI32LoadMem8S:
1760 len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
1761 break;
1762 case kExprI32LoadMem8U:
1763 len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
1764 break;
1765 case kExprI32LoadMem16S:
1766 len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
1767 break;
1768 case kExprI32LoadMem16U:
1769 len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
1770 break;
1771 case kExprI32LoadMem:
1772 len = 1 + DecodeLoadMem(LoadType::kI32Load);
1773 break;
1774 case kExprI64LoadMem8S:
1775 len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
1776 break;
1777 case kExprI64LoadMem8U:
1778 len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
1779 break;
1780 case kExprI64LoadMem16S:
1781 len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
1782 break;
1783 case kExprI64LoadMem16U:
1784 len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
1785 break;
1786 case kExprI64LoadMem32S:
1787 len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
1788 break;
1789 case kExprI64LoadMem32U:
1790 len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
1791 break;
1792 case kExprI64LoadMem:
1793 len = 1 + DecodeLoadMem(LoadType::kI64Load);
1794 break;
1795 case kExprF32LoadMem:
1796 len = 1 + DecodeLoadMem(LoadType::kF32Load);
1797 break;
1798 case kExprF64LoadMem:
1799 len = 1 + DecodeLoadMem(LoadType::kF64Load);
1800 break;
1801 case kExprI32StoreMem8:
1802 len = 1 + DecodeStoreMem(StoreType::kI32Store8);
1803 break;
1804 case kExprI32StoreMem16:
1805 len = 1 + DecodeStoreMem(StoreType::kI32Store16);
1806 break;
1807 case kExprI32StoreMem:
1808 len = 1 + DecodeStoreMem(StoreType::kI32Store);
1809 break;
1810 case kExprI64StoreMem8:
1811 len = 1 + DecodeStoreMem(StoreType::kI64Store8);
1812 break;
1813 case kExprI64StoreMem16:
1814 len = 1 + DecodeStoreMem(StoreType::kI64Store16);
1815 break;
1816 case kExprI64StoreMem32:
1817 len = 1 + DecodeStoreMem(StoreType::kI64Store32);
1818 break;
1819 case kExprI64StoreMem:
1820 len = 1 + DecodeStoreMem(StoreType::kI64Store);
1821 break;
1822 case kExprF32StoreMem:
1823 len = 1 + DecodeStoreMem(StoreType::kF32Store);
1824 break;
1825 case kExprF64StoreMem:
1826 len = 1 + DecodeStoreMem(StoreType::kF64Store);
1827 break;
1828 case kExprGrowMemory: {
1829 if (!CheckHasMemory()) break;
1830 MemoryIndexImmediate<validate> imm(this, this->pc_);
1831 len = 1 + imm.length;
1832 DCHECK_NOT_NULL(this->module_);
1833 if (!VALIDATE(this->module_->is_wasm())) {
1834 this->error("grow_memory is not supported for asmjs modules");
1835 break;
1836 }
1837 auto value = Pop(0, kWasmI32);
1838 auto* result = Push(kWasmI32);
1839 CALL_INTERFACE_IF_REACHABLE(GrowMemory, value, result);
1840 break;
1841 }
1842 case kExprMemorySize: {
1843 if (!CheckHasMemory()) break;
1844 MemoryIndexImmediate<validate> imm(this, this->pc_);
1845 auto* result = Push(kWasmI32);
1846 len = 1 + imm.length;
1847 CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
1848 break;
1849 }
1850 case kExprCallFunction: {
1851 CallFunctionImmediate<validate> imm(this, this->pc_);
1852 len = 1 + imm.length;
1853 if (!this->Validate(this->pc_, imm)) break;
1854 // TODO(clemensh): Better memory management.
1855 PopArgs(imm.sig);
1856 auto* returns = PushReturns(imm.sig);
1857 CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns);
1858 break;
1859 }
1860 case kExprCallIndirect: {
1861 CallIndirectImmediate<validate> imm(this, this->pc_);
1862 len = 1 + imm.length;
1863 if (!this->Validate(this->pc_, imm)) break;
1864 auto index = Pop(0, kWasmI32);
1865 PopArgs(imm.sig);
1866 auto* returns = PushReturns(imm.sig);
1867 CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(),
1868 returns);
1869 break;
1870 }
1871 case kNumericPrefix: {
1872 CHECK_PROTOTYPE_OPCODE(sat_f2i_conversions);
1873 ++len;
1874 byte numeric_index = this->template read_u8<validate>(
1875 this->pc_ + 1, "numeric index");
1876 opcode = static_cast<WasmOpcode>(opcode << 8 | numeric_index);
1877 TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1878 WasmOpcodes::OpcodeName(opcode));
1879 sig = WasmOpcodes::Signature(opcode);
1880 if (sig == nullptr) {
1881 this->errorf(this->pc_, "Unrecognized numeric opcode: %x\n",
1882 opcode);
1883 return;
1884 }
1885 BuildSimpleOperator(opcode, sig);
1886 break;
1887 }
1888 case kSimdPrefix: {
1889 CHECK_PROTOTYPE_OPCODE(simd);
1890 len++;
1891 byte simd_index =
1892 this->template read_u8<validate>(this->pc_ + 1, "simd index");
1893 opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
1894 TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1895 WasmOpcodes::OpcodeName(opcode));
1896 len += DecodeSimdOpcode(opcode);
1897 break;
1898 }
1899 case kAtomicPrefix: {
1900 CHECK_PROTOTYPE_OPCODE(threads);
1901 if (!CheckHasSharedMemory()) break;
1902 len++;
1903 byte atomic_index =
1904 this->template read_u8<validate>(this->pc_ + 1, "atomic index");
1905 opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
1906 TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1907 WasmOpcodes::OpcodeName(opcode));
1908 len += DecodeAtomicOpcode(opcode);
1909 break;
1910 }
1911 default: {
1912 // Deal with special asmjs opcodes.
1913 if (this->module_ != nullptr && this->module_->is_asm_js()) {
1914 sig = WasmOpcodes::AsmjsSignature(opcode);
1915 if (sig) {
1916 BuildSimpleOperator(opcode, sig);
1917 }
1918 } else {
1919 this->error("Invalid opcode");
1920 return;
1921 }
1922 }
1923 }
1924 }
1925
1926 #if DEBUG
1927 if (FLAG_trace_wasm_decoder) {
1928 TRACE_PART(" ");
1929 for (Control& c : control_) {
1930 switch (c.kind) {
1931 case kControlIf:
1932 TRACE_PART("I");
1933 break;
1934 case kControlBlock:
1935 TRACE_PART("B");
1936 break;
1937 case kControlLoop:
1938 TRACE_PART("L");
1939 break;
1940 case kControlTry:
1941 TRACE_PART("T");
1942 break;
1943 default:
1944 break;
1945 }
1946 if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity);
1947 TRACE_PART("%u", c.end_merge.arity);
1948 if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#');
1949 }
1950 TRACE_PART(" | ");
1951 for (size_t i = 0; i < stack_.size(); ++i) {
1952 auto& val = stack_[i];
1953 WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
1954 if (WasmOpcodes::IsPrefixOpcode(opcode)) {
1955 opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
1956 }
1957 TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type),
1958 static_cast<int>(val.pc - this->start_),
1959 WasmOpcodes::OpcodeName(opcode));
1960 // If the decoder failed, don't try to decode the immediates, as this
1961 // can trigger a DCHECK failure.
1962 if (this->failed()) continue;
1963 switch (opcode) {
1964 case kExprI32Const: {
1965 ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
1966 TRACE_PART("[%d]", imm.value);
1967 break;
1968 }
1969 case kExprGetLocal:
1970 case kExprSetLocal:
1971 case kExprTeeLocal: {
1972 LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
1973 TRACE_PART("[%u]", imm.index);
1974 break;
1975 }
1976 case kExprGetGlobal:
1977 case kExprSetGlobal: {
1978 GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
1979 TRACE_PART("[%u]", imm.index);
1980 break;
1981 }
1982 default:
1983 break;
1984 }
1985 }
1986 }
1987 #endif
1988 this->pc_ += len;
1989 } // end decode loop
1990 if (!VALIDATE(this->pc_ == this->end_) && this->ok()) {
1991 this->error("Beyond end of code");
1992 }
1993 }
1994
EndControl()1995 void EndControl() {
1996 DCHECK(!control_.empty());
1997 auto* current = &control_.back();
1998 stack_.resize(current->stack_depth);
1999 CALL_INTERFACE_IF_REACHABLE(EndControl, current);
2000 current->reachability = kUnreachable;
2001 }
2002
LookupBlockType(BlockTypeImmediate<validate> * imm)2003 bool LookupBlockType(BlockTypeImmediate<validate>* imm) {
2004 if (imm->type == kWasmVar) {
2005 if (!VALIDATE(this->module_ &&
2006 imm->sig_index < this->module_->signatures.size())) {
2007 this->errorf(
2008 this->pc_, "block type index %u out of bounds (%d signatures)",
2009 imm->sig_index,
2010 static_cast<int>(this->module_ ? this->module_->signatures.size()
2011 : 0));
2012 return false;
2013 }
2014 imm->sig = this->module_->signatures[imm->sig_index];
2015 }
2016 return true;
2017 }
2018
2019 template<typename func>
InitMerge(Merge<Value> * merge,uint32_t arity,func get_val)2020 void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) {
2021 merge->arity = arity;
2022 if (arity == 1) {
2023 merge->vals.first = get_val(0);
2024 } else if (arity > 1) {
2025 merge->vals.array = zone_->NewArray<Value>(arity);
2026 for (unsigned i = 0; i < arity; i++) {
2027 merge->vals.array[i] = get_val(i);
2028 }
2029 }
2030 }
2031
SetBlockType(Control * c,BlockTypeImmediate<validate> & imm)2032 void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) {
2033 DCHECK_EQ(imm.in_arity(), this->args_.size());
2034 const byte* pc = this->pc_;
2035 Value* args = this->args_.data();
2036 InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
2037 return Value::New(pc, imm.out_type(i));
2038 });
2039 InitMerge(&c->start_merge, imm.in_arity(),
2040 [args](uint32_t i) { return args[i]; });
2041 }
2042
2043 // Pops arguments as required by signature into {args_}.
PopArgs(FunctionSig * sig)2044 V8_INLINE void PopArgs(FunctionSig* sig) {
2045 int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
2046 args_.resize(count);
2047 for (int i = count - 1; i >= 0; --i) {
2048 args_[i] = Pop(i, sig->GetParam(i));
2049 }
2050 }
2051
GetReturnType(FunctionSig * sig)2052 ValueType GetReturnType(FunctionSig* sig) {
2053 DCHECK_GE(1, sig->return_count());
2054 return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
2055 }
2056
PushControl(Control && new_control)2057 Control* PushControl(Control&& new_control) {
2058 Reachability reachability =
2059 control_.empty() ? kReachable : control_.back().innerReachability();
2060 control_.emplace_back(std::move(new_control));
2061 Control* c = &control_.back();
2062 c->reachability = reachability;
2063 c->start_merge.reached = c->reachable();
2064 return c;
2065 }
2066
PushBlock()2067 Control* PushBlock() {
2068 return PushControl(Control::Block(this->pc_, stack_size()));
2069 }
PushLoop()2070 Control* PushLoop() {
2071 return PushControl(Control::Loop(this->pc_, stack_size()));
2072 }
PushIf()2073 Control* PushIf() {
2074 return PushControl(Control::If(this->pc_, stack_size()));
2075 }
PushTry()2076 Control* PushTry() {
2077 // current_catch_ = static_cast<int32_t>(control_.size() - 1);
2078 return PushControl(Control::Try(this->pc_, stack_size()));
2079 }
2080
PopControl(Control * c)2081 void PopControl(Control* c) {
2082 DCHECK_EQ(c, &control_.back());
2083 CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
2084 bool reached = c->end_merge.reached;
2085 control_.pop_back();
2086 // If the parent block was reachable before, but the popped control does not
2087 // return to here, this block becomes indirectly unreachable.
2088 if (!control_.empty() && !reached && control_.back().reachable()) {
2089 control_.back().reachability = kSpecOnlyReachable;
2090 }
2091 }
2092
2093 int DecodeLoadMem(LoadType type, int prefix_len = 0) {
2094 if (!CheckHasMemory()) return 0;
2095 MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
2096 type.size_log_2());
2097 auto index = Pop(0, kWasmI32);
2098 auto* result = Push(type.value_type());
2099 CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
2100 return imm.length;
2101 }
2102
2103 int DecodeStoreMem(StoreType store, int prefix_len = 0) {
2104 if (!CheckHasMemory()) return 0;
2105 MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
2106 store.size_log_2());
2107 auto value = Pop(1, store.value_type());
2108 auto index = Pop(0, kWasmI32);
2109 CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
2110 return imm.length;
2111 }
2112
SimdExtractLane(WasmOpcode opcode,ValueType type)2113 unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
2114 SimdLaneImmediate<validate> imm(this, this->pc_);
2115 if (this->Validate(this->pc_, opcode, imm)) {
2116 Value inputs[] = {Pop(0, kWasmS128)};
2117 auto* result = Push(type);
2118 CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
2119 result);
2120 }
2121 return imm.length;
2122 }
2123
SimdReplaceLane(WasmOpcode opcode,ValueType type)2124 unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
2125 SimdLaneImmediate<validate> imm(this, this->pc_);
2126 if (this->Validate(this->pc_, opcode, imm)) {
2127 Value inputs[2];
2128 inputs[1] = Pop(1, type);
2129 inputs[0] = Pop(0, kWasmS128);
2130 auto* result = Push(kWasmS128);
2131 CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
2132 result);
2133 }
2134 return imm.length;
2135 }
2136
SimdShiftOp(WasmOpcode opcode)2137 unsigned SimdShiftOp(WasmOpcode opcode) {
2138 SimdShiftImmediate<validate> imm(this, this->pc_);
2139 if (this->Validate(this->pc_, opcode, imm)) {
2140 auto input = Pop(0, kWasmS128);
2141 auto* result = Push(kWasmS128);
2142 CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
2143 }
2144 return imm.length;
2145 }
2146
Simd8x16ShuffleOp()2147 unsigned Simd8x16ShuffleOp() {
2148 Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
2149 if (this->Validate(this->pc_, imm)) {
2150 auto input1 = Pop(1, kWasmS128);
2151 auto input0 = Pop(0, kWasmS128);
2152 auto* result = Push(kWasmS128);
2153 CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
2154 result);
2155 }
2156 return 16;
2157 }
2158
DecodeSimdOpcode(WasmOpcode opcode)2159 unsigned DecodeSimdOpcode(WasmOpcode opcode) {
2160 unsigned len = 0;
2161 switch (opcode) {
2162 case kExprF32x4ExtractLane: {
2163 len = SimdExtractLane(opcode, kWasmF32);
2164 break;
2165 }
2166 case kExprI32x4ExtractLane:
2167 case kExprI16x8ExtractLane:
2168 case kExprI8x16ExtractLane: {
2169 len = SimdExtractLane(opcode, kWasmI32);
2170 break;
2171 }
2172 case kExprF32x4ReplaceLane: {
2173 len = SimdReplaceLane(opcode, kWasmF32);
2174 break;
2175 }
2176 case kExprI32x4ReplaceLane:
2177 case kExprI16x8ReplaceLane:
2178 case kExprI8x16ReplaceLane: {
2179 len = SimdReplaceLane(opcode, kWasmI32);
2180 break;
2181 }
2182 case kExprI32x4Shl:
2183 case kExprI32x4ShrS:
2184 case kExprI32x4ShrU:
2185 case kExprI16x8Shl:
2186 case kExprI16x8ShrS:
2187 case kExprI16x8ShrU:
2188 case kExprI8x16Shl:
2189 case kExprI8x16ShrS:
2190 case kExprI8x16ShrU: {
2191 len = SimdShiftOp(opcode);
2192 break;
2193 }
2194 case kExprS8x16Shuffle: {
2195 len = Simd8x16ShuffleOp();
2196 break;
2197 }
2198 case kExprS128LoadMem:
2199 len = DecodeLoadMem(LoadType::kS128Load, 1);
2200 break;
2201 case kExprS128StoreMem:
2202 len = DecodeStoreMem(StoreType::kS128Store, 1);
2203 break;
2204 default: {
2205 FunctionSig* sig = WasmOpcodes::Signature(opcode);
2206 if (!VALIDATE(sig != nullptr)) {
2207 this->error("invalid simd opcode");
2208 break;
2209 }
2210 PopArgs(sig);
2211 auto* results =
2212 sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
2213 CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, vec2vec(args_), results);
2214 }
2215 }
2216 return len;
2217 }
2218
DecodeAtomicOpcode(WasmOpcode opcode)2219 unsigned DecodeAtomicOpcode(WasmOpcode opcode) {
2220 unsigned len = 0;
2221 ValueType ret_type;
2222 FunctionSig* sig = WasmOpcodes::Signature(opcode);
2223 if (sig != nullptr) {
2224 MachineType memtype;
2225 switch (opcode) {
2226 #define CASE_ATOMIC_STORE_OP(Name, Type) \
2227 case kExpr##Name: { \
2228 memtype = MachineType::Type(); \
2229 ret_type = kWasmStmt; \
2230 break; \
2231 }
2232 ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
2233 #undef CASE_ATOMIC_OP
2234 #define CASE_ATOMIC_OP(Name, Type) \
2235 case kExpr##Name: { \
2236 memtype = MachineType::Type(); \
2237 ret_type = GetReturnType(sig); \
2238 break; \
2239 }
2240 ATOMIC_OP_LIST(CASE_ATOMIC_OP)
2241 #undef CASE_ATOMIC_OP
2242 default:
2243 this->error("invalid atomic opcode");
2244 return 0;
2245 }
2246 MemoryAccessImmediate<validate> imm(
2247 this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
2248 len += imm.length;
2249 PopArgs(sig);
2250 auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
2251 CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, vec2vec(args_), imm,
2252 result);
2253 } else {
2254 this->error("invalid atomic opcode");
2255 }
2256 return len;
2257 }
2258
DoReturn(Control * c,bool implicit)2259 void DoReturn(Control* c, bool implicit) {
2260 int return_count = static_cast<int>(this->sig_->return_count());
2261 args_.resize(return_count);
2262
2263 // Pop return values off the stack in reverse order.
2264 for (int i = return_count - 1; i >= 0; --i) {
2265 args_[i] = Pop(i, this->sig_->GetReturn(i));
2266 }
2267
2268 // Simulate that an implicit return morally comes after the current block.
2269 if (implicit && c->end_merge.reached) c->reachability = kReachable;
2270 CALL_INTERFACE_IF_REACHABLE(DoReturn, vec2vec(args_), implicit);
2271
2272 EndControl();
2273 }
2274
Push(ValueType type)2275 inline Value* Push(ValueType type) {
2276 DCHECK_NE(kWasmStmt, type);
2277 stack_.push_back(Value::New(this->pc_, type));
2278 return &stack_.back();
2279 }
2280
PushMergeValues(Control * c,Merge<Value> * merge)2281 void PushMergeValues(Control* c, Merge<Value>* merge) {
2282 DCHECK_EQ(c, &control_.back());
2283 DCHECK(merge == &c->start_merge || merge == &c->end_merge);
2284 stack_.resize(c->stack_depth);
2285 if (merge->arity == 1) {
2286 stack_.push_back(merge->vals.first);
2287 } else {
2288 for (unsigned i = 0; i < merge->arity; i++) {
2289 stack_.push_back(merge->vals.array[i]);
2290 }
2291 }
2292 DCHECK_EQ(c->stack_depth + merge->arity, stack_.size());
2293 }
2294
PushReturns(FunctionSig * sig)2295 Value* PushReturns(FunctionSig* sig) {
2296 size_t return_count = sig->return_count();
2297 if (return_count == 0) return nullptr;
2298 size_t old_size = stack_.size();
2299 for (size_t i = 0; i < return_count; ++i) {
2300 Push(sig->GetReturn(i));
2301 }
2302 return stack_.data() + old_size;
2303 }
2304
Pop(int index,ValueType expected)2305 Value Pop(int index, ValueType expected) {
2306 auto val = Pop();
2307 if (!VALIDATE(val.type == expected || val.type == kWasmVar ||
2308 expected == kWasmVar)) {
2309 this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
2310 SafeOpcodeNameAt(this->pc_), index,
2311 ValueTypes::TypeName(expected), SafeOpcodeNameAt(val.pc),
2312 ValueTypes::TypeName(val.type));
2313 }
2314 return val;
2315 }
2316
Pop()2317 Value Pop() {
2318 DCHECK(!control_.empty());
2319 uint32_t limit = control_.back().stack_depth;
2320 if (stack_.size() <= limit) {
2321 // Popping past the current control start in reachable code.
2322 if (!VALIDATE(control_.back().unreachable())) {
2323 this->errorf(this->pc_, "%s found empty stack",
2324 SafeOpcodeNameAt(this->pc_));
2325 }
2326 return Value::Unreachable(this->pc_);
2327 }
2328 auto val = stack_.back();
2329 stack_.pop_back();
2330 return val;
2331 }
2332
startrel(const byte * ptr)2333 int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
2334
FallThruTo(Control * c)2335 void FallThruTo(Control* c) {
2336 DCHECK_EQ(c, &control_.back());
2337 if (!TypeCheckFallThru(c)) return;
2338 if (!c->reachable()) return;
2339
2340 if (!c->is_loop()) CALL_INTERFACE(FallThruTo, c);
2341 c->end_merge.reached = true;
2342 }
2343
TypeCheckMergeValues(Control * c,Merge<Value> * merge)2344 bool TypeCheckMergeValues(Control* c, Merge<Value>* merge) {
2345 DCHECK(merge == &c->start_merge || merge == &c->end_merge);
2346 DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
2347 // Typecheck the topmost {merge->arity} values on the stack.
2348 for (uint32_t i = 0; i < merge->arity; ++i) {
2349 auto& val = GetMergeValueFromStack(c, merge, i);
2350 auto& old = (*merge)[i];
2351 if (val.type != old.type) {
2352 // If {val.type} is polymorphic, which results from unreachable, make
2353 // it more specific by using the merge value's expected type.
2354 // If it is not polymorphic, this is a type error.
2355 if (!VALIDATE(val.type == kWasmVar)) {
2356 this->errorf(
2357 this->pc_, "type error in merge[%u] (expected %s, got %s)", i,
2358 ValueTypes::TypeName(old.type), ValueTypes::TypeName(val.type));
2359 return false;
2360 }
2361 val.type = old.type;
2362 }
2363 }
2364
2365 return true;
2366 }
2367
TypeCheckFallThru(Control * c)2368 bool TypeCheckFallThru(Control* c) {
2369 DCHECK_EQ(c, &control_.back());
2370 if (!validate) return true;
2371 uint32_t expected = c->end_merge.arity;
2372 DCHECK_GE(stack_.size(), c->stack_depth);
2373 uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
2374 // Fallthrus must match the arity of the control exactly.
2375 if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
2376 this->errorf(
2377 this->pc_,
2378 "expected %u elements on the stack for fallthru to @%d, found %u",
2379 expected, startrel(c->pc), actual);
2380 return false;
2381 }
2382
2383 return TypeCheckMergeValues(c, &c->end_merge);
2384 }
2385
TypeCheckBreak(Control * c)2386 bool TypeCheckBreak(Control* c) {
2387 // Breaks must have at least the number of values expected; can have more.
2388 uint32_t expected = c->br_merge()->arity;
2389 DCHECK_GE(stack_.size(), control_.back().stack_depth);
2390 uint32_t actual =
2391 static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
2392 if (!InsertUnreachablesIfNecessary(expected, actual)) {
2393 this->errorf(this->pc_,
2394 "expected %u elements on the stack for br to @%d, found %u",
2395 expected, startrel(c->pc), actual);
2396 return false;
2397 }
2398 return TypeCheckMergeValues(c, c->br_merge());
2399 }
2400
InsertUnreachablesIfNecessary(uint32_t expected,uint32_t actual)2401 inline bool InsertUnreachablesIfNecessary(uint32_t expected,
2402 uint32_t actual) {
2403 if (V8_LIKELY(actual >= expected)) {
2404 return true; // enough actual values are there.
2405 }
2406 if (!VALIDATE(control_.back().unreachable())) {
2407 // There aren't enough values on the stack.
2408 return false;
2409 }
2410 // A slow path. When the actual number of values on the stack is less
2411 // than the expected number of values and the current control is
2412 // unreachable, insert unreachable values below the actual values.
2413 // This simplifies {TypeCheckMergeValues}.
2414 auto pos = stack_.begin() + (stack_.size() - actual);
2415 stack_.insert(pos, (expected - actual), Value::Unreachable(this->pc_));
2416 return true;
2417 }
2418
onFirstError()2419 virtual void onFirstError() {
2420 this->end_ = this->pc_; // Terminate decoding loop.
2421 TRACE(" !%s\n", this->error_msg_.c_str());
2422 CALL_INTERFACE(OnFirstError);
2423 }
2424
BuildSimpleOperator(WasmOpcode opcode,FunctionSig * sig)2425 inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
2426 if (WasmOpcodes::IsSignExtensionOpcode(opcode)) {
2427 RET_ON_PROTOTYPE_OPCODE(se);
2428 }
2429 if (WasmOpcodes::IsAnyRefOpcode(opcode)) {
2430 RET_ON_PROTOTYPE_OPCODE(anyref);
2431 }
2432
2433 switch (sig->parameter_count()) {
2434 case 1: {
2435 auto val = Pop(0, sig->GetParam(0));
2436 auto* ret =
2437 sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
2438 CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, sig, val, ret);
2439 break;
2440 }
2441 case 2: {
2442 auto rval = Pop(1, sig->GetParam(1));
2443 auto lval = Pop(0, sig->GetParam(0));
2444 auto* ret =
2445 sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
2446 CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, sig, lval, rval, ret);
2447 break;
2448 }
2449 default:
2450 UNREACHABLE();
2451 }
2452 }
2453 };
2454
2455 #undef CALL_INTERFACE
2456 #undef CALL_INTERFACE_IF_REACHABLE
2457 #undef CALL_INTERFACE_IF_PARENT_REACHABLE
2458
2459 class EmptyInterface {
2460 public:
2461 static constexpr wasm::Decoder::ValidateFlag validate =
2462 wasm::Decoder::kValidate;
2463 using Value = ValueBase;
2464 using Control = ControlBase<Value>;
2465 using Decoder = WasmFullDecoder<validate, EmptyInterface>;
2466
2467 #define DEFINE_EMPTY_CALLBACK(name, ...) \
2468 void name(Decoder* decoder, ##__VA_ARGS__) {}
2469 INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
2470 #undef DEFINE_EMPTY_CALLBACK
2471 };
2472
2473 #undef TRACE
2474 #undef TRACE_INST_FORMAT
2475 #undef VALIDATE
2476 #undef CHECK_PROTOTYPE_OPCODE
2477 #undef OPCODE_ERROR
2478
2479 } // namespace wasm
2480 } // namespace internal
2481 } // namespace v8
2482
2483 #endif // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
2484