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, ¶m_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, ¶m_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, ¶m_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, ©_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, ©_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