1 /*
2  * Copyright 2016 WebAssembly Community Group participants
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/interp/binary-reader-interp.h"
18 
19 #include <cassert>
20 #include <cinttypes>
21 #include <cstdarg>
22 #include <cstdio>
23 #include <vector>
24 
25 #include "src/binary-reader-nop.h"
26 #include "src/cast.h"
27 #include "src/feature.h"
28 #include "src/interp/interp.h"
29 #include "src/interp/interp-internal.h"
30 #include "src/stream.h"
31 #include "src/type-checker.h"
32 
33 namespace wabt {
34 
35 using namespace interp;
36 
37 namespace {
38 
39 typedef std::vector<Index> IndexVector;
40 typedef std::vector<IstreamOffset> IstreamOffsetVector;
41 typedef std::vector<IstreamOffsetVector> IstreamOffsetVectorVector;
42 
43 struct Label {
44   Label(IstreamOffset offset, IstreamOffset fixup_offset);
45 
46   IstreamOffset offset;
47   IstreamOffset fixup_offset;
48 };
49 
Label(IstreamOffset offset,IstreamOffset fixup_offset)50 Label::Label(IstreamOffset offset, IstreamOffset fixup_offset)
51     : offset(offset), fixup_offset(fixup_offset) {}
52 
53 struct ElemSegmentInfo {
ElemSegmentInfowabt::__anon6bd9a5f80111::ElemSegmentInfo54   ElemSegmentInfo(Table* table, Index dst) : table(table), dst(dst) {}
55 
56   Table* table;
57   Index dst;
58   std::vector<Index> src;
59 };
60 
61 struct DataSegmentInfo {
DataSegmentInfowabt::__anon6bd9a5f80111::DataSegmentInfo62   DataSegmentInfo(Memory* memory,
63                   Address dst,
64                   const void* src,
65                   IstreamOffset size)
66       : memory(memory), dst(dst), src(src), size(size) {}
67 
68   Memory* memory;
69   Address dst;
70   const void* src;  // Not owned.
71   IstreamOffset size;
72 };
73 
74 class BinaryReaderInterp : public BinaryReaderNop {
75  public:
76   BinaryReaderInterp(Environment* env,
77                      DefinedModule* module,
78                      std::unique_ptr<OutputBuffer> istream,
79                      Errors* errors,
80                      const Features& features);
81 
82   wabt::Result ReadBinary(DefinedModule* out_module);
83 
84   std::unique_ptr<OutputBuffer> ReleaseOutputBuffer();
85 
86   wabt::Result InitializeSegments();
87 
88   // Implement BinaryReader.
89   bool OnError(const Error&) override;
90 
91   wabt::Result OnTypeCount(Index count) override;
92   wabt::Result OnType(Index index,
93                       Index param_count,
94                       Type* param_types,
95                       Index result_count,
96                       Type* result_types) override;
97 
98   wabt::Result OnImportFunc(Index import_index,
99                             string_view module_name,
100                             string_view field_name,
101                             Index func_index,
102                             Index sig_index) override;
103   wabt::Result OnImportTable(Index import_index,
104                              string_view module_name,
105                              string_view field_name,
106                              Index table_index,
107                              Type elem_type,
108                              const Limits* elem_limits) override;
109   wabt::Result OnImportMemory(Index import_index,
110                               string_view module_name,
111                               string_view field_name,
112                               Index memory_index,
113                               const Limits* page_limits) override;
114   wabt::Result OnImportGlobal(Index import_index,
115                               string_view module_name,
116                               string_view field_name,
117                               Index global_index,
118                               Type type,
119                               bool mutable_) override;
120 
121   wabt::Result OnFunctionCount(Index count) override;
122   wabt::Result OnFunction(Index index, Index sig_index) override;
123 
124   wabt::Result OnTable(Index index,
125                        Type elem_type,
126                        const Limits* elem_limits) override;
127 
128   wabt::Result OnMemory(Index index, const Limits* limits) override;
129 
130   wabt::Result OnGlobalCount(Index count) override;
131   wabt::Result BeginGlobal(Index index, Type type, bool mutable_) override;
132   wabt::Result EndGlobalInitExpr(Index index) override;
133 
134   wabt::Result OnExport(Index index,
135                         ExternalKind kind,
136                         Index item_index,
137                         string_view name) override;
138 
139   wabt::Result OnStartFunction(Index func_index) override;
140 
141   wabt::Result BeginFunctionBody(Index index, Offset size) override;
142   wabt::Result OnLocalDeclCount(Index count) override;
143   wabt::Result OnLocalDecl(Index decl_index, Index count, Type type) override;
144 
145   wabt::Result OnOpcode(Opcode Opcode) override;
146   wabt::Result OnAtomicLoadExpr(Opcode opcode,
147                                 uint32_t alignment_log2,
148                                 Address offset) override;
149   wabt::Result OnAtomicStoreExpr(Opcode opcode,
150                                  uint32_t alignment_log2,
151                                  Address offset) override;
152   wabt::Result OnAtomicRmwExpr(Opcode opcode,
153                                uint32_t alignment_log2,
154                                Address offset) override;
155   wabt::Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
156                                       uint32_t alignment_log2,
157                                       Address offset) override;
158   wabt::Result OnAtomicWaitExpr(Opcode opcode,
159                                 uint32_t alignment_log2,
160                                 Address offset) override;
161   wabt::Result OnAtomicNotifyExpr(Opcode opcode,
162                                 uint32_t alignment_log2,
163                                 Address offset) override;
164   wabt::Result OnBinaryExpr(wabt::Opcode opcode) override;
165   wabt::Result OnBlockExpr(Type sig_type) override;
166   wabt::Result OnBrExpr(Index depth) override;
167   wabt::Result OnBrIfExpr(Index depth) override;
168   wabt::Result OnBrTableExpr(Index num_targets,
169                              Index* target_depths,
170                              Index default_target_depth) override;
171   wabt::Result OnCallExpr(Index func_index) override;
172   wabt::Result OnCallIndirectExpr(Index sig_index, Index table_index) override;
173   wabt::Result OnReturnCallExpr(Index func_index) override;
174   wabt::Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override;
175   wabt::Result OnCompareExpr(wabt::Opcode opcode) override;
176   wabt::Result OnConvertExpr(wabt::Opcode opcode) override;
177   wabt::Result OnDropExpr() override;
178   wabt::Result OnElseExpr() override;
179   wabt::Result OnEndExpr() override;
180   wabt::Result OnF32ConstExpr(uint32_t value_bits) override;
181   wabt::Result OnF64ConstExpr(uint64_t value_bits) override;
182   wabt::Result OnV128ConstExpr(v128 value_bits) override;
183   wabt::Result OnGlobalGetExpr(Index global_index) override;
184   wabt::Result OnGlobalSetExpr(Index global_index) override;
185   wabt::Result OnI32ConstExpr(uint32_t value) override;
186   wabt::Result OnI64ConstExpr(uint64_t value) override;
187   wabt::Result OnIfExpr(Type sig_type) override;
188   wabt::Result OnLoadExpr(wabt::Opcode opcode,
189                           uint32_t alignment_log2,
190                           Address offset) override;
191   wabt::Result OnLocalGetExpr(Index local_index) override;
192   wabt::Result OnLocalSetExpr(Index local_index) override;
193   wabt::Result OnLocalTeeExpr(Index local_index) override;
194   wabt::Result OnLoopExpr(Type sig_type) override;
195   wabt::Result OnMemoryCopyExpr() override;
196   wabt::Result OnDataDropExpr(Index segment_index) override;
197   wabt::Result OnMemoryGrowExpr() override;
198   wabt::Result OnMemoryFillExpr() override;
199   wabt::Result OnMemoryInitExpr(Index segment_index) override;
200   wabt::Result OnMemorySizeExpr() override;
201   wabt::Result OnNopExpr() override;
202   wabt::Result OnReturnExpr() override;
203   wabt::Result OnSelectExpr() override;
204   wabt::Result OnStoreExpr(wabt::Opcode opcode,
205                            uint32_t alignment_log2,
206                            Address offset) override;
207   wabt::Result OnUnaryExpr(wabt::Opcode opcode) override;
208   wabt::Result OnTableCopyExpr() override;
209   wabt::Result OnElemDropExpr(Index segment_index) override;
210   wabt::Result OnTableInitExpr(Index segment_index) override;
211   wabt::Result OnTernaryExpr(wabt::Opcode opcode) override;
212   wabt::Result OnUnreachableExpr() override;
213   wabt::Result EndFunctionBody(Index index) override;
214   wabt::Result OnSimdLaneOpExpr(wabt::Opcode opcode, uint64_t value) override;
215   wabt::Result OnSimdShuffleOpExpr(wabt::Opcode opcode, v128 value) override;
216   wabt::Result OnLoadSplatExpr(wabt::Opcode opcode,
217                                uint32_t alignment_log2,
218                                Address offset) override;
219 
220   wabt::Result OnElemSegmentCount(Index count) override;
221   wabt::Result BeginElemSegment(Index index,
222                                 Index table_index,
223                                 bool passive,
224                                 Type elem_type) override;
225   wabt::Result BeginElemSegmentInitExpr(Index index) override;
226   wabt::Result EndElemSegmentInitExpr(Index index) override;
227   wabt::Result OnElemSegmentElemExprCount(Index index, Index count) override;
228   wabt::Result OnElemSegmentElemExpr_RefNull(Index segment_index) override;
229   wabt::Result OnElemSegmentElemExpr_RefFunc(Index segment_index,
230                                              Index func_index) override;
231 
232   wabt::Result OnDataCount(Index count) override;
233   wabt::Result BeginDataSegment(Index index,
234                                 Index memory_index,
235                                 bool passive) override;
236   wabt::Result BeginDataSegmentInitExpr(Index index) override;
237   wabt::Result OnDataSegmentData(Index index,
238                                  const void* data,
239                                  Address size) override;
240 
241   wabt::Result OnInitExprF32ConstExpr(Index index, uint32_t value) override;
242   wabt::Result OnInitExprF64ConstExpr(Index index, uint64_t value) override;
243   wabt::Result OnInitExprV128ConstExpr(Index index, v128 value) override;
244   wabt::Result OnInitExprGlobalGetExpr(Index index,
245                                        Index global_index) override;
246   wabt::Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
247   wabt::Result OnInitExprI64ConstExpr(Index index, uint64_t value) override;
248   wabt::Result OnInitExprRefNull(Index index) override;
249 
250  private:
251   Label* GetLabel(Index depth);
252   Label* TopLabel();
253   void PushLabel(IstreamOffset offset, IstreamOffset fixup_offset);
254   void PopLabel();
255 
256   void PrintError(const char* format, ...);
257 
258   Index TranslateSigIndexToEnv(Index sig_index);
259   void GetBlockSignature(Type sig_type,
260                          TypeVector* out_param_types,
261                          TypeVector* out_result_types);
262   FuncSignature* GetSignatureByModuleIndex(Index sig_index);
263   Index TranslateFuncIndexToEnv(Index func_index);
264   Index TranslateModuleFuncIndexToDefined(Index func_index);
265   Func* GetFuncByModuleIndex(Index func_index);
266   Index TranslateGlobalIndexToEnv(Index global_index);
267   Global* GetGlobalByModuleIndex(Index global_index);
268   Type GetGlobalTypeByModuleIndex(Index global_index);
269   Index TranslateLocalIndex(Index local_index);
270   Type GetLocalTypeByIndex(Func* func, Index local_index);
271   Index TranslateDataSegmentIndexToEnv(Index data_segment_index);
272   Index TranslateElemSegmentIndexToEnv(Index elem_segment_index);
273 
274   IstreamOffset GetIstreamOffset();
275 
276   wabt::Result EmitDataAt(IstreamOffset offset,
277                           const void* data,
278                           IstreamOffset size);
279   wabt::Result EmitData(const void* data, IstreamOffset size);
280   wabt::Result EmitOpcode(Opcode opcode);
281   wabt::Result EmitI8(uint8_t value);
282   wabt::Result EmitI32(uint32_t value);
283   wabt::Result EmitI64(uint64_t value);
284   wabt::Result EmitV128(v128 value);
285   wabt::Result EmitI32At(IstreamOffset offset, uint32_t value);
286   wabt::Result EmitDropKeep(uint32_t drop, uint32_t keep);
287   wabt::Result AppendFixup(IstreamOffsetVectorVector* fixups_vector,
288                            Index index);
289   wabt::Result EmitBrOffset(Index depth, IstreamOffset offset);
290   wabt::Result GetDropCount(Index keep_count,
291                             size_t type_stack_limit,
292                             Index* out_drop_count);
293   wabt::Result GetBrDropKeepCount(Index depth,
294                                   Index* out_drop_count,
295                                   Index* out_keep_count);
296   wabt::Result GetReturnDropKeepCount(Index* out_drop_count,
297                                       Index* out_keep_count);
298   wabt::Result GetReturnCallDropKeepCount(FuncSignature* sig,
299                                           Index keep_extra,
300                                           Index* out_drop_count,
301                                           Index* out_keep_count);
302   wabt::Result EmitBr(Index depth, Index drop_count, Index keep_count);
303   wabt::Result EmitBrTableOffset(Index depth);
304   wabt::Result FixupTopLabel();
305   wabt::Result EmitFuncOffset(DefinedFunc* func, Index func_index);
306 
307   wabt::Result CheckLocal(Index local_index);
308   wabt::Result CheckGlobal(Index global_index);
309   wabt::Result CheckDataSegment(Index data_segment_index);
310   wabt::Result CheckElemSegment(Index elem_segment_index);
311   wabt::Result CheckImportKind(Import* import, ExternalKind expected_kind);
312   wabt::Result CheckImportLimits(const Limits* declared_limits,
313                                  const Limits* actual_limits);
314   wabt::Result CheckHasMemory(wabt::Opcode opcode);
315   wabt::Result CheckHasTable(wabt::Opcode opcode);
316   wabt::Result CheckAlign(uint32_t alignment_log2, Address natural_alignment);
317   wabt::Result CheckAtomicAlign(uint32_t alignment_log2,
318                                 Address natural_alignment);
319   wabt::Result CheckInFunction();
320 
321   wabt::Result AppendExport(Module* module,
322                             ExternalKind kind,
323                             Index item_index,
324                             string_view name);
325   wabt::Result FindRegisteredModule(string_view module_name,
326                                     Module** out_module);
327   wabt::Result GetModuleExport(Module* module,
328                                string_view field_name,
329                                Export** out_export);
330 
331   Features features_;
332   Errors* errors_ = nullptr;
333   Environment* env_ = nullptr;
334   DefinedModule* module_ = nullptr;
335   DefinedFunc* current_func_ = nullptr;
336   TypeChecker typechecker_;
337   std::vector<Label> label_stack_;
338   IstreamOffsetVectorVector func_fixups_;
339   IstreamOffsetVectorVector depth_fixups_;
340   MemoryStream istream_;
341   IstreamOffset istream_offset_ = 0;
342   /* mappings from module index space to env index space; this won't just be a
343    * translation, because imported values will be resolved as well */
344   IndexVector sig_index_mapping_;
345   IndexVector func_index_mapping_;
346   IndexVector global_index_mapping_;
347   IndexVector data_segment_index_mapping_;
348   IndexVector elem_segment_index_mapping_;
349 
350   Index num_func_imports_ = 0;
351   Index num_global_imports_ = 0;
352 
353   // Changes to linear memory and tables should not apply if a validation error
354   // occurs; these vectors cache the changes that must be applied after we know
355   // that there are no validation errors.
356   //
357   // Note that this behavior changed after the bulk memory proposal; in that
358   // case each segment is initialized as it is encountered. If one fails, then
359   // no further segments are processed.
360   std::vector<ElemSegmentInfo> elem_segment_infos_;
361   std::vector<DataSegmentInfo> data_segment_infos_;
362 
363   // Values cached so they can be shared between callbacks.
364   TypedValue init_expr_value_;
365   IstreamOffset table_offset_ = 0;
366   bool segment_is_passive_ = false;
367   ElemSegment* elem_segment_ = nullptr;
368   ElemSegmentInfo* elem_segment_info_ = nullptr;
369 };
370 
BinaryReaderInterp(Environment * env,DefinedModule * module,std::unique_ptr<OutputBuffer> istream,Errors * errors,const Features & features)371 BinaryReaderInterp::BinaryReaderInterp(Environment* env,
372                                        DefinedModule* module,
373                                        std::unique_ptr<OutputBuffer> istream,
374                                        Errors* errors,
375                                        const Features& features)
376     : features_(features),
377       errors_(errors),
378       env_(env),
379       module_(module),
380       istream_(std::move(istream)),
381       istream_offset_(istream_.output_buffer().size()) {
382   typechecker_.set_error_callback(
383       [this](const char* msg) { PrintError("%s", msg); });
384 }
385 
ReleaseOutputBuffer()386 std::unique_ptr<OutputBuffer> BinaryReaderInterp::ReleaseOutputBuffer() {
387   return istream_.ReleaseOutputBuffer();
388 }
389 
GetLabel(Index depth)390 Label* BinaryReaderInterp::GetLabel(Index depth) {
391   assert(depth < label_stack_.size());
392   return &label_stack_[label_stack_.size() - depth - 1];
393 }
394 
TopLabel()395 Label* BinaryReaderInterp::TopLabel() {
396   return GetLabel(0);
397 }
398 
PrintError(const char * format,...)399 void WABT_PRINTF_FORMAT(2, 3) BinaryReaderInterp::PrintError(const char* format,
400                                                              ...) {
401   WABT_SNPRINTF_ALLOCA(buffer, length, format);
402   errors_->emplace_back(ErrorLevel::Error, Location(kInvalidOffset), buffer);
403 }
404 
TranslateSigIndexToEnv(Index sig_index)405 Index BinaryReaderInterp::TranslateSigIndexToEnv(Index sig_index) {
406   assert(sig_index < sig_index_mapping_.size());
407   return sig_index_mapping_[sig_index];
408 }
409 
GetBlockSignature(Type sig_type,TypeVector * out_param_types,TypeVector * out_result_types)410 void BinaryReaderInterp::GetBlockSignature(Type sig_type,
411                                            TypeVector* out_param_types,
412                                            TypeVector* out_result_types) {
413   if (IsTypeIndex(sig_type)) {
414     FuncSignature* func_sig = GetSignatureByModuleIndex(GetTypeIndex(sig_type));
415     *out_param_types = func_sig->param_types;
416     *out_result_types = func_sig->result_types;
417   } else {
418     out_param_types->clear();
419     *out_result_types = GetInlineTypeVector(sig_type);
420   }
421 }
422 
GetSignatureByModuleIndex(Index sig_index)423 FuncSignature* BinaryReaderInterp::GetSignatureByModuleIndex(Index sig_index) {
424   return env_->GetFuncSignature(TranslateSigIndexToEnv(sig_index));
425 }
426 
TranslateFuncIndexToEnv(Index func_index)427 Index BinaryReaderInterp::TranslateFuncIndexToEnv(Index func_index) {
428   assert(func_index < func_index_mapping_.size());
429   return func_index_mapping_[func_index];
430 }
431 
TranslateModuleFuncIndexToDefined(Index func_index)432 Index BinaryReaderInterp::TranslateModuleFuncIndexToDefined(Index func_index) {
433   assert(func_index >= num_func_imports_);
434   return func_index - num_func_imports_;
435 }
436 
GetFuncByModuleIndex(Index func_index)437 Func* BinaryReaderInterp::GetFuncByModuleIndex(Index func_index) {
438   return env_->GetFunc(TranslateFuncIndexToEnv(func_index));
439 }
440 
TranslateGlobalIndexToEnv(Index global_index)441 Index BinaryReaderInterp::TranslateGlobalIndexToEnv(Index global_index) {
442   return global_index_mapping_[global_index];
443 }
444 
GetGlobalByModuleIndex(Index global_index)445 Global* BinaryReaderInterp::GetGlobalByModuleIndex(Index global_index) {
446   return env_->GetGlobal(TranslateGlobalIndexToEnv(global_index));
447 }
448 
GetGlobalTypeByModuleIndex(Index global_index)449 Type BinaryReaderInterp::GetGlobalTypeByModuleIndex(Index global_index) {
450   return GetGlobalByModuleIndex(global_index)->typed_value.type;
451 }
452 
GetLocalTypeByIndex(Func * func,Index local_index)453 Type BinaryReaderInterp::GetLocalTypeByIndex(Func* func, Index local_index) {
454   assert(!func->is_host);
455   return cast<DefinedFunc>(func)->param_and_local_types[local_index];
456 }
457 
TranslateDataSegmentIndexToEnv(Index index)458 Index BinaryReaderInterp::TranslateDataSegmentIndexToEnv(Index index) {
459   return data_segment_index_mapping_[index];
460 }
461 
TranslateElemSegmentIndexToEnv(Index index)462 Index BinaryReaderInterp::TranslateElemSegmentIndexToEnv(Index index) {
463   return elem_segment_index_mapping_[index];
464 }
465 
GetIstreamOffset()466 IstreamOffset BinaryReaderInterp::GetIstreamOffset() {
467   return istream_offset_;
468 }
469 
EmitDataAt(IstreamOffset offset,const void * data,IstreamOffset size)470 wabt::Result BinaryReaderInterp::EmitDataAt(IstreamOffset offset,
471                                             const void* data,
472                                             IstreamOffset size) {
473   istream_.WriteDataAt(offset, data, size);
474   return istream_.result();
475 }
476 
EmitData(const void * data,IstreamOffset size)477 wabt::Result BinaryReaderInterp::EmitData(const void* data,
478                                           IstreamOffset size) {
479   CHECK_RESULT(EmitDataAt(istream_offset_, data, size));
480   istream_offset_ += size;
481   return wabt::Result::Ok;
482 }
483 
EmitOpcode(Opcode opcode)484 wabt::Result BinaryReaderInterp::EmitOpcode(Opcode opcode) {
485   return EmitI32(static_cast<uint32_t>(opcode));
486 }
487 
EmitI8(uint8_t value)488 wabt::Result BinaryReaderInterp::EmitI8(uint8_t value) {
489   return EmitData(&value, sizeof(value));
490 }
491 
EmitI32(uint32_t value)492 wabt::Result BinaryReaderInterp::EmitI32(uint32_t value) {
493   return EmitData(&value, sizeof(value));
494 }
495 
EmitI64(uint64_t value)496 wabt::Result BinaryReaderInterp::EmitI64(uint64_t value) {
497   return EmitData(&value, sizeof(value));
498 }
499 
EmitV128(v128 value)500 wabt::Result BinaryReaderInterp::EmitV128(v128 value) {
501   return EmitData(&value, sizeof(value));
502 }
503 
EmitI32At(IstreamOffset offset,uint32_t value)504 wabt::Result BinaryReaderInterp::EmitI32At(IstreamOffset offset,
505                                            uint32_t value) {
506   return EmitDataAt(offset, &value, sizeof(value));
507 }
508 
EmitDropKeep(uint32_t drop,uint32_t keep)509 wabt::Result BinaryReaderInterp::EmitDropKeep(uint32_t drop, uint32_t keep) {
510   assert(drop != UINT32_MAX);
511   assert(keep != UINT32_MAX);
512   if (drop > 0) {
513     if (drop == 1 && keep == 0) {
514       CHECK_RESULT(EmitOpcode(Opcode::Drop));
515     } else {
516       CHECK_RESULT(EmitOpcode(Opcode::InterpDropKeep));
517       CHECK_RESULT(EmitI32(drop));
518       CHECK_RESULT(EmitI32(keep));
519     }
520   }
521   return wabt::Result::Ok;
522 }
523 
AppendFixup(IstreamOffsetVectorVector * fixups_vector,Index index)524 wabt::Result BinaryReaderInterp::AppendFixup(
525     IstreamOffsetVectorVector* fixups_vector,
526     Index index) {
527   if (index >= fixups_vector->size()) {
528     fixups_vector->resize(index + 1);
529   }
530   (*fixups_vector)[index].push_back(GetIstreamOffset());
531   return wabt::Result::Ok;
532 }
533 
EmitBrOffset(Index depth,IstreamOffset offset)534 wabt::Result BinaryReaderInterp::EmitBrOffset(Index depth,
535                                               IstreamOffset offset) {
536   if (offset == kInvalidIstreamOffset) {
537     /* depth_fixups_ stores the depth counting up from zero, where zero is the
538      * top-level function scope. */
539     depth = label_stack_.size() - 1 - depth;
540     CHECK_RESULT(AppendFixup(&depth_fixups_, depth));
541   }
542   CHECK_RESULT(EmitI32(offset));
543   return wabt::Result::Ok;
544 }
545 
GetDropCount(Index keep_count,size_t type_stack_limit,Index * out_drop_count)546 wabt::Result BinaryReaderInterp::GetDropCount(Index keep_count,
547                                               size_t type_stack_limit,
548                                               Index* out_drop_count) {
549   assert(typechecker_.type_stack_size() >= type_stack_limit);
550   Index type_stack_count = typechecker_.type_stack_size() - type_stack_limit;
551   // The keep_count may be larger than the type_stack_count if the typechecker
552   // is currently unreachable. In that case, it doesn't matter what value we
553   // drop, but 0 is a reasonable choice.
554   *out_drop_count =
555       type_stack_count >= keep_count ? type_stack_count - keep_count : 0;
556   return wabt::Result::Ok;
557 }
558 
GetBrDropKeepCount(Index depth,Index * out_drop_count,Index * out_keep_count)559 wabt::Result BinaryReaderInterp::GetBrDropKeepCount(Index depth,
560                                                     Index* out_drop_count,
561                                                     Index* out_keep_count) {
562   TypeChecker::Label* label;
563   CHECK_RESULT(typechecker_.GetLabel(depth, &label));
564   Index keep_count = label->br_types().size();
565   CHECK_RESULT(
566       GetDropCount(keep_count, label->type_stack_limit, out_drop_count));
567   *out_keep_count = keep_count;
568   return wabt::Result::Ok;
569 }
570 
GetReturnDropKeepCount(Index * out_drop_count,Index * out_keep_count)571 wabt::Result BinaryReaderInterp::GetReturnDropKeepCount(Index* out_drop_count,
572                                                         Index* out_keep_count) {
573   CHECK_RESULT(GetBrDropKeepCount(label_stack_.size() - 1, out_drop_count,
574                                   out_keep_count));
575   *out_drop_count += current_func_->param_and_local_types.size();
576   return wabt::Result::Ok;
577 }
578 
GetReturnCallDropKeepCount(FuncSignature * sig,Index keep_extra,Index * out_drop_count,Index * out_keep_count)579 wabt::Result BinaryReaderInterp::GetReturnCallDropKeepCount(
580     FuncSignature* sig,
581     Index keep_extra,
582     Index* out_drop_count,
583     Index* out_keep_count) {
584   Index keep_count = static_cast<Index>(sig->param_types.size()) + keep_extra;
585   CHECK_RESULT(GetDropCount(keep_count, 0, out_drop_count));
586   *out_drop_count += current_func_->param_and_local_types.size();
587   *out_keep_count = keep_count;
588   return wabt::Result::Ok;
589 }
590 
EmitBr(Index depth,Index drop_count,Index keep_count)591 wabt::Result BinaryReaderInterp::EmitBr(Index depth,
592                                         Index drop_count,
593                                         Index keep_count) {
594   CHECK_RESULT(EmitDropKeep(drop_count, keep_count));
595   CHECK_RESULT(EmitOpcode(Opcode::Br));
596   CHECK_RESULT(EmitBrOffset(depth, GetLabel(depth)->offset));
597   return wabt::Result::Ok;
598 }
599 
EmitBrTableOffset(Index depth)600 wabt::Result BinaryReaderInterp::EmitBrTableOffset(Index depth) {
601   Index drop_count, keep_count;
602   CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count));
603   CHECK_RESULT(EmitBrOffset(depth, GetLabel(depth)->offset));
604   CHECK_RESULT(EmitI32(drop_count));
605   CHECK_RESULT(EmitI32(keep_count));
606   return wabt::Result::Ok;
607 }
608 
FixupTopLabel()609 wabt::Result BinaryReaderInterp::FixupTopLabel() {
610   IstreamOffset offset = GetIstreamOffset();
611   Index top = label_stack_.size() - 1;
612   if (top >= depth_fixups_.size()) {
613     /* nothing to fixup */
614     return wabt::Result::Ok;
615   }
616 
617   IstreamOffsetVector& fixups = depth_fixups_[top];
618   for (IstreamOffset fixup : fixups)
619     CHECK_RESULT(EmitI32At(fixup, offset));
620   fixups.clear();
621   return wabt::Result::Ok;
622 }
623 
EmitFuncOffset(DefinedFunc * func,Index func_index)624 wabt::Result BinaryReaderInterp::EmitFuncOffset(DefinedFunc* func,
625                                                 Index func_index) {
626   if (func->offset == kInvalidIstreamOffset) {
627     Index defined_index = TranslateModuleFuncIndexToDefined(func_index);
628     CHECK_RESULT(AppendFixup(&func_fixups_, defined_index));
629   }
630   CHECK_RESULT(EmitI32(func->offset));
631   return wabt::Result::Ok;
632 }
633 
OnError(const Error & error)634 bool BinaryReaderInterp::OnError(const Error& error) {
635   errors_->push_back(error);
636   return true;
637 }
638 
OnTypeCount(Index count)639 wabt::Result BinaryReaderInterp::OnTypeCount(Index count) {
640   Index sig_count = env_->GetFuncSignatureCount();
641   sig_index_mapping_.resize(count);
642   for (Index i = 0; i < count; ++i)
643     sig_index_mapping_[i] = sig_count + i;
644   return wabt::Result::Ok;
645 }
646 
OnType(Index index,Index param_count,Type * param_types,Index result_count,Type * result_types)647 wabt::Result BinaryReaderInterp::OnType(Index index,
648                                         Index param_count,
649                                         Type* param_types,
650                                         Index result_count,
651                                         Type* result_types) {
652   assert(TranslateSigIndexToEnv(index) == env_->GetFuncSignatureCount());
653   env_->EmplaceBackFuncSignature(param_count, param_types, result_count,
654                                  result_types);
655   return wabt::Result::Ok;
656 }
657 
CheckLocal(Index local_index)658 wabt::Result BinaryReaderInterp::CheckLocal(Index local_index) {
659   Index max_local_index = current_func_->param_and_local_types.size();
660   if (local_index >= max_local_index) {
661     PrintError("invalid local_index: %" PRIindex " (max %" PRIindex ")",
662                local_index, max_local_index);
663     return wabt::Result::Error;
664   }
665   return wabt::Result::Ok;
666 }
667 
CheckGlobal(Index global_index)668 wabt::Result BinaryReaderInterp::CheckGlobal(Index global_index) {
669   Index max_global_index = global_index_mapping_.size();
670   if (global_index >= max_global_index) {
671     PrintError("invalid global_index: %" PRIindex " (max %" PRIindex ")",
672                global_index, max_global_index);
673     return wabt::Result::Error;
674   }
675   return wabt::Result::Ok;
676 }
677 
CheckDataSegment(Index data_segment_index)678 wabt::Result BinaryReaderInterp::CheckDataSegment(Index data_segment_index) {
679   Index max_data_segment_index = data_segment_index_mapping_.size();
680   if (data_segment_index >= max_data_segment_index) {
681     PrintError("invalid data_segment_index: %" PRIindex " (max %" PRIindex ")",
682                data_segment_index, max_data_segment_index);
683     return wabt::Result::Error;
684   }
685   return wabt::Result::Ok;
686 }
687 
CheckElemSegment(Index elem_segment_index)688 wabt::Result BinaryReaderInterp::CheckElemSegment(Index elem_segment_index) {
689   Index max_elem_segment_index = elem_segment_index_mapping_.size();
690   if (elem_segment_index >= max_elem_segment_index) {
691     PrintError("invalid elem_segment_index: %" PRIindex " (max %" PRIindex ")",
692                elem_segment_index, max_elem_segment_index);
693     return wabt::Result::Error;
694   }
695   return wabt::Result::Ok;
696 }
697 
CheckImportKind(Import * import,ExternalKind actual_kind)698 wabt::Result BinaryReaderInterp::CheckImportKind(Import* import,
699                                                  ExternalKind actual_kind) {
700   if (import->kind != actual_kind) {
701     PrintError("expected import \"" PRIstringview "." PRIstringview
702                "\" to have kind %s, not %s",
703                WABT_PRINTF_STRING_VIEW_ARG(import->module_name),
704                WABT_PRINTF_STRING_VIEW_ARG(import->field_name),
705                GetKindName(import->kind), GetKindName(actual_kind));
706     return wabt::Result::Error;
707   }
708   return wabt::Result::Ok;
709 }
710 
CheckImportLimits(const Limits * declared_limits,const Limits * actual_limits)711 wabt::Result BinaryReaderInterp::CheckImportLimits(
712     const Limits* declared_limits,
713     const Limits* actual_limits) {
714   if (actual_limits->initial < declared_limits->initial) {
715     PrintError("actual size (%" PRIu64 ") smaller than declared (%" PRIu64 ")",
716                actual_limits->initial, declared_limits->initial);
717     return wabt::Result::Error;
718   }
719 
720   if (declared_limits->has_max) {
721     if (!actual_limits->has_max) {
722       PrintError("max size (unspecified) larger than declared (%" PRIu64 ")",
723                  declared_limits->max);
724       return wabt::Result::Error;
725     } else if (actual_limits->max > declared_limits->max) {
726       PrintError("max size (%" PRIu64 ") larger than declared (%" PRIu64 ")",
727                  actual_limits->max, declared_limits->max);
728       return wabt::Result::Error;
729     }
730   }
731 
732   return wabt::Result::Ok;
733 }
734 
AppendExport(Module * module,ExternalKind kind,Index item_index,string_view name)735 wabt::Result BinaryReaderInterp::AppendExport(Module* module,
736                                               ExternalKind kind,
737                                               Index item_index,
738                                               string_view name) {
739   // Host modules are allowed to have duplicated exports; e.g. "spectest.print"
740   if (isa<DefinedModule>(module) &&
741       module->export_bindings.FindIndex(name) != kInvalidIndex) {
742     PrintError("duplicate export \"" PRIstringview "\"",
743                WABT_PRINTF_STRING_VIEW_ARG(name));
744     return wabt::Result::Error;
745   }
746 
747   module->AppendExport(kind, item_index, name);
748   return wabt::Result::Ok;
749 }
750 
FindRegisteredModule(string_view module_name,Module ** out_module)751 wabt::Result BinaryReaderInterp::FindRegisteredModule(string_view module_name,
752                                                       Module** out_module) {
753   Module* module = env_->FindRegisteredModule(module_name);
754   if (!module) {
755     PrintError("unknown import module \"" PRIstringview "\"",
756                WABT_PRINTF_STRING_VIEW_ARG(module_name));
757     return wabt::Result::Error;
758   }
759 
760   *out_module = module;
761   return wabt::Result::Ok;
762 }
763 
GetModuleExport(Module * module,string_view field_name,Export ** out_export)764 wabt::Result BinaryReaderInterp::GetModuleExport(Module* module,
765                                                  string_view field_name,
766                                                  Export** out_export) {
767   Export* export_ = module->GetExport(field_name);
768   if (!export_) {
769     PrintError("unknown module field \"" PRIstringview "\"",
770                WABT_PRINTF_STRING_VIEW_ARG(field_name));
771     return wabt::Result::Error;
772   }
773 
774   *out_export = export_;
775   return wabt::Result::Ok;
776 }
777 
OnImportFunc(Index import_index,string_view module_name,string_view field_name,Index func_index,Index sig_index)778 wabt::Result BinaryReaderInterp::OnImportFunc(Index import_index,
779                                               string_view module_name,
780                                               string_view field_name,
781                                               Index func_index,
782                                               Index sig_index) {
783   module_->func_imports.emplace_back(module_name, field_name);
784   FuncImport* import = &module_->func_imports.back();
785   import->sig_index = TranslateSigIndexToEnv(sig_index);
786 
787   Module* import_module;
788   CHECK_RESULT(FindRegisteredModule(import->module_name, &import_module));
789 
790   Export* export_ =
791       import_module->GetFuncExport(env_, field_name, import->sig_index);
792   if (!export_) {
793     // If GetFuncExport fails then GetModuleExport will fail too. But it's
794     // useful to call here to share the same error handling code as other
795     // imports.
796     CHECK_RESULT(GetModuleExport(import_module, import->field_name, &export_));
797   }
798 
799   CHECK_RESULT(CheckImportKind(import, export_->kind));
800 
801   Func* func = env_->GetFunc(export_->index);
802   if (!env_->FuncSignaturesAreEqual(import->sig_index, func->sig_index)) {
803     PrintError("import signature mismatch");
804     return wabt::Result::Error;
805   }
806 
807   func_index_mapping_.push_back(export_->index);
808   num_func_imports_++;
809   return wabt::Result::Ok;
810 }
811 
OnImportTable(Index import_index,string_view module_name,string_view field_name,Index table_index,Type elem_type,const Limits * elem_limits)812 wabt::Result BinaryReaderInterp::OnImportTable(Index import_index,
813                                                string_view module_name,
814                                                string_view field_name,
815                                                Index table_index,
816                                                Type elem_type,
817                                                const Limits* elem_limits) {
818   if (module_->table_index != kInvalidIndex) {
819     PrintError("only one table allowed");
820     return wabt::Result::Error;
821   }
822 
823   module_->table_imports.emplace_back(module_name, field_name);
824   TableImport* import = &module_->table_imports.back();
825 
826   Module* import_module;
827   CHECK_RESULT(FindRegisteredModule(import->module_name, &import_module));
828 
829   Export* export_;
830   CHECK_RESULT(GetModuleExport(import_module, import->field_name, &export_));
831   CHECK_RESULT(CheckImportKind(import, export_->kind));
832 
833   Table* table = env_->GetTable(export_->index);
834   CHECK_RESULT(CheckImportLimits(elem_limits, &table->limits));
835 
836   import->limits = *elem_limits;
837   module_->table_index = export_->index;
838   return wabt::Result::Ok;
839 }
840 
OnImportMemory(Index import_index,string_view module_name,string_view field_name,Index memory_index,const Limits * page_limits)841 wabt::Result BinaryReaderInterp::OnImportMemory(Index import_index,
842                                                 string_view module_name,
843                                                 string_view field_name,
844                                                 Index memory_index,
845                                                 const Limits* page_limits) {
846   if (module_->memory_index != kInvalidIndex) {
847     PrintError("only one memory allowed");
848     return wabt::Result::Error;
849   }
850 
851   module_->memory_imports.emplace_back(module_name, field_name);
852   MemoryImport* import = &module_->memory_imports.back();
853 
854   Module* import_module;
855   CHECK_RESULT(FindRegisteredModule(import->module_name, &import_module));
856 
857   Export* export_;
858   CHECK_RESULT(GetModuleExport(import_module, import->field_name, &export_));
859   CHECK_RESULT(CheckImportKind(import, export_->kind));
860 
861   Memory* memory = env_->GetMemory(export_->index);
862   CHECK_RESULT(CheckImportLimits(page_limits, &memory->page_limits));
863 
864   import->limits = *page_limits;
865   module_->memory_index = export_->index;
866   return wabt::Result::Ok;
867 }
868 
OnImportGlobal(Index import_index,string_view module_name,string_view field_name,Index global_index,Type type,bool mutable_)869 wabt::Result BinaryReaderInterp::OnImportGlobal(Index import_index,
870                                                 string_view module_name,
871                                                 string_view field_name,
872                                                 Index global_index,
873                                                 Type type,
874                                                 bool mutable_) {
875   module_->global_imports.emplace_back(module_name, field_name);
876   GlobalImport* import = &module_->global_imports.back();
877 
878   Module* import_module;
879   CHECK_RESULT(FindRegisteredModule(import->module_name, &import_module));
880 
881   Export* export_;
882   CHECK_RESULT(GetModuleExport(import_module, import->field_name, &export_));
883   CHECK_RESULT(CheckImportKind(import, export_->kind));
884 
885   Global* exported_global = env_->GetGlobal(export_->index);
886   if (exported_global->typed_value.type != type) {
887     PrintError("type mismatch in imported global, expected %s but got %s.",
888                GetTypeName(exported_global->typed_value.type),
889                GetTypeName(type));
890     return wabt::Result::Error;
891   }
892 
893   if (exported_global->mutable_ != mutable_) {
894     const char* kMutableNames[] = {"immutable", "mutable"};
895     PrintError(
896         "mutability mismatch in imported global, expected %s but got %s.",
897         kMutableNames[exported_global->mutable_], kMutableNames[mutable_]);
898     return wabt::Result::Error;
899   }
900 
901   import->type = type;
902   import->mutable_ = mutable_;
903   global_index_mapping_.push_back(export_->index);
904   num_global_imports_++;
905   return wabt::Result::Ok;
906 }
907 
OnFunctionCount(Index count)908 wabt::Result BinaryReaderInterp::OnFunctionCount(Index count) {
909   for (Index i = 0; i < count; ++i)
910     func_index_mapping_.push_back(env_->GetFuncCount() + i);
911   func_fixups_.resize(count);
912   return wabt::Result::Ok;
913 }
914 
OnFunction(Index index,Index sig_index)915 wabt::Result BinaryReaderInterp::OnFunction(Index index, Index sig_index) {
916   env_->EmplaceBackFunc(new DefinedFunc(TranslateSigIndexToEnv(sig_index)));
917   return wabt::Result::Ok;
918 }
919 
OnTable(Index index,Type elem_type,const Limits * elem_limits)920 wabt::Result BinaryReaderInterp::OnTable(Index index,
921                                          Type elem_type,
922                                          const Limits* elem_limits) {
923   if (module_->table_index != kInvalidIndex) {
924     PrintError("only one table allowed");
925     return wabt::Result::Error;
926   }
927   env_->EmplaceBackTable(elem_type, *elem_limits);
928   module_->table_index = env_->GetTableCount() - 1;
929   return wabt::Result::Ok;
930 }
931 
OnMemory(Index index,const Limits * page_limits)932 wabt::Result BinaryReaderInterp::OnMemory(Index index,
933                                           const Limits* page_limits) {
934   if (module_->memory_index != kInvalidIndex) {
935     PrintError("only one memory allowed");
936     return wabt::Result::Error;
937   }
938   env_->EmplaceBackMemory(*page_limits);
939   module_->memory_index = env_->GetMemoryCount() - 1;
940   return wabt::Result::Ok;
941 }
942 
OnGlobalCount(Index count)943 wabt::Result BinaryReaderInterp::OnGlobalCount(Index count) {
944   for (Index i = 0; i < count; ++i)
945     global_index_mapping_.push_back(env_->GetGlobalCount() + i);
946   return wabt::Result::Ok;
947 }
948 
BeginGlobal(Index index,Type type,bool mutable_)949 wabt::Result BinaryReaderInterp::BeginGlobal(Index index,
950                                              Type type,
951                                              bool mutable_) {
952   assert(TranslateGlobalIndexToEnv(index) == env_->GetGlobalCount());
953   env_->EmplaceBackGlobal(TypedValue(type), mutable_);
954   init_expr_value_.type = Type::Void;
955   return wabt::Result::Ok;
956 }
957 
EndGlobalInitExpr(Index index)958 wabt::Result BinaryReaderInterp::EndGlobalInitExpr(Index index) {
959   Global* global = GetGlobalByModuleIndex(index);
960   if (init_expr_value_.type != global->typed_value.type) {
961     PrintError("type mismatch in global, expected %s but got %s.",
962                GetTypeName(global->typed_value.type),
963                GetTypeName(init_expr_value_.type));
964     return wabt::Result::Error;
965   }
966   global->typed_value = init_expr_value_;
967   return wabt::Result::Ok;
968 }
969 
OnInitExprF32ConstExpr(Index index,uint32_t value_bits)970 wabt::Result BinaryReaderInterp::OnInitExprF32ConstExpr(Index index,
971                                                         uint32_t value_bits) {
972   init_expr_value_.type = Type::F32;
973   init_expr_value_.value.f32_bits = value_bits;
974   return wabt::Result::Ok;
975 }
976 
OnInitExprF64ConstExpr(Index index,uint64_t value_bits)977 wabt::Result BinaryReaderInterp::OnInitExprF64ConstExpr(Index index,
978                                                         uint64_t value_bits) {
979   init_expr_value_.type = Type::F64;
980   init_expr_value_.value.f64_bits = value_bits;
981   return wabt::Result::Ok;
982 }
983 
OnInitExprV128ConstExpr(Index index,v128 value_bits)984 wabt::Result BinaryReaderInterp::OnInitExprV128ConstExpr(Index index,
985                                                          v128 value_bits) {
986   init_expr_value_.type = Type::V128;
987   init_expr_value_.value.v128_bits = value_bits;
988   return wabt::Result::Ok;
989 }
990 
OnInitExprGlobalGetExpr(Index index,Index global_index)991 wabt::Result BinaryReaderInterp::OnInitExprGlobalGetExpr(Index index,
992                                                          Index global_index) {
993   if (global_index >= num_global_imports_) {
994     PrintError("initializer expression can only reference an imported global");
995     return wabt::Result::Error;
996   }
997   Global* ref_global = GetGlobalByModuleIndex(global_index);
998   if (ref_global->mutable_) {
999     PrintError("initializer expression cannot reference a mutable global");
1000     return wabt::Result::Error;
1001   }
1002   init_expr_value_ = ref_global->typed_value;
1003   return wabt::Result::Ok;
1004 }
1005 
OnInitExprI32ConstExpr(Index index,uint32_t value)1006 wabt::Result BinaryReaderInterp::OnInitExprI32ConstExpr(Index index,
1007                                                         uint32_t value) {
1008   init_expr_value_.type = Type::I32;
1009   init_expr_value_.value.i32 = value;
1010   return wabt::Result::Ok;
1011 }
1012 
OnInitExprI64ConstExpr(Index index,uint64_t value)1013 wabt::Result BinaryReaderInterp::OnInitExprI64ConstExpr(Index index,
1014                                                         uint64_t value) {
1015   init_expr_value_.type = Type::I64;
1016   init_expr_value_.value.i64 = value;
1017   return wabt::Result::Ok;
1018 }
1019 
OnInitExprRefNull(Index index)1020 wabt::Result BinaryReaderInterp::OnInitExprRefNull(Index index) {
1021   PrintError("ref.null global init expressions unimplemented by interpreter");
1022   return wabt::Result::Error;
1023 }
1024 
OnExport(Index index,ExternalKind kind,Index item_index,string_view name)1025 wabt::Result BinaryReaderInterp::OnExport(Index index,
1026                                           ExternalKind kind,
1027                                           Index item_index,
1028                                           string_view name) {
1029   switch (kind) {
1030     case ExternalKind::Func:
1031       item_index = TranslateFuncIndexToEnv(item_index);
1032       break;
1033 
1034     case ExternalKind::Table:
1035       item_index = module_->table_index;
1036       break;
1037 
1038     case ExternalKind::Memory:
1039       item_index = module_->memory_index;
1040       break;
1041 
1042     case ExternalKind::Global: {
1043       item_index = TranslateGlobalIndexToEnv(item_index);
1044       Global* global = env_->GetGlobal(item_index);
1045       if (global->mutable_ && !features_.mutable_globals_enabled()) {
1046         PrintError("mutable globals cannot be exported");
1047         return wabt::Result::Error;
1048       }
1049       break;
1050     }
1051 
1052     case ExternalKind::Event:
1053       // TODO(karlschimpf) Define
1054       WABT_FATAL("BinaryReaderInterp::OnExport(event) not implemented");
1055       break;
1056   }
1057   return AppendExport(module_, kind, item_index, name);
1058 }
1059 
OnStartFunction(Index func_index)1060 wabt::Result BinaryReaderInterp::OnStartFunction(Index func_index) {
1061   Index start_func_index = TranslateFuncIndexToEnv(func_index);
1062   Func* start_func = env_->GetFunc(start_func_index);
1063   FuncSignature* sig = env_->GetFuncSignature(start_func->sig_index);
1064   if (sig->param_types.size() != 0) {
1065     PrintError("start function must be nullary");
1066     return wabt::Result::Error;
1067   }
1068   if (sig->result_types.size() != 0) {
1069     PrintError("start function must not return anything");
1070     return wabt::Result::Error;
1071   }
1072   module_->start_func_index = start_func_index;
1073   return wabt::Result::Ok;
1074 }
1075 
OnElemSegmentCount(Index count)1076 wabt::Result BinaryReaderInterp::OnElemSegmentCount(Index count) {
1077   for (Index i = 0; i < count; ++i) {
1078     elem_segment_index_mapping_.push_back(env_->GetElemSegmentCount() + i);
1079   }
1080   return wabt::Result::Ok;
1081 }
1082 
BeginElemSegment(Index index,Index table_index,bool passive,Type elem_type)1083 wabt::Result BinaryReaderInterp::BeginElemSegment(Index index,
1084                                                   Index table_index,
1085                                                   bool passive,
1086                                                   Type elem_type) {
1087   segment_is_passive_ = passive;
1088   return wabt::Result::Ok;
1089 }
1090 
BeginElemSegmentInitExpr(Index index)1091 wabt::Result BinaryReaderInterp::BeginElemSegmentInitExpr(Index index) {
1092   init_expr_value_.type = Type::Void;
1093   return wabt::Result::Ok;
1094 }
1095 
EndElemSegmentInitExpr(Index index)1096 wabt::Result BinaryReaderInterp::EndElemSegmentInitExpr(Index index) {
1097   assert(segment_is_passive_ == false);
1098 
1099   if (init_expr_value_.type != Type::I32) {
1100     PrintError(
1101         "type mismatch in elem segment initializer expression, expected i32 "
1102         "but got %s",
1103         GetTypeName(init_expr_value_.type));
1104     return wabt::Result::Error;
1105   }
1106 
1107   table_offset_ = init_expr_value_.value.i32;
1108   return wabt::Result::Ok;
1109 }
1110 
OnElemSegmentElemExprCount(Index index,Index count)1111 wabt::Result BinaryReaderInterp::OnElemSegmentElemExprCount(Index index,
1112                                                             Index count) {
1113   elem_segment_ = env_->EmplaceBackElemSegment();
1114   if (segment_is_passive_) {
1115     elem_segment_info_ = nullptr;
1116   } else {
1117     // An active segment still is present in the segment index space, but
1118     // cannot be used with `table.init` (it's as if it has already been
1119     // dropped).
1120     elem_segment_->dropped = true;
1121 
1122     assert(module_->table_index != kInvalidIndex);
1123     Table* table = env_->GetTable(module_->table_index);
1124     elem_segment_infos_.emplace_back(table, table_offset_);
1125     elem_segment_info_ = &elem_segment_infos_.back();
1126   }
1127   return wabt::Result::Ok;
1128 }
1129 
OnElemSegmentElemExpr_RefNull(Index segment_index)1130 wabt::Result BinaryReaderInterp::OnElemSegmentElemExpr_RefNull(
1131     Index segment_index) {
1132   assert(segment_is_passive_);
1133   elem_segment_->elems.push_back(kInvalidIndex);
1134   return wabt::Result::Ok;
1135 }
1136 
OnElemSegmentElemExpr_RefFunc(Index index,Index func_index)1137 wabt::Result BinaryReaderInterp::OnElemSegmentElemExpr_RefFunc(
1138     Index index,
1139     Index func_index) {
1140   Index max_func_index = func_index_mapping_.size();
1141   if (func_index >= max_func_index) {
1142     PrintError("invalid func_index: %" PRIindex " (max %" PRIindex ")",
1143                func_index, max_func_index);
1144     return wabt::Result::Error;
1145   }
1146 
1147   func_index = TranslateFuncIndexToEnv(func_index);
1148 
1149   if (segment_is_passive_) {
1150     elem_segment_->elems.push_back(func_index);
1151   } else {
1152     elem_segment_info_->src.push_back(func_index);
1153   }
1154   return wabt::Result::Ok;
1155 }
1156 
OnDataCount(Index count)1157 wabt::Result BinaryReaderInterp::OnDataCount(Index count) {
1158   for (Index i = 0; i < count; ++i) {
1159     data_segment_index_mapping_.push_back(env_->GetDataSegmentCount() + i);
1160   }
1161   return wabt::Result::Ok;
1162 }
1163 
BeginDataSegment(Index index,Index memory_index,bool passive)1164 wabt::Result BinaryReaderInterp::BeginDataSegment(Index index,
1165                                                   Index memory_index,
1166                                                   bool passive) {
1167   segment_is_passive_ = passive;
1168   return wabt::Result::Ok;
1169 }
1170 
BeginDataSegmentInitExpr(Index index)1171 wabt::Result BinaryReaderInterp::BeginDataSegmentInitExpr(Index index) {
1172   init_expr_value_.type = Type::Void;
1173   return wabt::Result::Ok;
1174 }
1175 
OnDataSegmentData(Index index,const void * src_data,Address size)1176 wabt::Result BinaryReaderInterp::OnDataSegmentData(Index index,
1177                                                    const void* src_data,
1178                                                    Address size) {
1179   DataSegment* segment = env_->EmplaceBackDataSegment();
1180   if (segment_is_passive_) {
1181     segment->data.resize(size);
1182     if (size > 0) {
1183       memcpy(segment->data.data(), src_data, size);
1184     }
1185   } else {
1186     if (init_expr_value_.type != Type::I32) {
1187       PrintError(
1188           "type mismatch in data segment initializer expression, expected i32 "
1189           "but got %s",
1190           GetTypeName(init_expr_value_.type));
1191       return wabt::Result::Error;
1192     }
1193 
1194     // An active segment still is present in the segment index space, but
1195     // cannot be used with `memory.init` (it's as if it has already been
1196     // dropped).
1197     segment->dropped = true;
1198 
1199     assert(module_->memory_index != kInvalidIndex);
1200     Memory* memory = env_->GetMemory(module_->memory_index);
1201     Address address = init_expr_value_.value.i32;
1202     data_segment_infos_.emplace_back(memory, address, src_data, size);
1203   }
1204   return wabt::Result::Ok;
1205 }
1206 
PushLabel(IstreamOffset offset,IstreamOffset fixup_offset)1207 void BinaryReaderInterp::PushLabel(IstreamOffset offset,
1208                                    IstreamOffset fixup_offset) {
1209   label_stack_.emplace_back(offset, fixup_offset);
1210 }
1211 
PopLabel()1212 void BinaryReaderInterp::PopLabel() {
1213   label_stack_.pop_back();
1214   /* reduce the depth_fixups_ stack as well, but it may be smaller than
1215    * label_stack_ so only do it conditionally. */
1216   if (depth_fixups_.size() > label_stack_.size()) {
1217     depth_fixups_.erase(depth_fixups_.begin() + label_stack_.size(),
1218                         depth_fixups_.end());
1219   }
1220 }
1221 
BeginFunctionBody(Index index,Offset size)1222 wabt::Result BinaryReaderInterp::BeginFunctionBody(Index index, Offset size) {
1223   auto* func = cast<DefinedFunc>(GetFuncByModuleIndex(index));
1224   FuncSignature* sig = env_->GetFuncSignature(func->sig_index);
1225 
1226   func->offset = GetIstreamOffset();
1227   func->local_decl_count = 0;
1228   func->local_count = 0;
1229 
1230   current_func_ = func;
1231   depth_fixups_.clear();
1232   label_stack_.clear();
1233 
1234   /* fixup function references */
1235   Index defined_index = TranslateModuleFuncIndexToDefined(index);
1236   IstreamOffsetVector& fixups = func_fixups_[defined_index];
1237   for (IstreamOffset fixup : fixups)
1238     CHECK_RESULT(EmitI32At(fixup, func->offset));
1239 
1240   /* append param types */
1241   for (Type param_type : sig->param_types)
1242     func->param_and_local_types.push_back(param_type);
1243 
1244   CHECK_RESULT(typechecker_.BeginFunction(sig->result_types));
1245 
1246   /* push implicit func label (equivalent to return) */
1247   PushLabel(kInvalidIstreamOffset, kInvalidIstreamOffset);
1248   return wabt::Result::Ok;
1249 }
1250 
EndFunctionBody(Index index)1251 wabt::Result BinaryReaderInterp::EndFunctionBody(Index index) {
1252   FixupTopLabel();
1253   Index drop_count, keep_count;
1254   CHECK_RESULT(GetReturnDropKeepCount(&drop_count, &keep_count));
1255   CHECK_RESULT(typechecker_.EndFunction());
1256   CHECK_RESULT(EmitDropKeep(drop_count, keep_count));
1257   CHECK_RESULT(EmitOpcode(Opcode::Return));
1258   PopLabel();
1259   current_func_ = nullptr;
1260   return wabt::Result::Ok;
1261 }
1262 
OnLocalDeclCount(Index count)1263 wabt::Result BinaryReaderInterp::OnLocalDeclCount(Index count) {
1264   current_func_->local_decl_count = count;
1265   return wabt::Result::Ok;
1266 }
1267 
OnLocalDecl(Index decl_index,Index count,Type type)1268 wabt::Result BinaryReaderInterp::OnLocalDecl(Index decl_index,
1269                                              Index count,
1270                                              Type type) {
1271   current_func_->local_count += count;
1272 
1273   for (Index i = 0; i < count; ++i)
1274     current_func_->param_and_local_types.push_back(type);
1275 
1276   if (decl_index == current_func_->local_decl_count - 1) {
1277     /* last local declaration, allocate space for all locals. */
1278     CHECK_RESULT(EmitOpcode(Opcode::InterpAlloca));
1279     CHECK_RESULT(EmitI32(current_func_->local_count));
1280   }
1281   return wabt::Result::Ok;
1282 }
1283 
CheckHasMemory(wabt::Opcode opcode)1284 wabt::Result BinaryReaderInterp::CheckHasMemory(wabt::Opcode opcode) {
1285   if (module_->memory_index == kInvalidIndex) {
1286     PrintError("%s requires an imported or defined memory.", opcode.GetName());
1287     return wabt::Result::Error;
1288   }
1289   return wabt::Result::Ok;
1290 }
1291 
CheckHasTable(wabt::Opcode opcode)1292 wabt::Result BinaryReaderInterp::CheckHasTable(wabt::Opcode opcode) {
1293   if (module_->table_index == kInvalidIndex) {
1294     PrintError("%s requires an imported or defined table.", opcode.GetName());
1295     return wabt::Result::Error;
1296   }
1297   return wabt::Result::Ok;
1298 }
1299 
CheckAlign(uint32_t alignment_log2,Address natural_alignment)1300 wabt::Result BinaryReaderInterp::CheckAlign(uint32_t alignment_log2,
1301                                             Address natural_alignment) {
1302   if (alignment_log2 >= 32 || (1U << alignment_log2) > natural_alignment) {
1303     PrintError("alignment must not be larger than natural alignment (%u)",
1304                natural_alignment);
1305     return wabt::Result::Error;
1306   }
1307   return wabt::Result::Ok;
1308 }
1309 
CheckAtomicAlign(uint32_t alignment_log2,Address natural_alignment)1310 wabt::Result BinaryReaderInterp::CheckAtomicAlign(uint32_t alignment_log2,
1311                                                   Address natural_alignment) {
1312   if (alignment_log2 >= 32 || (1U << alignment_log2) != natural_alignment) {
1313     PrintError("alignment must be equal to natural alignment (%u)",
1314                natural_alignment);
1315     return wabt::Result::Error;
1316   }
1317   return wabt::Result::Ok;
1318 }
1319 
OnOpcode(Opcode opcode)1320 wabt::Result BinaryReaderInterp::OnOpcode(Opcode opcode) {
1321   if (current_func_ == nullptr || label_stack_.size() == 0) {
1322     PrintError("Unexpected instruction after end of function");
1323     return wabt::Result::Error;
1324   }
1325   return wabt::Result::Ok;
1326 }
1327 
OnUnaryExpr(wabt::Opcode opcode)1328 wabt::Result BinaryReaderInterp::OnUnaryExpr(wabt::Opcode opcode) {
1329   CHECK_RESULT(typechecker_.OnUnary(opcode));
1330   CHECK_RESULT(EmitOpcode(opcode));
1331   return wabt::Result::Ok;
1332 }
1333 
OnTernaryExpr(wabt::Opcode opcode)1334 wabt::Result BinaryReaderInterp::OnTernaryExpr(wabt::Opcode opcode) {
1335   CHECK_RESULT(typechecker_.OnTernary(opcode));
1336   CHECK_RESULT(EmitOpcode(opcode));
1337   return wabt::Result::Ok;
1338 }
1339 
OnSimdLaneOpExpr(wabt::Opcode opcode,uint64_t value)1340 wabt::Result BinaryReaderInterp::OnSimdLaneOpExpr(wabt::Opcode opcode,
1341                                                   uint64_t value) {
1342   CHECK_RESULT(typechecker_.OnSimdLaneOp(opcode, value));
1343   CHECK_RESULT(EmitOpcode(opcode));
1344   CHECK_RESULT(EmitI8(static_cast<uint8_t>(value)));
1345   return wabt::Result::Ok;
1346 }
1347 
OnSimdShuffleOpExpr(wabt::Opcode opcode,v128 value)1348 wabt::Result BinaryReaderInterp::OnSimdShuffleOpExpr(wabt::Opcode opcode,
1349                                                      v128 value) {
1350   CHECK_RESULT(typechecker_.OnSimdShuffleOp(opcode, value));
1351   CHECK_RESULT(EmitOpcode(opcode));
1352   CHECK_RESULT(EmitV128(value));
1353   return wabt::Result::Ok;
1354 }
1355 
OnLoadSplatExpr(wabt::Opcode opcode,uint32_t alignment_log2,Address offset)1356 wabt::Result BinaryReaderInterp::OnLoadSplatExpr(wabt::Opcode opcode,
1357                                                  uint32_t alignment_log2,
1358                                                  Address offset) {
1359   CHECK_RESULT(CheckHasMemory(opcode));
1360   CHECK_RESULT(CheckAlign(alignment_log2, opcode.GetMemorySize()));
1361   CHECK_RESULT(typechecker_.OnLoad(opcode));
1362   CHECK_RESULT(EmitOpcode(opcode));
1363   CHECK_RESULT(EmitI32(module_->memory_index));
1364   CHECK_RESULT(EmitI32(offset));
1365   return wabt::Result::Ok;
1366 }
1367 
OnAtomicLoadExpr(Opcode opcode,uint32_t alignment_log2,Address offset)1368 wabt::Result BinaryReaderInterp::OnAtomicLoadExpr(Opcode opcode,
1369                                                   uint32_t alignment_log2,
1370                                                   Address offset) {
1371   CHECK_RESULT(CheckHasMemory(opcode));
1372   CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
1373   CHECK_RESULT(typechecker_.OnAtomicLoad(opcode));
1374   CHECK_RESULT(EmitOpcode(opcode));
1375   CHECK_RESULT(EmitI32(module_->memory_index));
1376   CHECK_RESULT(EmitI32(offset));
1377   return wabt::Result::Ok;
1378 }
1379 
OnAtomicStoreExpr(Opcode opcode,uint32_t alignment_log2,Address offset)1380 wabt::Result BinaryReaderInterp::OnAtomicStoreExpr(Opcode opcode,
1381                                                    uint32_t alignment_log2,
1382                                                    Address offset) {
1383   CHECK_RESULT(CheckHasMemory(opcode));
1384   CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
1385   CHECK_RESULT(typechecker_.OnAtomicStore(opcode));
1386   CHECK_RESULT(EmitOpcode(opcode));
1387   CHECK_RESULT(EmitI32(module_->memory_index));
1388   CHECK_RESULT(EmitI32(offset));
1389   return wabt::Result::Ok;
1390 }
1391 
OnAtomicRmwExpr(Opcode opcode,uint32_t alignment_log2,Address offset)1392 wabt::Result BinaryReaderInterp::OnAtomicRmwExpr(Opcode opcode,
1393                                                  uint32_t alignment_log2,
1394                                                  Address offset) {
1395   CHECK_RESULT(CheckHasMemory(opcode));
1396   CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
1397   CHECK_RESULT(typechecker_.OnAtomicRmw(opcode));
1398   CHECK_RESULT(EmitOpcode(opcode));
1399   CHECK_RESULT(EmitI32(module_->memory_index));
1400   CHECK_RESULT(EmitI32(offset));
1401   return wabt::Result::Ok;
1402 }
1403 
OnAtomicRmwCmpxchgExpr(Opcode opcode,uint32_t alignment_log2,Address offset)1404 wabt::Result BinaryReaderInterp::OnAtomicRmwCmpxchgExpr(Opcode opcode,
1405                                                         uint32_t alignment_log2,
1406                                                         Address offset) {
1407   CHECK_RESULT(CheckHasMemory(opcode));
1408   CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
1409   CHECK_RESULT(typechecker_.OnAtomicRmwCmpxchg(opcode));
1410   CHECK_RESULT(EmitOpcode(opcode));
1411   CHECK_RESULT(EmitI32(module_->memory_index));
1412   CHECK_RESULT(EmitI32(offset));
1413   return wabt::Result::Ok;
1414 }
1415 
OnBinaryExpr(wabt::Opcode opcode)1416 wabt::Result BinaryReaderInterp::OnBinaryExpr(wabt::Opcode opcode) {
1417   CHECK_RESULT(typechecker_.OnBinary(opcode));
1418   CHECK_RESULT(EmitOpcode(opcode));
1419   return wabt::Result::Ok;
1420 }
1421 
OnBlockExpr(Type sig_type)1422 wabt::Result BinaryReaderInterp::OnBlockExpr(Type sig_type) {
1423   TypeVector param_types, result_types;
1424   GetBlockSignature(sig_type, &param_types, &result_types);
1425   CHECK_RESULT(typechecker_.OnBlock(param_types, result_types));
1426   PushLabel(kInvalidIstreamOffset, kInvalidIstreamOffset);
1427   return wabt::Result::Ok;
1428 }
1429 
OnLoopExpr(Type sig_type)1430 wabt::Result BinaryReaderInterp::OnLoopExpr(Type sig_type) {
1431   TypeVector param_types, result_types;
1432   GetBlockSignature(sig_type, &param_types, &result_types);
1433   CHECK_RESULT(typechecker_.OnLoop(param_types, result_types));
1434   PushLabel(GetIstreamOffset(), kInvalidIstreamOffset);
1435   return wabt::Result::Ok;
1436 }
1437 
OnIfExpr(Type sig_type)1438 wabt::Result BinaryReaderInterp::OnIfExpr(Type sig_type) {
1439   TypeVector param_types, result_types;
1440   GetBlockSignature(sig_type, &param_types, &result_types);
1441   CHECK_RESULT(typechecker_.OnIf(param_types, result_types));
1442   CHECK_RESULT(EmitOpcode(Opcode::InterpBrUnless));
1443   IstreamOffset fixup_offset = GetIstreamOffset();
1444   CHECK_RESULT(EmitI32(kInvalidIstreamOffset));
1445   PushLabel(kInvalidIstreamOffset, fixup_offset);
1446   return wabt::Result::Ok;
1447 }
1448 
OnElseExpr()1449 wabt::Result BinaryReaderInterp::OnElseExpr() {
1450   CHECK_RESULT(typechecker_.OnElse());
1451   Label* label = TopLabel();
1452   IstreamOffset fixup_cond_offset = label->fixup_offset;
1453   CHECK_RESULT(EmitOpcode(Opcode::Br));
1454   label->fixup_offset = GetIstreamOffset();
1455   CHECK_RESULT(EmitI32(kInvalidIstreamOffset));
1456   CHECK_RESULT(EmitI32At(fixup_cond_offset, GetIstreamOffset()));
1457   return wabt::Result::Ok;
1458 }
1459 
OnEndExpr()1460 wabt::Result BinaryReaderInterp::OnEndExpr() {
1461   TypeChecker::Label* label;
1462   CHECK_RESULT(typechecker_.GetLabel(0, &label));
1463   LabelType label_type = label->label_type;
1464   CHECK_RESULT(typechecker_.OnEnd());
1465   if (label_type == LabelType::If || label_type == LabelType::Else) {
1466     CHECK_RESULT(EmitI32At(TopLabel()->fixup_offset, GetIstreamOffset()));
1467   }
1468   FixupTopLabel();
1469   PopLabel();
1470   return wabt::Result::Ok;
1471 }
1472 
OnBrExpr(Index depth)1473 wabt::Result BinaryReaderInterp::OnBrExpr(Index depth) {
1474   Index drop_count, keep_count;
1475   CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count));
1476   CHECK_RESULT(typechecker_.OnBr(depth));
1477   CHECK_RESULT(EmitBr(depth, drop_count, keep_count));
1478   return wabt::Result::Ok;
1479 }
1480 
OnBrIfExpr(Index depth)1481 wabt::Result BinaryReaderInterp::OnBrIfExpr(Index depth) {
1482   Index drop_count, keep_count;
1483   CHECK_RESULT(typechecker_.OnBrIf(depth));
1484   CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count));
1485   /* flip the br_if so if <cond> is true it can drop values from the stack */
1486   CHECK_RESULT(EmitOpcode(Opcode::InterpBrUnless));
1487   IstreamOffset fixup_br_offset = GetIstreamOffset();
1488   CHECK_RESULT(EmitI32(kInvalidIstreamOffset));
1489   CHECK_RESULT(EmitBr(depth, drop_count, keep_count));
1490   CHECK_RESULT(EmitI32At(fixup_br_offset, GetIstreamOffset()));
1491   return wabt::Result::Ok;
1492 }
1493 
OnBrTableExpr(Index num_targets,Index * target_depths,Index default_target_depth)1494 wabt::Result BinaryReaderInterp::OnBrTableExpr(Index num_targets,
1495                                                Index* target_depths,
1496                                                Index default_target_depth) {
1497   CHECK_RESULT(typechecker_.BeginBrTable());
1498   CHECK_RESULT(EmitOpcode(Opcode::BrTable));
1499   CHECK_RESULT(EmitI32(num_targets));
1500   IstreamOffset fixup_table_offset = GetIstreamOffset();
1501   CHECK_RESULT(EmitI32(kInvalidIstreamOffset));
1502   /* not necessary for the interp, but it makes it easier to disassemble.
1503    * This opcode specifies how many bytes of data follow. */
1504   CHECK_RESULT(EmitOpcode(Opcode::InterpData));
1505   CHECK_RESULT(EmitI32((num_targets + 1) * WABT_TABLE_ENTRY_SIZE));
1506   CHECK_RESULT(EmitI32At(fixup_table_offset, GetIstreamOffset()));
1507 
1508   for (Index i = 0; i <= num_targets; ++i) {
1509     Index depth = i != num_targets ? target_depths[i] : default_target_depth;
1510     CHECK_RESULT(typechecker_.OnBrTableTarget(depth));
1511     CHECK_RESULT(EmitBrTableOffset(depth));
1512   }
1513 
1514   CHECK_RESULT(typechecker_.EndBrTable());
1515   return wabt::Result::Ok;
1516 }
1517 
OnCallExpr(Index func_index)1518 wabt::Result BinaryReaderInterp::OnCallExpr(Index func_index) {
1519   Func* func = GetFuncByModuleIndex(func_index);
1520   FuncSignature* sig = env_->GetFuncSignature(func->sig_index);
1521   CHECK_RESULT(typechecker_.OnCall(sig->param_types, sig->result_types));
1522 
1523   if (func->is_host) {
1524     CHECK_RESULT(EmitOpcode(Opcode::InterpCallHost));
1525     CHECK_RESULT(EmitI32(TranslateFuncIndexToEnv(func_index)));
1526   } else {
1527     CHECK_RESULT(EmitOpcode(Opcode::Call));
1528     CHECK_RESULT(EmitFuncOffset(cast<DefinedFunc>(func), func_index));
1529   }
1530 
1531   return wabt::Result::Ok;
1532 }
1533 
OnCallIndirectExpr(Index sig_index,Index table_index)1534 wabt::Result BinaryReaderInterp::OnCallIndirectExpr(Index sig_index,
1535                                                     Index table_index) {
1536   if (module_->table_index == kInvalidIndex) {
1537     PrintError("found call_indirect operator, but no table");
1538     return wabt::Result::Error;
1539   }
1540   FuncSignature* sig = GetSignatureByModuleIndex(sig_index);
1541   CHECK_RESULT(
1542       typechecker_.OnCallIndirect(sig->param_types, sig->result_types));
1543 
1544   CHECK_RESULT(EmitOpcode(Opcode::CallIndirect));
1545   CHECK_RESULT(EmitI32(module_->table_index));
1546   CHECK_RESULT(EmitI32(TranslateSigIndexToEnv(sig_index)));
1547   return wabt::Result::Ok;
1548 }
1549 
OnReturnCallExpr(Index func_index)1550 wabt::Result BinaryReaderInterp::OnReturnCallExpr(Index func_index) {
1551   Func* func = GetFuncByModuleIndex(func_index);
1552   FuncSignature* sig = env_->GetFuncSignature(func->sig_index);
1553 
1554   Index drop_count, keep_count;
1555   CHECK_RESULT(GetReturnCallDropKeepCount(sig, 0, &drop_count, &keep_count));
1556   // The typechecker must be run after we get the drop/keep counts, since it
1557   // will change the type stack.
1558   CHECK_RESULT(typechecker_.OnReturnCall(sig->param_types, sig->result_types));
1559   CHECK_RESULT(EmitDropKeep(drop_count, keep_count));
1560 
1561   if (func->is_host) {
1562     CHECK_RESULT(EmitOpcode(Opcode::InterpCallHost));
1563     CHECK_RESULT(EmitI32(TranslateFuncIndexToEnv(func_index)));
1564     CHECK_RESULT(EmitOpcode(Opcode::Return));
1565   } else {
1566     CHECK_RESULT(EmitOpcode(Opcode::ReturnCall));
1567     CHECK_RESULT(EmitFuncOffset(cast<DefinedFunc>(func), func_index));
1568   }
1569 
1570   return wabt::Result::Ok;
1571 }
1572 
OnReturnCallIndirectExpr(Index sig_index,Index table_index)1573 wabt::Result BinaryReaderInterp::OnReturnCallIndirectExpr(Index sig_index,
1574                                                           Index table_index) {
1575   if (module_->table_index == kInvalidIndex) {
1576     PrintError("found return_call_indirect operator, but no table");
1577     return wabt::Result::Error;
1578   }
1579   FuncSignature* sig = GetSignatureByModuleIndex(sig_index);
1580 
1581   Index drop_count, keep_count;
1582   // +1 to include the index of the function.
1583   CHECK_RESULT(GetReturnCallDropKeepCount(sig, +1, &drop_count, &keep_count));
1584   // The typechecker must be run after we get the drop/keep counts, since it
1585   // changes the type stack.
1586   CHECK_RESULT(
1587       typechecker_.OnReturnCallIndirect(sig->param_types, sig->result_types));
1588   CHECK_RESULT(EmitDropKeep(drop_count, keep_count));
1589 
1590   CHECK_RESULT(EmitOpcode(Opcode::ReturnCallIndirect));
1591   CHECK_RESULT(EmitI32(module_->table_index));
1592   CHECK_RESULT(EmitI32(TranslateSigIndexToEnv(sig_index)));
1593   return wabt::Result::Ok;
1594 }
1595 
OnCompareExpr(wabt::Opcode opcode)1596 wabt::Result BinaryReaderInterp::OnCompareExpr(wabt::Opcode opcode) {
1597   return OnBinaryExpr(opcode);
1598 }
1599 
OnConvertExpr(wabt::Opcode opcode)1600 wabt::Result BinaryReaderInterp::OnConvertExpr(wabt::Opcode opcode) {
1601   return OnUnaryExpr(opcode);
1602 }
1603 
OnDropExpr()1604 wabt::Result BinaryReaderInterp::OnDropExpr() {
1605   CHECK_RESULT(typechecker_.OnDrop());
1606   CHECK_RESULT(EmitOpcode(Opcode::Drop));
1607   return wabt::Result::Ok;
1608 }
1609 
OnI32ConstExpr(uint32_t value)1610 wabt::Result BinaryReaderInterp::OnI32ConstExpr(uint32_t value) {
1611   CHECK_RESULT(typechecker_.OnConst(Type::I32));
1612   CHECK_RESULT(EmitOpcode(Opcode::I32Const));
1613   CHECK_RESULT(EmitI32(value));
1614   return wabt::Result::Ok;
1615 }
1616 
OnI64ConstExpr(uint64_t value)1617 wabt::Result BinaryReaderInterp::OnI64ConstExpr(uint64_t value) {
1618   CHECK_RESULT(typechecker_.OnConst(Type::I64));
1619   CHECK_RESULT(EmitOpcode(Opcode::I64Const));
1620   CHECK_RESULT(EmitI64(value));
1621   return wabt::Result::Ok;
1622 }
1623 
OnF32ConstExpr(uint32_t value_bits)1624 wabt::Result BinaryReaderInterp::OnF32ConstExpr(uint32_t value_bits) {
1625   CHECK_RESULT(typechecker_.OnConst(Type::F32));
1626   CHECK_RESULT(EmitOpcode(Opcode::F32Const));
1627   CHECK_RESULT(EmitI32(value_bits));
1628   return wabt::Result::Ok;
1629 }
1630 
OnF64ConstExpr(uint64_t value_bits)1631 wabt::Result BinaryReaderInterp::OnF64ConstExpr(uint64_t value_bits) {
1632   CHECK_RESULT(typechecker_.OnConst(Type::F64));
1633   CHECK_RESULT(EmitOpcode(Opcode::F64Const));
1634   CHECK_RESULT(EmitI64(value_bits));
1635   return wabt::Result::Ok;
1636 }
1637 
OnV128ConstExpr(v128 value_bits)1638 wabt::Result BinaryReaderInterp::OnV128ConstExpr(v128 value_bits) {
1639   CHECK_RESULT(typechecker_.OnConst(Type::V128));
1640   CHECK_RESULT(EmitOpcode(Opcode::V128Const));
1641   CHECK_RESULT(EmitV128(value_bits));
1642   return wabt::Result::Ok;
1643 }
1644 
OnGlobalGetExpr(Index global_index)1645 wabt::Result BinaryReaderInterp::OnGlobalGetExpr(Index global_index) {
1646   CHECK_RESULT(CheckGlobal(global_index));
1647   Type type = GetGlobalTypeByModuleIndex(global_index);
1648   CHECK_RESULT(typechecker_.OnGlobalGet(type));
1649   CHECK_RESULT(EmitOpcode(Opcode::GlobalGet));
1650   CHECK_RESULT(EmitI32(TranslateGlobalIndexToEnv(global_index)));
1651   return wabt::Result::Ok;
1652 }
1653 
OnGlobalSetExpr(Index global_index)1654 wabt::Result BinaryReaderInterp::OnGlobalSetExpr(Index global_index) {
1655   CHECK_RESULT(CheckGlobal(global_index));
1656   Global* global = GetGlobalByModuleIndex(global_index);
1657   if (!global->mutable_) {
1658     PrintError("can't global.set on immutable global at index %" PRIindex ".",
1659                global_index);
1660     return wabt::Result::Error;
1661   }
1662   CHECK_RESULT(typechecker_.OnGlobalSet(global->typed_value.type));
1663   CHECK_RESULT(EmitOpcode(Opcode::GlobalSet));
1664   CHECK_RESULT(EmitI32(TranslateGlobalIndexToEnv(global_index)));
1665   return wabt::Result::Ok;
1666 }
1667 
TranslateLocalIndex(Index local_index)1668 Index BinaryReaderInterp::TranslateLocalIndex(Index local_index) {
1669   return typechecker_.type_stack_size() +
1670          current_func_->param_and_local_types.size() - local_index;
1671 }
1672 
OnLocalGetExpr(Index local_index)1673 wabt::Result BinaryReaderInterp::OnLocalGetExpr(Index local_index) {
1674   CHECK_RESULT(CheckLocal(local_index));
1675   Type type = GetLocalTypeByIndex(current_func_, local_index);
1676   // Get the translated index before calling typechecker_.OnLocalGet because it
1677   // will update the type stack size. We need the index to be relative to the
1678   // old stack size.
1679   Index translated_local_index = TranslateLocalIndex(local_index);
1680   CHECK_RESULT(typechecker_.OnLocalGet(type));
1681   CHECK_RESULT(EmitOpcode(Opcode::LocalGet));
1682   CHECK_RESULT(EmitI32(translated_local_index));
1683   return wabt::Result::Ok;
1684 }
1685 
OnLocalSetExpr(Index local_index)1686 wabt::Result BinaryReaderInterp::OnLocalSetExpr(Index local_index) {
1687   CHECK_RESULT(CheckLocal(local_index));
1688   Type type = GetLocalTypeByIndex(current_func_, local_index);
1689   CHECK_RESULT(typechecker_.OnLocalSet(type));
1690   CHECK_RESULT(EmitOpcode(Opcode::LocalSet));
1691   CHECK_RESULT(EmitI32(TranslateLocalIndex(local_index)));
1692   return wabt::Result::Ok;
1693 }
1694 
OnLocalTeeExpr(Index local_index)1695 wabt::Result BinaryReaderInterp::OnLocalTeeExpr(Index local_index) {
1696   CHECK_RESULT(CheckLocal(local_index));
1697   Type type = GetLocalTypeByIndex(current_func_, local_index);
1698   CHECK_RESULT(typechecker_.OnLocalTee(type));
1699   CHECK_RESULT(EmitOpcode(Opcode::LocalTee));
1700   CHECK_RESULT(EmitI32(TranslateLocalIndex(local_index)));
1701   return wabt::Result::Ok;
1702 }
1703 
OnLoadExpr(wabt::Opcode opcode,uint32_t alignment_log2,Address offset)1704 wabt::Result BinaryReaderInterp::OnLoadExpr(wabt::Opcode opcode,
1705                                             uint32_t alignment_log2,
1706                                             Address offset) {
1707   CHECK_RESULT(CheckHasMemory(opcode));
1708   CHECK_RESULT(CheckAlign(alignment_log2, opcode.GetMemorySize()));
1709   CHECK_RESULT(typechecker_.OnLoad(opcode));
1710   CHECK_RESULT(EmitOpcode(opcode));
1711   CHECK_RESULT(EmitI32(module_->memory_index));
1712   CHECK_RESULT(EmitI32(offset));
1713   return wabt::Result::Ok;
1714 }
1715 
OnStoreExpr(wabt::Opcode opcode,uint32_t alignment_log2,Address offset)1716 wabt::Result BinaryReaderInterp::OnStoreExpr(wabt::Opcode opcode,
1717                                              uint32_t alignment_log2,
1718                                              Address offset) {
1719   CHECK_RESULT(CheckHasMemory(opcode));
1720   CHECK_RESULT(CheckAlign(alignment_log2, opcode.GetMemorySize()));
1721   CHECK_RESULT(typechecker_.OnStore(opcode));
1722   CHECK_RESULT(EmitOpcode(opcode));
1723   CHECK_RESULT(EmitI32(module_->memory_index));
1724   CHECK_RESULT(EmitI32(offset));
1725   return wabt::Result::Ok;
1726 }
1727 
OnMemoryGrowExpr()1728 wabt::Result BinaryReaderInterp::OnMemoryGrowExpr() {
1729   CHECK_RESULT(CheckHasMemory(wabt::Opcode::MemoryGrow));
1730   CHECK_RESULT(typechecker_.OnMemoryGrow());
1731   CHECK_RESULT(EmitOpcode(Opcode::MemoryGrow));
1732   CHECK_RESULT(EmitI32(module_->memory_index));
1733   return wabt::Result::Ok;
1734 }
1735 
OnMemorySizeExpr()1736 wabt::Result BinaryReaderInterp::OnMemorySizeExpr() {
1737   CHECK_RESULT(CheckHasMemory(wabt::Opcode::MemorySize));
1738   CHECK_RESULT(typechecker_.OnMemorySize());
1739   CHECK_RESULT(EmitOpcode(Opcode::MemorySize));
1740   CHECK_RESULT(EmitI32(module_->memory_index));
1741   return wabt::Result::Ok;
1742 }
1743 
OnNopExpr()1744 wabt::Result BinaryReaderInterp::OnNopExpr() {
1745   return wabt::Result::Ok;
1746 }
1747 
OnReturnExpr()1748 wabt::Result BinaryReaderInterp::OnReturnExpr() {
1749   Index drop_count, keep_count;
1750   CHECK_RESULT(GetReturnDropKeepCount(&drop_count, &keep_count));
1751   CHECK_RESULT(typechecker_.OnReturn());
1752   CHECK_RESULT(EmitDropKeep(drop_count, keep_count));
1753   CHECK_RESULT(EmitOpcode(Opcode::Return));
1754   return wabt::Result::Ok;
1755 }
1756 
OnSelectExpr()1757 wabt::Result BinaryReaderInterp::OnSelectExpr() {
1758   CHECK_RESULT(typechecker_.OnSelect());
1759   CHECK_RESULT(EmitOpcode(Opcode::Select));
1760   return wabt::Result::Ok;
1761 }
1762 
OnUnreachableExpr()1763 wabt::Result BinaryReaderInterp::OnUnreachableExpr() {
1764   CHECK_RESULT(typechecker_.OnUnreachable());
1765   CHECK_RESULT(EmitOpcode(Opcode::Unreachable));
1766   return wabt::Result::Ok;
1767 }
1768 
OnAtomicWaitExpr(Opcode opcode,uint32_t alignment_log2,Address offset)1769 wabt::Result BinaryReaderInterp::OnAtomicWaitExpr(Opcode opcode,
1770                                                   uint32_t alignment_log2,
1771                                                   Address offset) {
1772   CHECK_RESULT(CheckHasMemory(opcode));
1773   CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
1774   CHECK_RESULT(typechecker_.OnAtomicWait(opcode));
1775   CHECK_RESULT(EmitOpcode(opcode));
1776   CHECK_RESULT(EmitI32(module_->memory_index));
1777   CHECK_RESULT(EmitI32(offset));
1778   return wabt::Result::Ok;
1779 }
1780 
OnAtomicNotifyExpr(Opcode opcode,uint32_t alignment_log2,Address offset)1781 wabt::Result BinaryReaderInterp::OnAtomicNotifyExpr(Opcode opcode,
1782                                                     uint32_t alignment_log2,
1783                                                     Address offset) {
1784   CHECK_RESULT(CheckHasMemory(opcode));
1785   CHECK_RESULT(CheckAtomicAlign(alignment_log2, opcode.GetMemorySize()));
1786   CHECK_RESULT(typechecker_.OnAtomicNotify(opcode));
1787   CHECK_RESULT(EmitOpcode(opcode));
1788   CHECK_RESULT(EmitI32(module_->memory_index));
1789   CHECK_RESULT(EmitI32(offset));
1790   return wabt::Result::Ok;
1791 }
1792 
OnMemoryCopyExpr()1793 wabt::Result BinaryReaderInterp::OnMemoryCopyExpr() {
1794   CHECK_RESULT(CheckHasMemory(Opcode::MemoryCopy));
1795   CHECK_RESULT(typechecker_.OnMemoryCopy());
1796   CHECK_RESULT(EmitOpcode(Opcode::MemoryCopy));
1797   CHECK_RESULT(EmitI32(module_->memory_index));
1798   return wabt::Result::Ok;
1799 }
1800 
OnDataDropExpr(Index segment_index)1801 wabt::Result BinaryReaderInterp::OnDataDropExpr(Index segment_index) {
1802   CHECK_RESULT(CheckDataSegment(segment_index));
1803   CHECK_RESULT(typechecker_.OnDataDrop(segment_index));
1804   CHECK_RESULT(EmitOpcode(Opcode::DataDrop));
1805   CHECK_RESULT(EmitI32(TranslateDataSegmentIndexToEnv(segment_index)));
1806   return wabt::Result::Ok;
1807 }
1808 
OnMemoryFillExpr()1809 wabt::Result BinaryReaderInterp::OnMemoryFillExpr() {
1810   CHECK_RESULT(CheckHasMemory(Opcode::MemoryFill));
1811   CHECK_RESULT(typechecker_.OnMemoryFill());
1812   CHECK_RESULT(EmitOpcode(Opcode::MemoryFill));
1813   CHECK_RESULT(EmitI32(module_->memory_index));
1814   return wabt::Result::Ok;
1815 }
1816 
OnMemoryInitExpr(Index segment_index)1817 wabt::Result BinaryReaderInterp::OnMemoryInitExpr(Index segment_index) {
1818   CHECK_RESULT(CheckHasMemory(Opcode::MemoryInit));
1819   CHECK_RESULT(CheckDataSegment(segment_index));
1820   CHECK_RESULT(typechecker_.OnMemoryInit(segment_index));
1821   CHECK_RESULT(EmitOpcode(Opcode::MemoryInit));
1822   CHECK_RESULT(EmitI32(module_->memory_index));
1823   CHECK_RESULT(EmitI32(TranslateDataSegmentIndexToEnv(segment_index)));
1824   return wabt::Result::Ok;
1825 }
1826 
OnTableCopyExpr()1827 wabt::Result BinaryReaderInterp::OnTableCopyExpr() {
1828   CHECK_RESULT(CheckHasTable(Opcode::TableCopy));
1829   CHECK_RESULT(typechecker_.OnTableCopy());
1830   CHECK_RESULT(EmitOpcode(Opcode::TableCopy));
1831   CHECK_RESULT(EmitI32(module_->table_index));
1832   return wabt::Result::Ok;
1833 }
1834 
OnElemDropExpr(Index segment_index)1835 wabt::Result BinaryReaderInterp::OnElemDropExpr(Index segment_index) {
1836   CHECK_RESULT(CheckElemSegment(segment_index));
1837   CHECK_RESULT(typechecker_.OnElemDrop(segment_index));
1838   CHECK_RESULT(EmitOpcode(Opcode::ElemDrop));
1839   CHECK_RESULT(EmitI32(TranslateElemSegmentIndexToEnv(segment_index)));
1840   return wabt::Result::Ok;
1841 }
1842 
OnTableInitExpr(Index segment_index)1843 wabt::Result BinaryReaderInterp::OnTableInitExpr(Index segment_index) {
1844   CHECK_RESULT(CheckHasTable(Opcode::TableInit));
1845   CHECK_RESULT(CheckElemSegment(segment_index));
1846   CHECK_RESULT(typechecker_.OnTableInit(segment_index));
1847   CHECK_RESULT(EmitOpcode(Opcode::TableInit));
1848   CHECK_RESULT(EmitI32(module_->table_index));
1849   CHECK_RESULT(EmitI32(TranslateElemSegmentIndexToEnv(segment_index)));
1850   return wabt::Result::Ok;
1851 }
1852 
InitializeSegments()1853 wabt::Result BinaryReaderInterp::InitializeSegments() {
1854   // The MVP requires that all segments are bounds-checked before being copied
1855   // into the table or memory. The bulk memory proposal changes this behavior;
1856   // instead, each segment is copied in order. If any segment fails, then no
1857   // further segments are copied. Any data that was written persists.
1858   enum Pass { Check = 0, Init = 1 };
1859   int pass = features_.bulk_memory_enabled() ? Init : Check;
1860 
1861   for (; pass <= Init; ++pass) {
1862     for (const ElemSegmentInfo& info : elem_segment_infos_) {
1863       uint32_t table_size = info.table->func_indexes.size();
1864       uint32_t segment_size = info.src.size();
1865       uint32_t copy_size = segment_size;
1866       bool ok = ClampToBounds(info.dst, &copy_size, table_size);
1867 
1868       if (pass == Init && copy_size > 0) {
1869         std::copy(info.src.begin(), info.src.begin() + copy_size,
1870                   info.table->func_indexes.begin() + info.dst);
1871       }
1872 
1873       if (!ok) {
1874         PrintError("elem segment is out of bounds: [%u, %" PRIu64
1875                    ") >= max value %u",
1876                    info.dst, static_cast<uint64_t>(info.dst) + segment_size,
1877                    table_size);
1878         return wabt::Result::Error;
1879       }
1880     }
1881 
1882     for (const DataSegmentInfo& info : data_segment_infos_) {
1883       uint32_t memory_size = info.memory->data.size();
1884       uint32_t segment_size = info.size;
1885       uint32_t copy_size = segment_size;
1886       bool ok = ClampToBounds(info.dst, &copy_size, memory_size);
1887 
1888       if (pass == Init && copy_size > 0) {
1889         const char* src_data = static_cast<const char*>(info.src);
1890         std::copy(src_data, src_data + copy_size,
1891                   info.memory->data.begin() + info.dst);
1892       }
1893 
1894       if (!ok) {
1895         PrintError("data segment is out of bounds: [%u, %" PRIu64
1896                    ") >= max value %u",
1897                    info.dst, static_cast<uint64_t>(info.dst) + segment_size,
1898                    memory_size);
1899         return wabt::Result::Error;
1900       }
1901     }
1902   }
1903 
1904   return wabt::Result::Ok;
1905 }
1906 
1907 }  // end anonymous namespace
1908 
ReadBinaryInterp(Environment * env,const void * data,size_t size,const ReadBinaryOptions & options,Errors * errors,DefinedModule ** out_module)1909 wabt::Result ReadBinaryInterp(Environment* env,
1910                               const void* data,
1911                               size_t size,
1912                               const ReadBinaryOptions& options,
1913                               Errors* errors,
1914                               DefinedModule** out_module) {
1915   // Need to mark before taking ownership of env->istream.
1916   Environment::MarkPoint mark = env->Mark();
1917 
1918   std::unique_ptr<OutputBuffer> istream = env->ReleaseIstream();
1919   IstreamOffset istream_offset = istream->size();
1920   DefinedModule* module = new DefinedModule();
1921 
1922   BinaryReaderInterp reader(env, module, std::move(istream), errors,
1923                             options.features);
1924   env->EmplaceBackModule(module);
1925 
1926   wabt::Result result = ReadBinary(data, size, &reader, options);
1927   env->SetIstream(reader.ReleaseOutputBuffer());
1928 
1929   if (Succeeded(result)) {
1930     module->istream_start = istream_offset;
1931     module->istream_end = env->istream().size();
1932 
1933     result = reader.InitializeSegments();
1934     if (Succeeded(result)) {
1935       *out_module = module;
1936     } else {
1937       // We failed to initialize data and element segments, but we can't reset
1938       // to the mark point. An element segment may have initialized an imported
1939       // table with a function from this module, which is still callable.
1940       *out_module = nullptr;
1941     }
1942   } else {
1943     env->ResetToMarkPoint(mark);
1944     *out_module = nullptr;
1945   }
1946 
1947   return result;
1948 }
1949 
1950 }  // namespace wabt
1951